Я только что обновил веб-API ASP.NET Core 6 до .NET 8 (обратите внимание, что в .NET 6 все работало отлично), и при создании токена JWT я получаю следующую ошибку:
System.ArgumentOutOfRangeException: 'IDX10720: невозможно создать KeyedHashAlgorithm для алгоритма 'HS256', размер ключа должен быть больше чем: «256» бит, ключ имеет «152» бита. (Параметр 'keyBytes')'
Исходя из того, что я понял из этой ошибки, похоже, что появилось новое требование относительно того, как долго должен храниться секрет. быть так, я сделал секрет длиннее, что работает для создания токена, но при чтении токена я получаю совершенно новую ошибку
System.ArgumentException: 'IDX12723: Невозможно декодировать полезная нагрузка '[PII типа System.String' скрыта. Для получения более подробной информации см. https://aka.ms/IdentityModel/PII.]' как строку в кодировке Base64Url.'
Изменить: вот внутренний исключение, возможно, это может пролить некоторый свет
JsonException: IDX11020: значение JSON типа: 'String' не удалось преобразовать в 'JsonTokenType.Номер'. Чтение: «System.IdentityModel.Tokens.Jwt.JwtPayload.iat», позиция: «52», CurrentDepth: «1», BytesConsumed: «75».
Есть ли здесь какие-то критические изменения для обработки токенов JWT?
Вот код частного метода, читающего токен
private User? _GetIdentity(HttpContext context, string token)
{
try
{
var handler = new JwtSecurityTokenHandler();
//var jsonToken = handler.ReadToken(token);
var tokenS = handler.ReadToken(token) as JwtSecurityToken;//error happens here
var user = new User
{
Id = tokenS.Claims.First(claim => claim.Type == ClaimTypes.NameIdentifier).Value,
UserName = tokenS.Claims.First(claim => claim.Type == ClaimTypes.Name).Value,
Email = tokenS.Claims.First(claim => claim.Type == ClaimTypes.Email).Value,
Role = tokenS.Claims.First(claim => claim.Type == ClaimTypes.Role).Value
};
if (tokenS.ValidTo < DateTime.UtcNow)
{
throw new Exceptions.UnauthorizedAccessException($"...");
}
return user;
}
catch(Exceptions.UnauthorizedAccessException e)
{
_logger.LogError(e.Message);
throw;
}
}
Вот код класса, генерирующего токен JWT:
public class JwtService
{
private const int EXPIRATION_TOKEN_MINUTES = 25;
private const int EXPIRATION_REFRESH_DAYS = 7;
private readonly IConfiguration _configuration;
public JwtService(IConfiguration configuration)
{
_configuration = configuration;
}
public AuthenticationResponse CreateToken(IdentityUser user, IEnumerable roles)
{
var expiration = DateTime.Now.AddMinutes(EXPIRATION_TOKEN_MINUTES);
var refreshExpiration = DateTime.Now.AddDays(EXPIRATION_REFRESH_DAYS);
var token = CreateJwtToken(
CreateClaims(user, roles),
CreateSigningCredentials(),
expiration
);
var refreshToken = CreateJwtToken(
CreateRefreshTokenClaims(user.Id),
CreateSigningCredentials(),
refreshExpiration
);
var tokenHandler = new JwtSecurityTokenHandler();
return new AuthenticationResponse
{
Token = tokenHandler.WriteToken(token),
RefreshToken = tokenHandler.WriteToken(refreshToken),
Expiration = expiration
};
}
private JwtSecurityToken CreateJwtToken(Claim[] claims, SigningCredentials credentials, DateTime expiration) =>
new JwtSecurityToken(
_configuration["Jwt:Issuer"],
_configuration["Jwt:Audience"],
claims,
expires: expiration,
signingCredentials: credentials
);
private Claim[] CreateRefreshTokenClaims(string userId) =>
new[]
{
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
new Claim(ClaimTypes.NameIdentifier, userId)
};
private Claim[] CreateClaims(IdentityUser user, IEnumerable roles) =>
new[] {
//new Claim(JwtRegisteredClaimNames.Sub, _configuration["Jwt:Subject"]),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Email, user.Email),
}
.Concat(roles.Select(r => new Claim(ClaimTypes.Role, r)).ToArray())
.ToArray();
private SigningCredentials CreateSigningCredentials() =>
new SigningCredentials(
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Secret"])
),
SecurityAlgorithms.HmacSha256
);
public ClaimsIdentity CreateClaimsIdentity(string username, string userId, IEnumerable roles)
{
List claims = new List
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.NameIdentifier, userId)
};
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
ClaimsIdentity identity = new ClaimsIdentity(
claims,
"Token",
ClaimTypes.Name,
ClaimTypes.Role
);
return identity;
}
public ClaimsPrincipal ValidateToken(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
// Set the token validation parameters
var validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidAudience = _configuration["Jwt:Audience"],
ValidIssuer = _configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Secret"])
)
};
// Validate and parse the token
var principal = tokenHandler.ValidateToken(token, validationParameters, out var _);
return principal;
}
catch
{
// Token validation failed
return null;
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/775 ... jwt-tokens
При переносе существующего проекта API в .NET 8 возникает ошибка при создании токенов JWT. ⇐ C#
Место общения программистов C#
1736312884
Anonymous
Я только что обновил веб-API ASP.NET Core 6 до .NET 8 (обратите внимание, что в .NET 6 все работало отлично), и при создании токена JWT я получаю следующую ошибку:
System.ArgumentOutOfRangeException: 'IDX10720: невозможно создать KeyedHashAlgorithm для алгоритма 'HS256', размер ключа должен быть больше чем: «256» бит, ключ имеет «152» бита. (Параметр 'keyBytes')'
Исходя из того, что я понял из этой ошибки, похоже, что появилось новое требование относительно того, как долго должен храниться секрет. быть так, я сделал секрет длиннее, что работает для создания токена, но при чтении токена я получаю совершенно новую ошибку
System.ArgumentException: 'IDX12723: Невозможно декодировать полезная нагрузка '[PII типа System.String' скрыта. Для получения более подробной информации см. https://aka.ms/IdentityModel/PII.]' как строку в кодировке Base64Url.'
Изменить: вот внутренний исключение, возможно, это может пролить некоторый свет
JsonException: IDX11020: значение JSON типа: 'String' не удалось преобразовать в 'JsonTokenType.Номер'. Чтение: «System.IdentityModel.Tokens.Jwt.JwtPayload.iat», позиция: «52», CurrentDepth: «1», BytesConsumed: «75».
Есть ли здесь какие-то критические изменения для обработки токенов JWT?
Вот код частного метода, читающего токен
private User? _GetIdentity(HttpContext context, string token)
{
try
{
var handler = new JwtSecurityTokenHandler();
//var jsonToken = handler.ReadToken(token);
var tokenS = handler.ReadToken(token) as JwtSecurityToken;//error happens here
var user = new User
{
Id = tokenS.Claims.First(claim => claim.Type == ClaimTypes.NameIdentifier).Value,
UserName = tokenS.Claims.First(claim => claim.Type == ClaimTypes.Name).Value,
Email = tokenS.Claims.First(claim => claim.Type == ClaimTypes.Email).Value,
Role = tokenS.Claims.First(claim => claim.Type == ClaimTypes.Role).Value
};
if (tokenS.ValidTo < DateTime.UtcNow)
{
throw new Exceptions.UnauthorizedAccessException($"...");
}
return user;
}
catch(Exceptions.UnauthorizedAccessException e)
{
_logger.LogError(e.Message);
throw;
}
}
Вот код класса, генерирующего токен JWT:
public class JwtService
{
private const int EXPIRATION_TOKEN_MINUTES = 25;
private const int EXPIRATION_REFRESH_DAYS = 7;
private readonly IConfiguration _configuration;
public JwtService(IConfiguration configuration)
{
_configuration = configuration;
}
public AuthenticationResponse CreateToken(IdentityUser user, IEnumerable roles)
{
var expiration = DateTime.Now.AddMinutes(EXPIRATION_TOKEN_MINUTES);
var refreshExpiration = DateTime.Now.AddDays(EXPIRATION_REFRESH_DAYS);
var token = CreateJwtToken(
CreateClaims(user, roles),
CreateSigningCredentials(),
expiration
);
var refreshToken = CreateJwtToken(
CreateRefreshTokenClaims(user.Id),
CreateSigningCredentials(),
refreshExpiration
);
var tokenHandler = new JwtSecurityTokenHandler();
return new AuthenticationResponse
{
Token = tokenHandler.WriteToken(token),
RefreshToken = tokenHandler.WriteToken(refreshToken),
Expiration = expiration
};
}
private JwtSecurityToken CreateJwtToken(Claim[] claims, SigningCredentials credentials, DateTime expiration) =>
new JwtSecurityToken(
_configuration["Jwt:Issuer"],
_configuration["Jwt:Audience"],
claims,
expires: expiration,
signingCredentials: credentials
);
private Claim[] CreateRefreshTokenClaims(string userId) =>
new[]
{
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
new Claim(ClaimTypes.NameIdentifier, userId)
};
private Claim[] CreateClaims(IdentityUser user, IEnumerable roles) =>
new[] {
//new Claim(JwtRegisteredClaimNames.Sub, _configuration["Jwt:Subject"]),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Email, user.Email),
}
.Concat(roles.Select(r => new Claim(ClaimTypes.Role, r)).ToArray())
.ToArray();
private SigningCredentials CreateSigningCredentials() =>
new SigningCredentials(
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Secret"])
),
SecurityAlgorithms.HmacSha256
);
public ClaimsIdentity CreateClaimsIdentity(string username, string userId, IEnumerable roles)
{
List claims = new List
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.NameIdentifier, userId)
};
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
ClaimsIdentity identity = new ClaimsIdentity(
claims,
"Token",
ClaimTypes.Name,
ClaimTypes.Role
);
return identity;
}
public ClaimsPrincipal ValidateToken(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
// Set the token validation parameters
var validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidAudience = _configuration["Jwt:Audience"],
ValidIssuer = _configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Secret"])
)
};
// Validate and parse the token
var principal = tokenHandler.ValidateToken(token, validationParameters, out var _);
return principal;
}
catch
{
// Token validation failed
return null;
}
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/77518092/migrating-existing-api-project-to-net-8-getting-error-when-creating-jwt-tokens[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия