当前位置: 首页>前端>正文

.NET Web API+IIS+Windows验证

一、需求背景

1、针对公司内部系统构建提供业务数据的API接口,分发给业务人员做自助数据分析。
2、业务人员通过PowerQuery、PowerBI连接API接口完成数据消费。
3、通过Windows鉴权完成权限管理。额外创建一套Basic鉴权会重复编码且用户体验不好。
4、BI或Excel连接API接口无需使用JWT方法、内部系统也无需过多考虑安全问题,所有选择Windows鉴权。

二、本文内容

1、来源于微软官方文档:在 ASP.NET Core 中配置 Windows 身份验证
2、本文内容对比官方文档并不全面。也有一些坑的补充。

三、配置

1、Program.cs。两个注意点的一定要看仔细的

.NET Web API+IIS+Windows验证,第1张
  • 代码配置
// ---window鉴权配置
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});
// ---
var app = builder.Build();
  • 注意1:配置代码要在var app..前面,否则报错。在ASP.NET Core 中,builder.Build()方法用于创建并构建应用程序的主机。该方法之后的代码将在应用程序运行之前执行。而在鉴权配置的情况下,它需要在应用程序启动之前完成以确保正确的身份验证和授权机制。

    .NET Web API+IIS+Windows验证,第2张
  • 注意2:如果Program.cs中已经有了 app.UseRouting() 和 app.UseEndpoints(...) 的调用,则必须在它们之间添加 app.UseAuthorization()。否则配置了Authorize的Controller,在测试环境可以正常调用,在线上环境就会报500(500 Internal Server Error)。且只能通过日志信息得知。


    .NET Web API+IIS+Windows验证,第3张

    .NET Web API+IIS+Windows验证,第4张

2、关于3点和4点的说明

  • 同一个项目中,有时候会要实现:部分接口通过鉴权才能访问,部分接口可以直接匿名访问。并不是所有接口都要参与鉴权。

3、生产环境中(IIS中)配置身份验证。两种方式:可视化的修改、按照配置文件的修改

  • 可视化修改:官方文档给出的参考是开启Windows身份认证、关闭匿名验证。可以看到我的配置中,将匿名访问和Windows身份验证都启用了,因为我要实现项目中部分接口不需要通过Windows鉴权即可访问(Controller的方法参不参与windows鉴权,需要通过特性标注实现,详见4点)。

    .NET Web API+IIS+Windows验证,第5张

    .NET Web API+IIS+Windows验证,第6张

    .NET Web API+IIS+Windows验证,第7张
  • 如果项目里面有需要鉴权和不需要鉴权的接口,那匿名访问和windows验证都需要开启,如果只开windows验证会报500错误(HTTP Error 500.30 - ASP.NET Core app failed to start)。

.NET Web API+IIS+Windows验证,第8张
  • 配置文件中修改:官方也给出了在项目根目录中配置web.config文件的方式,这种感觉坑很多,建议不使用,直接在IIS中可视化配置。

    .NET Web API+IIS+Windows验证,第9张
  • 测试环境中(IIS Express中)开启windows身份校验。也和IIS中开启身份校验一样,有两种方式,一种是改配置文件,一种是通过可视化的方式更改。其实就是一个东西,可视化修改,配置文件中的内容也会自动变动。


    .NET Web API+IIS+Windows验证,第10张
    可视化修改第一步

    .NET Web API+IIS+Windows验证,第11张
    可视化修改第二部

    .NET Web API+IIS+Windows验证,第12张
    launchSettings.json文件(配置文件)

4、如2所说,3中配置,如何设置哪些接口通过鉴权、哪些接口不通过鉴权?(以下呢内容基于3中的配置验证得知)

  • 命名空间:Microsoft.AspNetCore.Authorization

  • [Authorize]表示当前接口的方法需要Windows验证、[AllowAnonymous]表示当前接口方法可以匿名访问

  • Authorize和AllowAnonymous可以标注在Controller上,也可以标注在Controller的方法上

  • 不标注Authorize和AllowAnonymous,需要windows验证

  • Controller标注Authorize,action标注AllowAnonymous,那么这个action可以匿名访问
    ....还有一些其它的组合,大家可以尝试下,这块比较绕的

  • 代码:BasicDataMaintenanceController中的方法需要鉴权、TestController中的方法不需要鉴权


    .NET Web API+IIS+Windows验证,第13张

    .NET Web API+IIS+Windows验证,第14张

四、访问API进行验证

1、访问配置了[Authorize]的接口的方法,会弹出来登录框。否则报错401。


.NET Web API+IIS+Windows验证,第15张

五、在代码中获取当前访问的人的域账号

1、在接口中:

        [HttpGet]
        [ApiCode("当前访问用户GID账号")]
        public ActionResult<String> GetCurrentUser()
        {
            string gid = User.Identity.Name.Split('\')[1];
            return gid;
        }
.NET Web API+IIS+Windows验证,第16张

2、在Filter中(切面编程),可以获取到当前请求人的GID,然后进行权限上的逻辑校验


.NET Web API+IIS+Windows验证,第17张

六、对Swagger页面配置Windows鉴权,并且访问Swagger登陆Windows后,登陆的账号可作为访问api的请求头内容。

1、通过中间件实现
2、中间件代码

namespace JCH_GC.Helpers
{
    /// <summary>
    /// 打开Swagger页面鉴权
    /// </summary>
    public class AuthorizeSwaggerAccessMiddleware
    {
        private readonly RequestDelegate next;
        public AuthorizeSwaggerAccessMiddleware(RequestDelegate next)
        {
            this.next = next;
        }
        public async Task InvokeAsync(HttpContext context)
        {
            if (context.Request.Path.StartsWithSegments("/swagger")) // 只有打开界面 的链接是 swagger结尾的才使用鉴权
            {
                // 在此处进行身份验证逻辑
                // ...
                if (!string.IsNullOrEmpty(context.User.Identity.Name))
                {
                    // 这里使用 Windows 身份验证鉴权的方式进行判断
                    if (context.User.Identity.Name.Split('\')[1] != "admin") // 判断是不是管理员
                    {
                        context.Response.StatusCode = 401;
                        await context.Response.WriteAsync("Unauthorized");
                    }
                    else
                    {
                        await next(context);
                    }
                }
                else
                {
                    context.Response.StatusCode = 401;
                    await context.Response.WriteAsync("Unauthorized");
                }
            }
            else
            {
                await next(context);
            }

        }
    }
}

3、Program.cs中代码配置

app.UseSwagger();
app.UseSwaggerUI(c=>
{
    app.UseMiddleware<AuthorizeSwaggerAccessMiddleware>();
});
.NET Web API+IIS+Windows验证,第18张

4、在Swagger中访问接口,测试登陆Swagger页面的账号是作为了请求头的内容

  • 访问有权限接口


    .NET Web API+IIS+Windows验证,第19张
  • 访问没权限接口:它返回的报错信息中,显示的是我登陆Swagger页面的windows账号


    .NET Web API+IIS+Windows验证,第20张
  • 所以这里测试用也非常方便,相比较Identity鉴权要在Program.cs中配置很多信息而言

七、在PostMan中访问需要Windows鉴权的API

1、打开Postman并创建一个新的请求。
2、点击请求头部分下方的“Authorization”选项卡。
3、选择“Type”选项卡,然后从下拉列表中选择“NTLM”。
在“Username”和“Password”字段中输入Windows域用户的凭据。

4、
.NET Web API+IIS+Windows验证,第21张

八、在Python中访问需要Windows鉴权的API

import requests
from requests_ntlm import HttpNtlmAuth

url = 'http://1111/api/jch_gc/GetU8CurrentStockFinalProduct'
username = 'xx'
password = 'xxx'
domain = "xxx"

# Create a session object with NTLM authentication
session = requests.Session()
session.auth = HttpNtlmAuth(f'{domain}\{username}', password)

# Send a GET request to the API endpoint
response = session.get(url)

# Check the response status code
if response.status_code == 200:
    # Do something with the API response
    print(response.json())
else:
    print("Failed to access API. Status code:", response.status_code)


https://www.xamrdz.com/web/2yw1994135.html

相关文章: