• AspNetCore&JWT认证授权


    有时想快速搭建一个简单应用,并集成登录功能时,总是会被认证授权绕来绕去,一直想着要搞个授权中心,却把最为简单快捷的方式抛掷脑后。

    认证与授权说来说去还是四个核心步骤,登录退出,登录有效后请求资源,请求人是谁与请求人有没有权限请求。

    图片

    JWT

    JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。其本身只是一种格式或是协议,集成到框架中,然后便按照这种格式或协议来传递信息。

    当使用认证授权时,将具有用户信息的令牌以JWT格式的呈现,命名为Id token或是Access token。

    项目准备

    准备一个Asp.Net Core 6.0的WebApi(前端实现不考虑)。按照如上几个用例挨个实现(退出用例不考虑)

    图片


    安装Nuget包

    <ItemGroup>
      <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
      <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.3" />
      <PackageReference Include="IdentityModel" Version="6.0.0" />
    </ItemGroup>
    

    生成JWT格式令牌

    增加Account控制器

    [ApiController]
    [Route("[controller]")]
    public class AccountController : ControllerBase
    {
    
    }
    

    增加JwtOption

    该部分信息用户Jwt格式中所需要的

    public class JwtOptions
    {
        public const string Name = "Jwt";
    
        public string Audience { get; set; }
        public string Issuer { get; set; }
        public double ExpiresMinutes { get; set; } = 30d;
        public Encoding Encoding { get; set; } = Encoding.UTF8;
        public string SymmetricSecurityKeyString { get; set; }
        public SymmetricSecurityKey SymmetricSecurityKey => new(Encoding.GetBytes(SymmetricSecurityKeyString));
    }
    

    服务注册

    builder.Services.Configure<AuthConfigOptions>(builder.Configuration.GetSection(AuthConfigOptions.Name));
    

    配置信息

    appsettings.json中增加该块配置

    {
      "Jwt": {
        "Audience": "http://localhost:5105",
        "Issuer": "http://localhost:5105",
        "ExpiresMinutes": 30,
        "SymmetricSecurityKeyString": "Symmetric Security Key"
      }
    }
    

    注入Option

    [ApiController]
    [Route("[controller]")]
    public class AccountController : ControllerBase
    {
        private readonly JwtOptions _jwtOptions;
    
        public AccountController(IOptionsSnapshot<JwtOptions> jwtOptions)
        {
            _jwtOptions = jwtOptions.Value;
        }
    }
    

    增加SignIn方法

    此处只模拟存在一个用户,将该用户通过Jwt格式存储信息并颁发token。

    [AllowAnonymous]
    [HttpPost("Login")]
    public IActionResult SignIn([FromBody] SignInDto dto)
    {
        //db query...
        //return Unauthorized();
    
        //user info
        var user = new UserModel()
        {
            Id = Guid.NewGuid(),
            UserName = dto.UserName,
            Email = "test@test.com"
        };
    
        // 1 定义需要的Cliam信息
        var claims = new[]
        {
            new Claim(JwtClaimTypes.Id, user.Id.ToString("N")),
            new Claim(JwtClaimTypes.Name, user.UserName),
            new Claim(JwtClaimTypes.Email, user.Email)
        };
    
        // 2 设置SecretKey
        var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtOptions.SymmetricSecurityKeyString));
    
        // 3 设置加密算法
        var algorithm = SecurityAlgorithms.HmacSha256;
    
        // 4 生成签名凭证信息
        var signingCredentials = new SigningCredentials(secretKey, algorithm);
    
        // 5 设置token过期时间
        var expires = DateTime.Now.AddMinutes(_jwtOptions.ExpiresMinutes);
    
        // 6 生成token
        var securityToken = new JwtSecurityToken(
            claims: claims,
            issuer: _jwtOptions.Issuer,
            audience: _jwtOptions.Audience,
            notBefore: DateTime.Now,
            expires: expires,
            signingCredentials: signingCredentials
        );
    
        var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
        var token = jwtSecurityTokenHandler.WriteToken(securityToken);
    
        return Ok(new { token });
    }
    

    生成token

    图片


    请求资源

    默认模板生成时自带了一个WeatherForecast控制器,此处将其作为资源,对其添加Authorize特性,控制资源。

    [ApiController]
    [Route("[controller]")]
    [Authorize]
    public class WeatherForecastController : ControllerBase
    {
      
    }
    

    因模板中管道部分默认带上了UseAuthorization,因此再次请求WeatherForecast的方法则会报错,没有为Authorization配置相关服务。
    图片

    增加服务配置

    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.RequireHttpsMetadata = false;
            options.SaveToken = true;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = false,
                ValidIssuer = jwtOptions.Issuer,
                ValidateAudience = false,
                ValidAudience = jwtOptions.Audience,
                ValidateLifetime = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SymmetricSecurityKeyString)),
            };
        });
    

    增加Authentication中间件

    app.UseAuthentication();
    

    访问资源

    图片

    Authorization中间件与Filter区别

    在控制器/方法上加Authorize特性,有相应的Filter处理是否有权限,为什么存在了一个Authorization中间件去提前验证?

    答:Filter的处理属于MVC的职责范围,而Authorization则是中间件的职责范围,可以认为是总闸与分闸。

    图片

    2022-04-17,望技术有成后能回来看见自己的脚步

  • 相关阅读:
    SGU 127. Telephone directory --- 模拟
    SGU 126. Boxes --- 模拟
    SGU 128. Snake --- 暴力枚举+并查集+贪心+计算几何
    Codeforces Round #246 (Div. 2) B. Football Kit
    Codeforces Round #252 (Div. 2) C. Valera and Tubes
    Codeforces Round #251 (Div. 2) C. Devu and Partitioning of the Array
    codeforces --- Round #250 (Div. 2) B. The Child and Set
    codeforces --- Round #250 (Div. 2) A. The Child and Homework
    AFNetworking 动态修改acceptableContentTypes 设置ContentType
    swift pod第三方OC库使用use_frameworks!导致#import提示无法找到头文件
  • 原文地址:https://www.cnblogs.com/CKExp/p/16157439.html
Copyright © 2020-2023  润新知