• 前后端分离项目中的jwt令牌应用


    做为前后端分离项目中,授权认证常用token令牌做为身份认证的方式,对于jwt令牌的获取、验证、解析以及存储,分别示例如下:

    需要安装两个nuget包,分别为:IdentityModel和Microsoft.AspNetCore.Authentication.JwtBearer

    1、JWT令牌生成及获取

                        //写Session或Cookies换成JWT
    
    
                        IList<Claim> claims = new List<Claim> {
                            new Claim(JwtClaimTypes.Id,admin.AdminId.ToString()),
                            new Claim(JwtClaimTypes.Name,loginDto.UserName),
                            new Claim(JwtClaimTypes.Email,loginDto.UserName),
                            new Claim(JwtClaimTypes.Role,string.Join(",", ""))
                        };
    
                        //JWT密钥
                        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtConfig:Bearer:SecurityKey"]));
    
                        //算法
                        var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    
                        //过期时间
                        DateTime expires = DateTime.UtcNow.AddHours(10);
    
    
                        //Payload负载
                        var token = new JwtSecurityToken(
                            issuer: configuration["JwtConfig:Bearer:Issuer"],
                            audience: configuration["JwtConfig:Bearer:Audience"],
                            claims: claims,
                            notBefore: DateTime.UtcNow,
                            expires: expires,
                            signingCredentials: cred
                            );
    
                        var handler = new JwtSecurityTokenHandler();
    
                        //生成令牌
                        string jwt = handler.WriteToken(token);

    2、JWT验证部分

    JWT在Startup中的配置,主要用来使用固定的配置密钥对JWT的Token进行有效性验证。

                //数据库连接
                services.AddDbContext<SmsDBContext>(action => {
                    action.UseSqlServer(Configuration.GetConnectionString("Default"));
                });
    
                services.AddCors(option =>
                {
                    option.AddDefaultPolicy(policy =>
                    {
                        //对应客户端withCredentials,需要设置具体允许的域名
                        policy.WithOrigins("http://web.a.com:88").AllowCredentials();
                        policy.AllowAnyMethod();
                        policy.AllowAnyHeader();
                    });
                });
    
                services.AddAuthentication(option => {
                    option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                }).AddJwtBearer(
                    option => {
                        option.TokenValidationParameters = new TokenValidationParameters
                        {
                            //是否验证发行人
                            ValidateIssuer = true,
                            ValidIssuer = Configuration["Authentication:JwtBearer:Issuer"],//发行人
    
                            //是否验证受众人
                            ValidateAudience = true,
                            ValidAudience = Configuration["Authentication:JwtBearer:Audience"],//受众人
    
                            //是否验证密钥
                            ValidateIssuerSigningKey = true,
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Authentication:JwtBearer:SecurityKey"])),
    
                            ValidateLifetime = true, //验证生命周期
    
                            RequireExpirationTime = true, //过期时间
    
                            ClockSkew = TimeSpan.Zero   //平滑过期偏移时间
                        };
                    }
                );

    另外,还需要配置相应的认证中间件和授权中间件

            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                    app.UseSwagger();
                    string ApiName = "Rbac.Core";
                    app.UseSwaggerUI(c =>
                    {
                        c.SwaggerEndpoint("/swagger/V1/swagger.json", $"{ApiName} V1");
                        c.SwaggerEndpoint("/swagger/gp/swagger.json", "登录模块");
                        c.SwaggerEndpoint("/swagger/mom/swagger.json", "业务模块");
                        c.SwaggerEndpoint("/swagger/dm/swagger.json", "其他模块");
    
                        //路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,去launchSettings.json把launchUrl去掉,如果你想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "doc";
                        c.RoutePrefix = "";
                    });
                }
    
                //app.UseHttpsRedirection();
    
                //静态文件中间件
                app.UseStaticFiles();
    
                //路由中间件
                app.UseRouting();
    
                //跨域
                app.UseCors();
    
                //认证中间件
                app.UseAuthentication();
    
                //授权中间件
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }

    经过上面配置,可以完成JWT令牌的生成及校验。

    3、前端Axios的令牌保存及请求授权接口

    前端接收到Api接口返回的token令牌后,应该把token保存起来,保存的位置可以是localStorage或sessionStorage,当访问授权接口时,从localStorage或sessionStorage中取出令牌,通过HTTP请求头进行访问。

    import router from '../router'
    import axios from 'axios'
    let baseUrl = "http://localhost:5000/api";
    
    axios.defaults.baseURL = baseUrl;
    axios.defaults.headers.common['Authorization'] = `bearer ${localStorage.getItem('token')}`;
    
    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
        // 对响应数据做点什么
        return response;
      }, function (error) {
        router.push("/");
        return Promise.reject(error);
      });
    
    export default {
        baseUrl,
        axios
    }

     4、Swagger中的权限小锁配置

                    //开启权限小锁
                    options.OperationFilter<AddResponseHeadersFilter>();
                    options.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
                    options.OperationFilter<SecurityRequirementsOperationFilter>();
    
                    //在header中添加token,传递到后台
                    options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
                    {
                        Description = "JWT授权(数据将在请求头中进行传递)直接在下面框中输入Bearer {token}(注意两者之间是一个空格) \"",
                        Name = "Authorization",//jwt默认的参数名称
                        In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
                        Type = SecuritySchemeType.ApiKey
                    });
  • 相关阅读:
    Ubuntu 15.04 开机无法进入图形界面,自动进入emergency mode解决方法
    Docker常用命令
    安装mongodb时报错 configure: error: Cannot find OpenSSL's libraries
    Invalid command 'Header', perhaps misspelled or defined by a module not included in the server configuration
    mysql varchar类型转换int类型
    elasticsearch 安装 head插件
    解决linux下root运行Elasticsearch异常
    PHP 数组中出现中文乱码,json_encode返回结果为null 或false
    Git命令_git remote与远程仓库管理
    Git命令_git clone和git fork的区别以及pull request含义
  • 原文地址:https://www.cnblogs.com/superfeeling/p/16007915.html
Copyright © 2020-2023  润新知