基于 JWT Bearer 的身份认证方案
基于 JWT Bearer 的身份认证方案
认证流程
- 匿名访问资源,server 响应 401
- client 跳转至登录页面
- client 请求 RSA 公钥,用户输入账号、密码
- client 对密码执行 RSA 加密,请求 login
- server 验证账号、密码,通过之后,签发包含用户标识的 JWT
- client 使用 JWT 设置 Authorization,scheme type 为 Bearer
- server 验证 JWT 是否合法,是否过期,验证通过后,完成身份认证
密码安全
不存储原始的明文密码
- client 对密码执行 RSA 加密,然后传递密文
- 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);
}

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号