net6 swagger与IdentityServer集成登录验证,完美解决调试、部署等问题

网上很多教程的结果是这样的,用postman获取token,再复制到下图value进行登录,这样的方式感觉有点呆。

理想的状态是跳到登录界面,实现集成登录验证,如图

自动跳转到登录界面

登录后再自动跳转到swgger

实现步骤

1、NuGet包添加Swashbuckle.AspNetCore

 

自定义鉴权中间件SetupAuthenticationMiddleware

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace Kstopa.Extensions.Middlewares
{
    public static class SetupAuthenticationMiddleware
    {
        public static void AddAuthenticationSetup(this IServiceCollection services, IConfiguration configuration)
        {
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.Authority = configuration["AuthServer:Authority"];
                options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
                options.Audience = "KstopaAcs";
                options.TokenValidationParameters = new()
                {
                    ValidateAudience = false,
                    ValidateIssuerSigningKey = true,
                    ValidateIssuer = false,
                    LifetimeValidator = (before, expires, token, param) =>
                    {
                        return expires > DateTime.UtcNow;
                    }
                };
            });
 // API授权
            services.AddAuthorization(options =>
            {
                options.AddPolicy("ApiScope", policy =>
                {
                    policy.RequireAuthenticatedUser();
                    policy.RequireClaim("scope", "KstopaAcs");
                });
            });
        }
    }
}

 自定义SetupSwaggerGenMiddleware中间件

代码如下(ApiGroup与DescriptionAttribute类不建议到中间件里,ApiGroup是定义的分组)

关键代码:Flows使用Implicit类型,不要使用AuthorizationCode

using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;

namespace Kstopa.Extensions.Middlewares
{
public static class SetupSwaggerGenMiddleware
{
public static IServiceCollection AddSwaggerGenSetup(this IServiceCollection services, Action<SwaggerGenOptions> setupAction = null)
        {
            return services.AddSwaggerGen(delegate (SwaggerGenOptions options)
            {
                Func<OpenApiSchema> schemaFactory = () => new OpenApiSchema
                {
                    Type = "string",
                    Format = "binary"
                };
                setupAction?.Invoke(options);
            });
        }
public static IServiceCollection AddSwaggerGenWithOAuthSetup(this IServiceCollection services, string authority,
                Dictionary<string, string> scopes, Action<SwaggerGenOptions> setupAction = null)
        {
            return services.AddSwaggerGenSetup().AddSwaggerGen(delegate (SwaggerGenOptions options)
            {
                options.OperationFilter<SecurityRequirementsOperationFilter>();
                options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
                    {
                        Type = SecuritySchemeType.OAuth2,
                        Flows = new OpenApiOAuthFlows
                        {
                            Implicit = new OpenApiOAuthFlow
                            {
                                AuthorizationUrl = new Uri(authority + "connect/authorize"),
                                Scopes = scopes,
                                TokenUrl = new Uri(authority + "connect/token")
                            }
                        }
                    });
options.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "oauth2"
                            }
                        },
                        Array.Empty<string>()
                    }
                });
                setupAction?.Invoke(options);
            });
        }
 /// <summary>
        /// 添加Xml注释
        /// </summary>
        /// <param name="options"></param>
        public static void AddXmlComments(this SwaggerGenOptions options)
        {
            var basePath = AppContext.BaseDirectory;

            #region Controller的注释
            {
                var xmlPath = Path.Combine(basePath, "Kstopa.HttpApi.Host.xml");
                if (File.Exists(xmlPath))
                {
                    options.IncludeXmlComments(xmlPath, true);//第二参数要设为true,默认为false
                }
            }
            #endregion

            #region Model的注释
            {
                var xmlModelPath = Path.Combine(basePath, "Kstopa.Model.xml");
                if (File.Exists(xmlModelPath))
                {
                    options.IncludeXmlComments(xmlModelPath);//第二参数默认为false,不用设
                    options.CustomSchemaIds(type => type.ToString());
                }
            }
            #endregion
        }
/// <summary>
        /// 按模块分组
        /// </summary>
        /// <param name="options"></param>
        public static void GroupByModule(this SwaggerGenOptions options)
        {
            #region 按模块分组显示
            {
                var fields = typeof(ApiGroup).GetFields().ToList();
                fields.ForEach(f =>
                {
                    var info = f.GetCustomAttributes(typeof(DescriptionAttribute), false)
                        .OfType<DescriptionAttribute>()
                        .FirstOrDefault();
                    options.SwaggerDoc($"{f.Name}", new OpenApiInfo
                    {
                        Title = $"{info?.Title} 接口文档-{RuntimeInformation.FrameworkDescription}",
                        Version = $"{info?.Version}",
                        Description = $"版本:{info?.Version} <br>{info?.Remark}"
                    });
                    options.OrderActionsBy(o => o.RelativePath);
                });
            }
#endregion

            #region 无分组归类显示
            {
                options.SwaggerDoc("无分组", new OpenApiInfo
                {
                    Title = $"接口文档——{RuntimeInformation.FrameworkDescription}",
                    Version = "v1",
                    Description = "Kstopa MES HTTP API v1"
                });
                options.DocInclusionPredicate((docName, description) =>
                {
                    if (docName.Equals("NoGroup"))
                    {
                        return string.IsNullOrEmpty(description.GroupName);
                    }
                    return description.GroupName == docName;
                });
            }
            #endregion
        }
    }
                    
      public class ApiGroup
    {
        [Description(Title = "系统通用", Remark = "导入(出)、定时任务、缓存、消息队列")]
        public static string Common_v1;

        [Description(Title = "系统框架", Remark = "组织、部门、用户、角色、权限、登录、枚举")]
        public static string Framework_v1;
    } 
public class DescriptionAttribute : Attribute
    {
        /// <summary>
        /// 标题
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }

        /// <summary>
        /// 版本
        /// </summary>
        public string Version { get; set; } = "v1";
    }        
}

 在Program.cs使用中间件

 #region Authentication 鉴权设置
        {
            builder.Services.AddAuthenticationSetup(builder.Configuration);
            IdentityModelEventSource.ShowPII = true;//解决IDX10214: Audience validation failed. Audiences: '[PII is hidden]'错误
            builder.Services.AddHttpContextAccessorSetup();
        }
        #endregion
      builder.Services.AddCorsSetup(builder.Configuration);//跨域配置
        builder.Services.AddEndpointsApiExplorer();
        builder.Services.AddSwaggerGenWithOAuthSetup(
            builder.Configuration["AuthServer:Authority"],
            new Dictionary<string, string>
            {
                {"KstopaAcs", "KstopaAcs API"}
            },
            options =>
            {
                options.GroupByModule();
                options.AddXmlComments();
                options.CustomSchemaIds(type => type.FullName);
            });

配置文件代码

 "App": {
    "CorsOrigins": "https://*.KstopaAcs.com",
    "RegisterModule": "Kstopa.Service.dll",
    "StaticFilePath": "doc"
  },
  "AuthServer": {
    "Authority": "https://192.168.18.13:9081/",
    "RequireHttpsMetadata": false,
    "SwaggerClientId": "Kstopa",
    "SwaggerClientSecret": "xxxx"
  }

如下图

 

IdentityServer配置

RedirectUris为api服务地址+swagger/oauth2-redirect.html,如下图

可能会遇到的问题如下:

本机调试和服务器同时使用,只要在IdentityServer配置文件中添加多个RedirectUris即可

 跳到在登录界面录入帐号和密码后不跳转,必须使用https才可以,https需要证书请参考这里

使用 mkcert 解决 局域网IIS 网页 SSL 证书问题 - googlegis - 博客园

安装证书后,浏览器的安全锁如下图是正常的(客户端和服务器都要安装crt证书,按上图链接操作

 如果前端请求提示:IDX20803,一般是证书导致的问题(服务器没有安装证书)

证书加载代码:

 var cert = new X509Certificate2(builder.Configuration["cert:path"], builder.Configuration["cert:password"]);
    builder.Services.Configure<KestrelServerOptions>(options =>
    {
        options.ConfigureHttpsDefaults(c =>
        {
            c.ServerCertificate = cert;
        });
    }

 

如果有问题请加微信讨论:25489181

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神色自若

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值