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

  • 相关阅读:
    JavaScript cookie详解
    Javascript数组的排序:sort()方法和reverse()方法
    javascript中write( ) 和 writeln( )的区别
    div做表格
    JS 盒模型 scrollLeft, scrollWidth, clientWidth, offsetWidth 详解
    Job for phpfpm.service failed because the control process exited with error code. See "systemctl status phpfpm.service" and "journalctl xe" for details.
    orm查询存在价格为空问题
    利用救援模式破解系统密码
    SSH服务拒绝了密码
    C# 调用 C++ DLL 中的委托,引发“对XXX::Invoke类型的已垃圾回收委托进行了回调”错误的解决办法
  • 原文地址:https://www.cnblogs.com/cwsheng/p/14289599.html
Copyright © 2011-2022 走看看