基于 JWT Bearer 的身份认证方案

基于 JWT Bearer 的身份认证方案

认证流程

  1. 匿名访问资源,server 响应 401
  2. client 跳转至登录页面
  3. client 请求 RSA 公钥,用户输入账号、密码
  4. client 对密码执行 RSA 加密,请求 login
  5. server 验证账号、密码,通过之后,签发包含用户标识的 JWT
  6. client 使用 JWT 设置 Authorization,scheme type 为 Bearer
  7. server 验证 JWT 是否合法,是否过期,验证通过后,完成身份认证

密码安全

不存储原始的明文密码

  1. client 对密码执行 RSA 加密,然后传递密文
  2. server 使用私钥对密码进行解密,成功之后,结合数据库中记录的 salt 验证密码的 MD5

关键实现

JWT Authentication

引用 package Microsoft.AspNetCore.Authentication.JwtBearer

配置 Authentication Scheme

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options => 
            {
                // your configuration
            });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();

        // after routing, so that route information is available for authentication decisions
        app.UseAuthentication();

        // after authentication
        app.UseAuthorization();

        app.UseEndpoints();
    }
}

生成 JWT

public string GenerateToken(string userId)
{
    var claims = new Claim[]
    {
        new Claim(ClaimTypes.NameIdentifier, "Your_Identitier"),
        //add any claim
    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Your_SecurityKey"));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var token = new JwtSecurityToken(
        issuer: ,
        audience: ,
        signingCredentials: creds,
        claims: claims,
        notBefore: ,
        expires: 
    );

    return new JwtSecurityTokenHandler().WriteToken(token);
}

获取身份信息

var value = context?.User?.Claims
    ?.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)
    ?.Value;

RSA Encryption and Decryption

为保证跨平台,使用第三方的 package XC.RSAUtil


public static string RSAEncrypt(string publicKey, string dataToEncrypt)
{
    using var rsa = new RsaPkcs1Util(Encoding.UTF8, publicKey, null, 1024);
    return rsa.Encrypt(dataToEncrypt, RSAEncryptionPadding.Pkcs1);
}

public static string RSADecrypt(string privateKey, string dataToDecrypt)
{
    using var rsa = new RsaPkcs1Util(Encoding.UTF8, null, privateKey, 1024);
    return rsa.Decrypt(dataToDecrypt, RSAEncryptionPadding.Pkcs1);
}

扩展资料

posted @ 2022-11-26 15:34  祁去尘  阅读(310)  评论(0编辑  收藏  举报