首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Net Core JWT签名凭据

Net Core JWT签名凭据
EN

Stack Overflow用户
提问于 2018-02-15 11:59:03
回答 2查看 7.2K关注 0票数 1

我正在学习本教程:https://jonhilton.net/2017/10/11/secure-your-asp.net-core-2.0-api-part-1---issuing-a-jwt/

以下是主要代码:

代码语言:javascript
复制
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SecurityKey"]));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var token = new JwtSecurityToken(
                    issuer: "yourdomain.com",
                    audience: "yourdomain.com",
                    claims: user.Claims,
                    expires: DateTime.Now.AddMinutes(30),
                    signingCredentials: creds);

我不明白的部分是它在配置文件中查找密钥的位置,但是它没有给出这个键是/应该是什么的指示符?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-15 13:57:20

这个密钥可以是任何字符串:它是用于加密和解密安全负载的秘密密钥。来自维基百科

对称密钥算法是用于密码学的算法,它使用相同的密码密钥对明文进行加密和对密文进行解密。在实践中,密钥代表两个或多个当事方之间的共享秘密,可用于维护私有信息链接。

至于如何生成有效的密钥,您可以在crypto.stackexchange上参考这个问题。

票数 0
EN

Stack Overflow用户

发布于 2018-03-09 14:13:37

一种选择是在JWT头中保留与“claim”声明相关联的对称签名密钥的存储库。例如,在加密的AWS S3桶中保存一个密钥文件。.NET核心2 web服务每隔X分钟从S3桶中提取密钥文件。

当请求到达时,“built”声明值将用于从从拉出的文件构建的集合中查找相关的对称密钥。

示例:配置IssuerSigningKeyResolver函数。

代码语言:javascript
复制
public static IServiceCollection AddJwtValidation(this IServiceCollection services)
{
        IServiceProvider sp = services.BuildServiceProvider();
        ConfigRoot = sp.GetRequiredService<IConfigurationRoot>();

        tokenAudience = ConfigRoot["JwtToken:Audience"];
        tokenIssuer = ConfigRoot["JwtToken:Issuer"];

        SecurityKeyManager.Start();

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
        {
            options.Audience = tokenAudience;
            options.ClaimsIssuer = tokenIssuer;

            options.TokenValidationParameters = new TokenValidationParameters
            {                    
                // The signing key must match!
                ValidateIssuerSigningKey = true,
                RequireSignedTokens = true,
                IssuerSigningKeyResolver = MyIssuerSigningKeyResolver,
                ....

IssuerSigningKeyResolver被定义为:

代码语言:javascript
复制
public static List<SecurityKey> MyIssuerSigningKeyResolver(string token, SecurityToken jwtToken, string kid, TokenValidationParameters validationParameters)
{
        List<SecurityKey> keys = new List<SecurityKey>();

        if (validationParameters == null)
        {
            throw new ArgumentNullException("validationParameters");
        }

        if (jwtToken == null)
        {
            throw new ArgumentNullException("securityToken");
        }

        if (!string.IsNullOrEmpty(kid))
        {
            SymmetricSecurityKey key = SecurityKeyManager.GetSecurityKey(kid);

            keys.Add(key);
        }

        return keys;
}

SecurityKeyManager定期从AWS S3中提取密钥文件,并将密钥存储在集合中。

代码语言:javascript
复制
// Example approved-clients.txt file in the approved-clients S3 bucket (us-east-1).
//    //kid,key,active
//    customer1,AAAAAAAAAAAAAAAA,true
//    customer2,BBBBBBBBBBBBBBBB,true
//    customer3,CCCCCCCCCCCCCCCC,true
//    customer4,DDDDDDDDDDDDDDDD,true

namespace My.CoreServices.Security.Jwt
{
    public class SecurityKeyManager
    {
        private const int RELOAD_TIMER_DELAY_SECONDS = 3 * 1000;
        private const int RELOAD_TIMER_PERIOD_MINUTES = 60 * 60 * 1000;

        [DebuggerDisplay("{Kid}  {SymmetricKey}  {Active}")]
        internal class ApprovedClient
        {
            public string Kid { get; set; }
            public bool Active { get; set; }
            public string SymmetricKey { get; set; }
        };

        private static List<SymmetricSecurityKey> securityKeys = new List<SymmetricSecurityKey>();

        private static Timer reloadTimer = null;

        private static object keySync = new object();

        public static void Start()
        {
            // Start a new timer to reload all the security keys every RELOAD_TIMER_PERIOD_MINUTES.
            if (reloadTimer == null)
            {
                reloadTimer = new Timer(async (t) =>
                {
                    try
                    {
                        List<ApprovedClient> approvedClients = new List<ApprovedClient>();

                        Log.Debug("Pulling latest approved client symmetric keys for JWT signature validation");

                        string awsAccessKeyId = JwtConfigure.ConfigRoot["AWS:KeyManagement:AccessKeyId"];
                        string awsSecretAccessKey = fromBase64(JwtConfigure.ConfigRoot["AWS:KeyManagement:SecretAccessKey"]);
                        string awsRegion = JwtConfigure.ConfigRoot["AWS:KeyManagement:Region"];

                        using (var client = new AmazonS3Client(awsAccessKeyId, awsSecretAccessKey, RegionEndpoint.GetBySystemName(awsRegion)))
                        {
                            var request = new GetObjectRequest();
                            request.BucketName = JwtConfigure.ConfigRoot["AWS:KeyManagement:Bucket"];
                            request.Key = JwtConfigure.ConfigRoot["AWS:KeyManagement:Key"];

                            var response = await client.GetObjectAsync(request);

                            using (StreamReader sr = new StreamReader(response.ResponseStream))
                            {
                                while (sr.Peek() > 0)
                                {
                                    string line = await sr.ReadLineAsync();

                                    // Ignore comment lines in the approved-client file
                                    if (!line.StartsWith("//") && !string.IsNullOrEmpty(line))
                                    {
                                        // Each line of the file should only have 3 items:
                                        // kid, key, active
                                        string[] items = line.Split(',');
                                        approvedClients.Add(new ApprovedClient()
                                        {
                                            Kid = items[0],
                                            SymmetricKey = items[1],
                                            Active = Boolean.Parse(items[2])
                                        });
                                    }
                                }
                            }

                        }
                        lock (keySync)
                        {
                            if (approvedClients.Count > 0)
                            {
                                // Clear the security key list and repopulate
                                securityKeys.Clear();

                                foreach (var approvedClient in approvedClients)
                                {
                                    if (approvedClient.Active)
                                    {
                                        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(approvedClient.SymmetricKey));
                                        key.KeyId = approvedClient.Kid;
                                        securityKeys.Add(key);
                                    }
                                }
                            }
                        }

                        Log.Information($"Reloaded security keys");
                    }
                    catch (Exception ex)
                    {
                        Log.Warning($"Error getting current security keys - {ex.Message}");
                    }
                }, null, RELOAD_TIMER_DELAY_SECONDS, RELOAD_TIMER_PERIOD_MINUTES);
            }
        }

        public static void Stop()
        {
            if (reloadTimer != null)
            {
                reloadTimer.Dispose();
                reloadTimer = null;
            }
        }

        public static SymmetricSecurityKey GetSecurityKey(string kid)
        {
            SymmetricSecurityKey securityKey = null;

            lock (keySync)
            {
                byte[] keyData = securityKeys.Where(k => k.KeyId == kid).Select(x => x.Key).FirstOrDefault();

                if (keyData != null)
                {
                    securityKey = new SymmetricSecurityKey(keyData);
                    securityKey.KeyId = kid;
                }
            }

            return securityKey;
        }

        private static string fromBase64(string encodedValue)
        {
            byte[] decodedBytes = Convert.FromBase64String(encodedValue);
            return Encoding.UTF8.GetString(decodedBytes);
        }
    }
}

确保在为特定用户/customer/etc创建JWT时,在JWT头中设置“claim”声明。

代码语言:javascript
复制
{
  "alg": "HS256",
  "kid": "customer2",
  "typ": "JWT"
}

“third”的值将作为第三个参数传递给IssuerSigningKeyResolver方法。然后,该子节点将用于查找用于验证JWT签名的相关对称密钥。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48806754

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档