我们的商店使用ServiceStack库已经有几年了,没有太多的问题。最近,在从5.12版本升级到6.0版本之后,我们看到一个基于凭据的身份验证请求没有返回BearerToken。
我已经阅读了关于JWT变更( 这里 )的发行说明部分,我理解了“破坏”更改以及这里,其中描述了如何返回响应中的承载令牌。但是,建议的更改是针对JwtAuthProvider,而不是CredentialsAuthProvider。CredentialsAuthProvider没有UseTokenCookie属性。
当auth提供者是CredentialsAuthProvider时,是否有方法返回身份验证响应中的承载令牌?
值得注意的是,下面是相关的服务器代码:
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
private readonly IDbContext _dbContext;
private const string AuthProviderType = "credentials";
public CustomCredentialsAuthProvider(IDbContext dbContext)
{
_dbContext = dbContext;
}
public override async Task<bool> TryAuthenticateAsync(IServiceBase authService,
string userName, string password, CancellationToken token=default)
{
var userAuthentication = _dbContext.GetUserAuthenticationData(userName);
return (userAuthentication != null && HashHelper.VerifyHash(password, userAuthentication.PasswordSalt, userAuthentication.PasswordHash));
}
public override async Task<IHttpResult> OnAuthenticatedAsync(IServiceBase authService,
IAuthSession session, IAuthTokens tokens,
Dictionary<string, string> authInfo, CancellationToken token=default)
{
var customUserSession = (CustomUserSession)session;
var userId = _dbContext.GetUserId(string.Empty, customUserSession.UserAuthName);
if (!userId.HasValue) throw new AuthenticationException("Unable to locate UserId");
var claims = _dbContext.GetClaims(userId.Value);
var postalCode = _dbContext.GetPostalCode(userId.Value);
HydrateCustomUserSession(claims.ToList(), customUserSession, postalCode);
//Call base method to Save Session and fire Auth/Session callbacks:
return result = await base.OnAuthenticatedAsync(authService, customUserSession, tokens, authInfo, token);
}
private void HydrateCustomUserSession(IReadOnlyCollection<Claims> claims, CustomUserSession customUserSession, string postalCode)
{
customUserSession.AuthProvider = AuthProviderType;
customUserSession.CreatedAt = DateTime.UtcNow;
customUserSession.UserId = Convert.ToInt32(claims.First(item => item.ClaimName == "sub").ClaimValue);
customUserSession.UserStatusId = Convert.ToInt32(claims.First(item => item.ClaimName == "user_status_id").ClaimValue);
customUserSession.UserAuthId = claims.First(item => item.ClaimName == "sub").ClaimValue;
customUserSession.FirstName = claims.First(item => item.ClaimName == "given_name").ClaimValue;
customUserSession.LastName = claims.First(item => item.ClaimName == "family_name").ClaimValue;
customUserSession.Email = claims.First(item => item.ClaimName == "email").ClaimValue;
customUserSession.Company = claims.First(item => item.ClaimName == "company_name").ClaimValue;
customUserSession.CompanyId = Convert.ToInt32(claims.First(item => item.ClaimName == "company_id").ClaimValue);
customUserSession.CompanyTypeId = Convert.ToInt32(claims.First(item => item.ClaimName == "company_type_id").ClaimValue);
customUserSession.PostalCode = postalCode;
var productIds = claims.First(item => item.ClaimName == "product_ids").ClaimValue;
if (!string.IsNullOrEmpty(productIds))
{
customUserSession.ProductIds = productIds.Split(",").Select(int.Parse).ToList();
}
else
{
customUserSession.ProductIds = new List<int>();
}
var productFeatureIds = claims.First(item => item.ClaimName == "product_feature_ids").ClaimValue;
if (!string.IsNullOrEmpty(productFeatureIds))
{
customUserSession.ProductFeatureIds = productFeatureIds.Split(",").Select(int.Parse).ToList();
}
else
{
customUserSession.ProductFeatureIds = new List<int>();
}
var userRoles = claims.First(item => item.ClaimName == "user_roles").ClaimValue;
if (!string.IsNullOrEmpty(userRoles))
{
customUserSession.UserRoles = userRoles.Split(",").Select(x => new UserRole(x)).ToList();
}
else
{
customUserSession.UserRoles = new List<UserRole>();
}
}
}
在客户端,这是一个批处理程序,而不是一个web应用程序。认证部分在这里:
private static void GetBearerToken()
{
var authRequest = new Authenticate()
{
UserName = ConfigHelper.ServiceUserName,
Password = ConfigHelper.ServicePassword,
provider = "credentials",
RememberMe = true
};
var authResponse = _authServiceClient.Post(authRequest);
// BearerToken was returned until the auth service was updated to using ServiceStack 6.0
// After using 6.0, BearerToken is empty.
_myOtherServiceClient.BearerToken = authResponse.BearerToken;
}
一旦被填充,承载令牌就被用来验证对其他服务的调用。谢谢你的帮助!
发布于 2022-03-24 13:15:07
如果您使用JWT,您将在JwtAuthProvider
插件中配置JWT,这是需要使用UseTokenCookie=false
配置的,以便在响应DTO上填充JWT令牌(即不使用令牌Cookies),如在链接文档中解释。
new JwtAuthProvider(AppSettings) {
UseTokenCookie = false
}
尽管您应该考虑使用推荐的JWT令牌cookie作为成功的身份验证,但仍然会产生经过身份验证的_authServiceClient
。
var authResponse = _authServiceClient.Post(authRequest);
// manual JWT handling is unnecessary when using Token Cookies
//_myOtherServiceClient.BearerToken = authResponse.BearerToken;
因为JWT令牌是在HTTP中返回的,这将节省手动处理/填充Bearer令牌所需的额外工作,包括在v6中自动刷新过期的JWT令牌。
https://stackoverflow.com/questions/71603055
复制相似问题