JwtSecurityToken не истекает, когда он должен
В настоящее время я использую класс JwtSecurityToken в пространстве имен System.IdentityModels.Tokens. Я создаю токен, используя следующее:
DateTime expires = DateTime.UtcNow.AddSeconds(10);
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
var genericIdentity = new System.Security.Principal.GenericIdentity(username, "TokenAuth");
ClaimsIdentity identity = new ClaimsIdentity(claims);
string secret = ConfigurationManager.AppSettings["jwtSecret"].ToString();
var securityKey = new InMemorySymmetricSecurityKey(Encoding.Default.GetBytes(secret));
var signingCreds = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.HmacSha256Signature);
var securityToken = handler.CreateToken(
issuer: issuer,
audience: ConfigurationManager.AppSettings["UiUrl"].ToString(),
signingCredentials: signingCreds,
subject: identity,
expires: expires,
notBefore: DateTime.UtcNow
);
return handler.WriteToken(securityToken);
По какой-то причине, несмотря на то, что срок истечения установлен на 10 секунд после текущего времени, он фактически не генерирует исключение, когда токен проверяется до примерно 5 минут. Увидев это, я подумал, что, возможно, было минимальное время истечения 5 минут, поэтому я установил время истечения срока:
DateTime.UtcNow.AddMinutes(5);
Затем он истекает через 10 минут, но в сообщении об исключении указано, что время истечения времени установлено на то, что оно должно быть (через 5 минут после входа пользователя в систему), и когда оно показывает текущее время в исключении, оно Через 5 минут после истечения срока. Таким образом, он, похоже, знает, когда он ДОЛЖЕН истечь, но на самом деле он не генерирует исключение только через 5 минут после истечения срока. Затем, поскольку токен, кажется, добавляет 5 минут в любое время, когда я установил его для истечения срока действия, я устанавливаю время истечения срока действия:
DateTime.UtcNow.AddMinutes(-5).AddSecond(10);
Я тестировал это, и до сих пор он еще не истек (спустя более десяти минут). Может кто-нибудь объяснить, почему это происходит и что я делаю неправильно? Кроме того, если вы видите что-либо еще с кодом, который я предоставил, любые рекомендации будут оценены, поскольку я новичок в использовании JWT и этой библиотеки.
Заранее благодарю
Ответы
Ответ 1
Прочитав ответ @Denis Kucherov, я узнал, что могу использовать тот же пользовательский валидатор, который он опубликовал, не используя класс JwtBearerOptions, который потребовал бы, чтобы я добавил новую библиотеку.
Кроме того, поскольку существует два пространства имен, которые содержат много этих же классов, я обязательно упомянул, что все они используют пространства имен System.IdentityModels... namespaces. (НЕ Microsoft.IdentityModels...)
Ниже приведен код, который я использовал:
private bool CustomLifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken tokenToValidate, TokenValidationParameters @param)
{
if (expires != null)
{
return expires > DateTime.UtcNow;
}
return false;
}
private JwtSecurityToken ValidateJwtToken(string tokenString)
{
string secret = ConfigurationManager.AppSettings["jwtSecret"].ToString();
var securityKey = new InMemorySymmetricSecurityKey(Encoding.Default.GetBytes(secret));
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
TokenValidationParameters validation = new TokenValidationParameters()
{
ValidAudience = "MyAudience",
ValidIssuer = "MyIssuer",
ValidateIssuer = true,
ValidateLifetime = true,
LifetimeValidator = CustomLifetimeValidator,
RequireExpirationTime = true,
IssuerSigningKey = securityKey,
ValidateIssuerSigningKey = true,
};
SecurityToken token;
ClaimsPrincipal principal = handler.ValidateToken(tokenString, validation, out token);
return (JwtSecurityToken)token;
}
Ответ 2
Проблема связана с ClockSkew
. Обычно проверочные библиотеки (по крайней мере, одна из MS) компенсируют перекос тактовой частоты. ClockSkew
значение по умолчанию составляет 5 минут. Смотрите ответ здесь
Вы можете изменить ClockSkew
в TokenValidationParameters
:
var tokenValidationParameters = new TokenValidationParameters
{
//...your setting
// set ClockSkew is zero
ClockSkew = TimeSpan.Zero
};
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
TokenValidationParameters = tokenValidationParameters
});
Удачного кодирования!
Ответ 3
Кажется, что есть проблема с LifeTimeValidator. Вы можете просто переопределить свою логику с помощью специального делегата. Кроме того, используйте класс JwtBearerOptions для управления поведением промежуточного программного обеспечения. Например:
new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidIssuer = _configuration["Tokens:Issuer"],
ValidAudience = _configuration["Tokens:Audience"],
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
LifetimeValidator = LifetimeValidator,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Tokens:Key"]))
}
}
И назначьте делегат LifetimeValidotor, чтобы предоставить свою собственную логику проверки таймаута:
private bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken token, TokenValidationParameters @params)
{
if (expires != null)
{
return expires > DateTime.UtcNow;
}
return false;
}
Ответ 4
Я только что реализовал промежуточное программное обеспечение токена JWT, и, хотя в примерах в Интернете используется UtcNow
, мне пришлось использовать Now
или время истечения срока действия. Когда я использую Now
, истекает время.
Ответ 5
Ниже ссылка даст вам точный ответ, так как по умолчанию время истечения MS составляет 5 минут.
Так что либо вы должны сделать это на заказ, либо время, которое вы отдадите
истекает: DateTime.Now.AddSeconds(30)
30 секунд в вышеуказанной строке будут добавлены в срок истечения. Таким образом, общее время истечения будет 5 минут и 30 секунд
https://github.com/IdentityServer/IdentityServer3/issues/1251
Надеюсь, это поможет.