首页 学海无涯 WebAPI .NET Core WebAPI 认证授权之JWT(三):RSA算法实操
.NET Core WebAPI 认证授权之JWT(三):RSA算法实操
摘要 在.NET Core WebAPI中实操JWT认证授权,鉴权中心使用RsaSha256算法进行签名,以及在API中添加JWT授权验证。

开发环境

VisualStudio 2019 16.8.3 

ASP.NET Core 5.0   

正文

一、前言

在上一篇《.NET Core WebAPI 认证授权之JWT(二):HMAC算法实操》中进行了JWT签名常用算法之一HMAC算法实操,本文进行另一种更安全的非对称加密算法RSA实操。

HMAC算法和RSA算法的大致步骤是一样的,区别在于生成Token时使用的算法以及密钥。由于RSA是一种非对称加密算法,它和HMAC加密时使用一个密钥不同,它需要一对密钥,使用私钥加密,然后使用公钥解密。

二、生成Token

生成Token的步骤和上一篇差不多,这里只说区别,如有疑问,请看上篇:

1.创建项目 

区别于上一篇将颁发Token和API分成两个项目,这里我将二者写在同一个项目(根据实际需求自己选择)。


2.引入Nuget包 

这里和上一篇没什么区别,略过。

3.在AuthenticationController中创建一个登录接口 

同上。

4.生成JWT

在生成Token之前,我们需要准备一对RSA密钥(公钥和私钥),密钥可以借助网上的工具生成,如支付宝的:https://opendocs.alipay.com/open/291/105971,也可以自己写代码生成。

注意:这里我们使用的是PEM格式的密钥(PKCS#1或PKCS#8都可以),在.NET 5.0中,有直接从PEM格式导入密钥的API。   

#region 生成Token RSA
var claims = new[] {
    new Claim(ClaimTypes.Name, userName)
};

string rootPath = Directory.GetCurrentDirectory();
string filePath = Path.Combine(rootPath, "key.pem");

if (!System.IO.File.Exists(filePath))
    throw new Exception("私钥文件不存在");
string key = System.IO.File.ReadAllText(filePath);

var rsa = RSA.Create();
rsa.ImportFromPem(key.AsSpan());

var creds = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha256);

var token = new JwtSecurityToken(issuer: "leo96.com", //发布者 随便写 可用于验证 建议写配置文件中
                                    audience: "leo96.com",  //受众 随便写 可用于验证 建议写配置文件中
                                    claims: claims, //声明 存储其他信息
                                    expires: DateTime.Now.AddMinutes(5), //过期时间 可写配置文件中
                                    signingCredentials: creds); //凭证

string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
#endregion

和上一篇类似,区别在于这里的key是RSA密钥对中的私钥,通常是从pem文件导入:RSA.Create().ImportFromPem()

三、Token认证和授权

步骤同上一篇一样。添加JWT认证服务认证中间件授权中间件Authorize特性

这里主要是添加JWT认证服务时略有不同:

#region 添加JWT认证 RSA
string path = Path.Combine(Directory.GetCurrentDirectory(), "key.public.pem");

var rsa = RSA.Create();
rsa.ImportFromPem(File.ReadAllText(path).AsSpan());

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,  //是否验证Issuer
            ValidateAudience = true,    //是否验证Audience
            ValidateLifetime = true,    //是否验证有效时间
            ValidateIssuerSigningKey = true,    //是否验证key
            ClockSkew = TimeSpan.FormSecends(30),    //缓冲过期时间 默认5分钟 有效时间 = 过期时间 + 缓冲过期时间
            ValidIssuer = "leo96.com",
            ValidAudience = "leo96.com",
            IssuerSigningKey = new RsaSecurityKey(rsa)
        };
    });
#endregion

这里需要从pem文件读取公钥:RSA.Create().ImportFromPem(),进行验证。

附加:C#生成RSA密钥对

.NET自带API可以导出PKCS#1、PKCS#8的私钥和PKCS#1的公钥,但没有导出PKCS#8格式公钥的API,并且不支持PEM格式。

所以这里我用到了第三方Nuget包:RSAExtensions,里面有RSA类的扩展方法,弥补了官方API的不足。

RSAExtensions 功能如下:

    ● 提供以前Framework有的XML格式的密钥导入和导出

    ● 提供对PKCS#1、PKCS#8 PEM格式导入和导出支持

    ● 提供对PKCS#1、PKCS#8、XML格式的统一导入和导出

    ● 提供对大数据分段加密的支持 

使用RSAExtensions生成RSA密钥对: 

using RSAExtensions;

private RSA GenerateAndSaveKey(string filePath, bool isPem)
{
    string publicKeys, privateKeys, privateKeys_pkcs8, publicKeys_pkcs8, ext;

    ext = isPem ? "pem" : "txt";

    var rsa = RSA.Create();

    privateKeys = rsa.ExportPrivateKey(RSAKeyType.Pkcs1, isPem); //私钥
    publicKeys = rsa.ExportPublicKey(RSAKeyType.Pkcs1, isPem);   //公钥
    privateKeys_pkcs8 = rsa.ExportPrivateKey(RSAKeyType.Pkcs8, isPem); //pkcs8私钥
    publicKeys_pkcs8 = rsa.ExportPublicKey(RSAKeyType.Pkcs8, isPem);   //pkcs8公钥

    File.WriteAllText(System.IO.Path.Combine(filePath, $"key.pkcs8.{ext}"), privateKeys_pkcs8);
    File.WriteAllText(System.IO.Path.Combine(filePath, $"key.public.pkcs8.{ext}"), publicKeys_pkcs8);
    File.WriteAllText(System.IO.Path.Combine(filePath, $"key.{ext}"), privateKeys);
    File.WriteAllText(System.IO.Path.Combine(filePath, $"key.public.{ext}"), publicKeys);

    return rsa;
}

此外博主自己写了一个RSA密钥对生成工具(文末附录):


感谢阅读,敬请斧正!

附录一:RSA密钥对生成工具安装包  

附录二:系列Demo(弄丢了,卧槽)

附录三:系列目录

            《.NET Core WebAPI 认证授权之JWT(一):JWT介绍》

            《.NET Core WebAPI 认证授权之JWT(二):HMAC算法实操》

            《.NET Core WebAPI 认证授权之JWT(三):RSA算法实操》

            《.NET Core WebAPI 认证授权之JWT(四):JWT续期问题》  


版权声明:本文由不落阁原创出品,转载请注明出处!

本文链接:http://www.leo96.com/article/detail/57

广告位

来说两句吧
最新评论
  • NULL
    NULL
    活了[嘻嘻]

    Leo
    Leo 回复 NULL 0.0

    2021-02-05 14:11回复