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

  • 相关阅读:
    django自学
    Oracle
    Linux查看日志常用命令
    Appium使用
    jmeter性能测试
    数据库连接
    redis相关
    ubuntu系统软件安装以及相关命令
    LINUX远程强制重启/proc/sys/kernel/sysrq /proc/sysrq-trigger
    sqlserver查询表大小
  • 原文地址:https://www.cnblogs.com/cwsheng/p/14289599.html
Copyright © 2011-2022 走看看