zoukankan      html  css  js  c++  java
  • ASP.NET Core

    一、JWT结构

     JWT介绍就太多了,这里主要关注下Jwt的结构。 

     Jwt中包含三个部分:Header(头部).Payload(负载).Signature(签名)

    • Header:描述 JWT 的元数据的JSON对象,如:

      {"alg":"HS256","typ":"JWT"}
    • Payload:一个用来存放实际需要传递的数据的JSON 对象。如:

      "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin",
          "exp": 1610877510,
          "iss": "cba",
          "aud": "cba"
      }
    • Signature:对前两部分(Header、Payload)的签名,防止数据篡改。
      HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

      JWT示例:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJleHAiOjE2MTA4Nzc1MTAsImlzcyI6ImNiYSIsImF1ZCI6ImNiYSJ9.O9lbZwfqRuA6vKcRCfYieA1zLkTPppdSvTc8UzwCkNw

    二、ASP.NET Core 使用JTW认证

     1、添加Nuget包引用:

    dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

     2、定义一个JwtSettingDto结构,用于读取JWT配置信息

    public class JwtSetting
    {
        /// <summary>
        /// 发行者
        /// </summary>
        public string Issuer { get; set; }
        /// <summary>
        /// 受众
        /// </summary>
        public string Audience { get; set; }
        /// <summary>
        /// 秘钥
        /// </summary>
        public string SecretKey { get; set; }
        /// <summary>
        /// 过期时间
        /// </summary>
        public int AccessExpiration { get; set; }
        /// <summary>
        /// 刷新时间
        /// </summary>
        public int RefreshExpiration { get; set; }
    }

     3、在appsetting.json配置文件中,添加jwt相关配置信息

      "JWTSetting": {
        "Issuer": "cba",
        "Audience": "cba",
        "SecretKey": "123456789abcdefghi",
        "AccessExpiration": 60,
        "RefreshExpiration": 80
      }

     4、在Startup.cs 中启用Jwt认证

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<JwtSetting>(Configuration.GetSection("JWTSetting"));
        var token = Configuration.GetSection("JWTSetting").Get<JwtSetting>();
        //JWT认证
        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(x =>
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(token.SecretKey)),
                ValidIssuer = token.Issuer,
                ValidAudience = token.Audience,
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });
    }
    
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseAuthentication();
        app.UseAuthorization();
    }

     5、实现认证控制器:

      a) 添加认证Dto

    public class LoginDto
    {
        [Required]
        public string Username { get; set; }
    
        [Required]
        public string Password { get; set; }
    }

      b) 实现用户校验服务:默认实现:当用户密码都等于admin通过校验  

    public interface IUserService
    {
        bool IsValid(LoginDto request);
    }
    
    public class UserService : IUserService
    {
        //本次,固定校验admin
        public bool IsValid(LoginDto request)
        {
            return request.Password == request.Username && request.Username == "admin";
        }
    }

      c) 实现签发token的认证服务:  

    //认证服务接口
    public
    interface IAuthenticateService { bool IsAuthenticated(LoginDto request, out string token); } //认证服务 public class TokenAuthenticationService : IAuthenticateService { private readonly IUserService _userService; private readonly JwtSetting _jwtSetting; public TokenAuthenticationService(IUserService userService, IOptions<JwtSetting> jwtSetting) { _userService = userService; _jwtSetting = jwtSetting.Value; } public bool IsAuthenticated(LoginDto request, out string token) { token = string.Empty; if (!_userService.IsValid(request)) return false; var claims = new[] { new Claim(ClaimTypes.Name, request.Username) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSetting.SecretKey)); var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var jwtToken = new JwtSecurityToken(_jwtSetting.Issuer, _jwtSetting.Audience, claims, expires: DateTime.Now.AddMinutes(_jwtSetting.AccessExpiration), signingCredentials: credentials); token = new JwtSecurityTokenHandler().WriteToken(jwtToken); return true; } }

      d) 添加认证控制器

    [Route("api/[controller]")]
    [ApiController]
    public class AuthenticationController : ControllerBase
    {
        private IAuthenticateService _authService;
    
        public AuthenticationController(IAuthenticateService authService)
        {
            _authService = authService;
        }
        [AllowAnonymous]
        [HttpPost, Route("RequestToken")]
        public ActionResult RequestToken([FromBody] LoginDto request)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest("Invalid Request");
            }
            string token;
            if (_authService.IsAuthenticated(request, out token))
            {
                return Ok(token);
            }
            return BadRequest("Invalid Request");
        }
    }

     6、注入服务:TokenAuthenticationService 、UserService 

    services.AddScoped<IUserService, UserService>();
    services.AddScoped<IAuthenticateService, TokenAuthenticationService>();

     7、添加测试控制器:

    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class AuditLogController : ControllerBase
    {
        // GET: api/<AuditLogController>
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
    }

         到此Jwt认证在.net core中已经实现,接下来验证下运行效果

    三、验证结果

     1、请求AuditLog接口:api/AuditLog未传入认证信息时:

      

      2、获取Token:

      

     3、添加token调用接口:

      

    四、Swagger UI添加认证

      在项目中通常都添加了Swagger UI来展示接口及基础测试,那么如果添加了认证后,如何在调用接口前添加认证信息呢?

      在Startup中:ConfigureServices中添加Swagger设置时,添加认证设置

    //注册Swagger生成器,定义一个和多个Swagger 文档
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "AuditLogDemo API", Version = "v1" });
        #region 启用swagger验证功能
        //添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称一致即可。
        c.AddSecurityRequirement(new OpenApiSecurityRequirement
        {
            {
                new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference {
                        Type = ReferenceType.SecurityScheme,
                        Id = "Bearer"
                    }
                },
                new string[] { }
            }
        });
        c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
        {
            Description = "JWT授权(数据将在请求头中进行传输) 在下方输入Bearer {token} 即可,注意两者之间有空格",
            Name = "Authorization",//jwt默认的参数名称
            In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
            Type = SecuritySchemeType.ApiKey,
            BearerFormat = "JWT",
            Scheme = "Bearer",              
                        
        });
        #endregion
    });

      运行效果: 添加token->调用需认证接口

       

           

    其他:

      源码地址:https://github.com/cwsheng/AuditLogDemo.git

  • 相关阅读:
    跃迁方法论 Continuous practice
    EPI online zoom session 面试算法基础知识直播分享
    台州 OJ 2648 小希的迷宫
    洛谷 P1074 靶形数独
    洛谷 P1433 DP 状态压缩
    台州 OJ FatMouse and Cheese 深搜 记忆化搜索
    台州 OJ 2676 Tree of Tree 树状 DP
    台州 OJ 2537 Charlie's Change 多重背包 二进制优化 路径记录
    台州 OJ 2378 Tug of War
    台州 OJ 2850 Key Task BFS
  • 原文地址:https://www.cnblogs.com/cwsheng/p/14289599.html
Copyright © 2011-2022 走看看