• Asp.Net Core: Swagger 与 Identity Server 4


    Swagger不用多说,可以自动生成Web Api的接口文档和客户端调用代码,方便开发人员进行测试。通常我们只需要几行代码就可以实现这个功能:

    ...
    builder.Services.AddSwaggerGen();
    ...
    app.UseSwagger();
    app.UseSwaggerUI();
    ...
    

    可如果使用Identity Server 4等认证服务对Web Api进行保护后,使用上面代码生成的Web Api文档就无法工作了,在进行测试时会提示401错误。

    本文介绍如何使Swagger在Identity Server 4认证服务保护下工作。

    配置Identity Server 4

    首先,使用开源的Identity Server 4 Admin搭建认证服务,这部分工作在系列文章《Identity Server 4 从入门到落地》中有详细的介绍,这里不再重复。

    准备测试用Web Api

    接下来,使用Visual Studio 2022创建一个Asp.Net Core Web Api项目,我们使用项目中缺省的Web Api进行测试。在项目中增加Identity Server 4对Web Api的保护,这部分的详细介绍参见《Identity Server 4 从入门到落地(十)—— 编写可配置的客户端和Web Api》,这里只列出必要的步骤。
    1、使用Nuget包管理器安装ZL.IdentityServer4ClientConfig和ZL.SameSiteCookiesService
    2、修改Program.cs,增加如下代码:

    ...
    builder.Services.AddIdentityServer4Api(builder.Configuration);//增加代码
    builder.Services.AddSameSiteSupport();;//增加代码
    ...
    app.UseCors("cors");//增加代码
    app.UseAuthentication(); //增加代码
    app.UseAuthorization();
    

    3、在appSettings.json中增加相应的配置:
    "IdentityServer4Api": {
    "Authority": "http://host.docker.internal:4010",
    "CorsOrgins": [
    "http://host.docker.internal:5291"
    ],
    "Policies": [
    {
    "Name": "ApiScope",
    "RequireAuthenticatedUser": "true",
    "Claims": [
    {
    "ClaimType": "scope",
    "AllowValues": [ "testapi" ]
    }
    ]
    }
    ],
    这里定义的认证服务器地址需要根据实际情况进行修改,CorsOrgins中设置的是允许访问的客户端的Uri。这里定义的允许访问的scope是testapi,需要根据实际进行修改。
    4、为Web Api的Action增加[Authorize]标签:

            [Authorize]
            [HttpGet(Name = "GetWeatherForecast")]
            public IEnumerable<WeatherForecast> Get()
            {
                return Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = Random.Shared.Next(-20, 55),
                    Summary = Summaries[Random.Shared.Next(Summaries.Length)]
                })
                .ToArray();
            }
    

    在认证中心增加Web Api Scope和Swagger Client

    现在我们在认证中心增加Web Api Scope和Swagger Client。
    首先,增加Web Api Scope,在配置文件中定义的允许访问的scope是testapi,所以在这里增加的Scope名称必须为testapi。

    然后,还需要为Swagger 增加一个客户端,名称为demo_api_swagger:

    客户端定义中有几个地方需要注意,首先是允许作用域必须与前面定义的相同,这里是testapi:

    需要客户端密钥设置为false:

    还有重定向的Url,Swagger针对oauth 2.0的重定向地址是swagger/oauth2-redirect.html

    最后,不要忘记在令牌分页中设置CORS:

    修改Swagger相关代码

    在认证中心设置完成后,还需要修改Web Api项目中Swagger相关的代码,使Swagger支持认证。
    首先需要增加一个类,实现IOperationFilter接口:

    using Microsoft.AspNetCore.Authorization;
    using Microsoft.OpenApi.Models;
    using Swashbuckle.AspNetCore.SwaggerGen;
    
    namespace WebApiIDS4Demo
    {
        public class AuthorizeCheckOperationFilter : IOperationFilter
        {
            public void Apply(OpenApiOperation operation, OperationFilterContext context)
            {
                var hasAuthorize =
                  context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any()
                  || context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();
    
                if (hasAuthorize)
                {
                    operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
                    operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
    
                    operation.Security = new List<OpenApiSecurityRequirement>
                {
                    new OpenApiSecurityRequirement
                    {
                        [
                            new OpenApiSecurityScheme {Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "oauth2"}
                            }
                        ] = new[] {"api1"}
                    }
                };
    
                }
            }
        }
    }
    
    

    然后,在Program.cs中修改Swagger相关的代码:

    ...
    builder.Services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc("v1", new OpenApiInfo { Title = "Protected API", Version = "v1" });
        var strurl = builder.Configuration["IdentityServer4Api:Authority"];
        options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
        {
            Type = SecuritySchemeType.OAuth2,
            Flows = new OpenApiOAuthFlows
            {
                AuthorizationCode = new OpenApiOAuthFlow
                {
                    AuthorizationUrl = new Uri( strurl +"/connect/authorize"),
                    TokenUrl = new Uri(strurl + "/connect/token"),
                    Scopes = new Dictionary<string, string>
                {
                    {"testapi", "Demo API - full access"}
                }
                }
            }
        });
        options.OperationFilter<AuthorizeCheckOperationFilter>();
    });
    ...
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI(options =>
        {
            options.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            options.OAuthClientId("demo_api_swagger");
            options.OAuthAppName("Demo API - Swagger");
            options.OAuthUsePkce();
        });
    }
    

    改造完成,可以进行测试了,运行Web Api项目,缺省进入Swagger文档页面,我们会发现多了一个Authorize按钮,并且Web Api方法旁边会有一个加锁的图标:

    这时,如果访问Web Api,会出现401错误,我们需要先进行认证再访问,点击加锁的图标,弹出认证界面:

    点击认证按钮,如果顺利的话,会出现认证完成的界面:

    点击Close关闭窗口,会发现加锁图标发生了变化:

    这时,再次访问Web Api就可以正常返回数据了:

  • 相关阅读:
    C# 图片与Base64的相互转化
    LeetCode 303. Range Sum Query – Immutable
    LeetCode 300. Longest Increasing Subsequence
    LeetCode 292. Nim Game
    LeetCode 283. Move Zeroes
    LeetCode 279. Perfect Squares
    LeetCode 268. Missing Number
    LeetCode 264. Ugly Number II
    LeetCode 258. Add Digits
    LeetCode 257. Binary Tree Paths
  • 原文地址:https://www.cnblogs.com/zhenl/p/15917978.html
Copyright © 2020-2023  润新知