我正在学习本教程:https://jonhilton.net/2017/10/11/secure-your-asp.net-core-2.0-api-part-1---issuing-a-jwt/
以下是主要代码:
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);我不明白的部分是它在配置文件中查找密钥的位置,但是它没有给出这个键是/应该是什么的指示符?
发布于 2018-02-15 13:57:20
这个密钥可以是任何字符串:它是用于加密和解密安全负载的秘密密钥。来自维基百科:
对称密钥算法是用于密码学的算法,它使用相同的密码密钥对明文进行加密和对密文进行解密。在实践中,密钥代表两个或多个当事方之间的共享秘密,可用于维护私有信息链接。
至于如何生成有效的密钥,您可以在crypto.stackexchange上参考这个问题。
发布于 2018-03-09 14:13:37
一种选择是在JWT头中保留与“claim”声明相关联的对称签名密钥的存储库。例如,在加密的AWS S3桶中保存一个密钥文件。.NET核心2 web服务每隔X分钟从S3桶中提取密钥文件。
当请求到达时,“built”声明值将用于从从拉出的文件构建的集合中查找相关的对称密钥。
示例:配置IssuerSigningKeyResolver函数。
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被定义为:
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中提取密钥文件,并将密钥存储在集合中。
// 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”声明。
{
"alg": "HS256",
"kid": "customer2",
"typ": "JWT"
}“third”的值将作为第三个参数传递给IssuerSigningKeyResolver方法。然后,该子节点将用于查找用于验证JWT签名的相关对称密钥。
https://stackoverflow.com/questions/48806754
复制相似问题