自定义Token失效或过期的响应处理以及Bearer名称或者取消授权时要输入的前缀

问题点:
1:我们在Swagger授权时往往要输入前缀,感觉比较麻烦

2:Token过期,前端页面没有跳转只是抛一个异常,需要刷新一下再登录才行,体验差

 private const string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

 public void ConfigureServices(IServiceCollection services)
 { 
   services.AddAddCorsInfo(MyAllowSpecificOrigins);//允许跨域
   services.AddAuthorizationSetup(Configuration);//添加验证服务,jwt授权验证
   services.AddSwaggerGenTask(); //配置Swagger
 }

主要代码如下:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;

using QzjcService.Models;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QzjcService.SetUp
{
    public static class AuthorizationSetup
    {
        public static void AddAuthorizationSetup(this IServiceCollection services, Microsoft.Extensions.Configuration.IConfiguration configuration)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));

            // 1【授权】、这个和上边的异曲同工,好处就是不用在controller中,写多个 roles 。
            // 然后这么写 [Authorize(Policy = "Admin")]
            services.AddAuthorization(options =>
            {
                options.AddPolicy("User", policy => policy.RequireRole("User").Build());
                options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System"));

            });

            //读取配置文件
            var symmetricKeyAsBase64 = configuration["Jwt:key"];
            var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
            var signingKey = new SymmetricSecurityKey(keyByteArray);
            var Issuer = configuration["Jwt:issuer"];
            var Audience = configuration["Jwt:audience"];

            // 令牌验证参数
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,
                ValidateIssuer = true,
                ValidIssuer = Issuer,//发行人
                ValidateAudience = true,
                ValidAudience = Audience,//订阅人
                ValidateLifetime = true,
                ClockSkew = TimeSpan.FromSeconds(30),
                RequireExpirationTime = true,
            };

            //2.1【认证】、core自带官方JWT认证
            // 开启Bearer认证
            services.AddAuthentication(o =>
            {
                o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
             // 添加JwtBearer服务
             .AddJwtBearer(o =>
             {
                 o.TokenValidationParameters = tokenValidationParameters;
                 o.Events = new JwtBearerEvents
                 {
                     OnAuthenticationFailed = context =>
                     {
                         // 如果过期,则把<是否过期>添加到,返回头信息中
                         //if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                         //{
                         //    context.Response.Headers.Add("Token-Expired", "true");
                         //}
                         if (!context.Response.Headers.Any(c => c.Key.Contains("Access-Control-Allow-Origin")))
                             context.Response.Headers.Add("Access-Control-Allow-Origin", "*");//这里需要处理一下
                         context.Response.Headers.Add("Token-Expired", "true");
                         context.Response.Headers.Add("LmzTokenValide", "false");
                         return Task.CompletedTask;
                     },
                     OnMessageReceived = recevied =>
                     {
                         var headStr = recevied.HttpContext.Request.Headers[ConstData.Authorization].ToString();
                         if (!headStr.IsNonOrEmpty())
                         {
                             if (!headStr.Contains(ConstData.TokenBearer))//处理 不输入 Bearer会自动加上
                             {
                                 string autoAuthHead = $"{ConstData.TokenBearer}{headStr}";
                                 recevied.HttpContext.Request.Headers.Remove(ConstData.Authorization);
                                 recevied.HttpContext.Request.Headers.Add(ConstData.Authorization, autoAuthHead);
                             }
                         }
                         return Task.CompletedTask;
                     }
                 };
             });
        }
    }
}

允许跨域等

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace QzjcService.ServicesExtend.CorsInfo
{
    public static class AddCorsInfo
    {
        /// <summary>
        /// IServiceCollection 扩展函数
        /// </summary>
        /// <param name="services"></param>
        /// <param name="MyAllowSpecificOrigins"></param>
        public static void AddAddCorsInfo(this IServiceCollection services,string MyAllowSpecificOrigins)
        {

            //允许跨域
            services.AddCors(options =>
            {
                options.AddPolicy(MyAllowSpecificOrigins, builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("Token-Expired").WithExposedHeaders("LmzTokenValide") );
            });

        }
    }
}

启用中间件服务生成Swagge

            app.UseSwagger();
            //启用中间件服务生成SwaggerUI,指定Swagger JSON终结点
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "Web App V1");
                //c.SwaggerEndpoint("v1/swagger.json", "Web App V1");
                c.RoutePrefix = string.Empty;//设置根节点访问
            });

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
            });

配置Swagger

using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace QzjcService.ServicesExtend.SwaggerInfo
{
    public static class SwaggerGenTask
    {
        /// <summary>
        /// IServiceCollection 扩展函数
        /// </summary>
        /// <param name="services"></param>
        public static void AddSwaggerGenTask(this IServiceCollection services)
        {
            //配置Swagger
            //注册Swagger生成器,定义一个Swagger 文档
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
                {
                    Version = "v1",
                    Title = "**平台接口文档",
                    Description = "***大数据平台接口文档"
                });
                // 为 Swagger 设置xml文档注释路径
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);

                // 在header中添加token,传递到后台
                c.OperationFilter<SecurityRequirementsOperationFilter>();

                //region Token绑定到ConfigureServices,swagger右上角显示Token输入框
                c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
                {
                    Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
                    Name = "Authorization",//jwt默认的参数名称
                      In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
                    Type = SecuritySchemeType.ApiKey
                });
            });            

        }
    }
}

通常我们的网站过期时间过长,修改时间太短再发布到服务器会影响到其他使用的使用,我们可以这样处理:

 

 

 

 

 

此时页面就方便跳转了,需要注意的跨域那块需要处理不然页面拿不到信息

 

 

 

 

  

posted @ 2022-05-25 16:21  天天向上518  阅读(1210)  评论(0编辑  收藏  举报