首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ServiceStack 6 CredentialsAuthProvider不返回BearerToken

ServiceStack 6 CredentialsAuthProvider不返回BearerToken
EN

Stack Overflow用户
提问于 2022-03-24 13:05:19
回答 1查看 90关注 0票数 1

我们的商店使用ServiceStack库已经有几年了,没有太多的问题。最近,在从5.12版本升级到6.0版本之后,我们看到一个基于凭据的身份验证请求没有返回BearerToken。

我已经阅读了关于JWT变更( 这里 )的发行说明部分,我理解了“破坏”更改以及这里,其中描述了如何返回响应中的承载令牌。但是,建议的更改是针对JwtAuthProvider,而不是CredentialsAuthProvider。CredentialsAuthProvider没有UseTokenCookie属性。

当auth提供者是CredentialsAuthProvider时,是否有方法返回身份验证响应中的承载令牌?

值得注意的是,下面是相关的服务器代码:

代码语言:javascript
运行
复制
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应用程序。认证部分在这里:

代码语言:javascript
运行
复制
        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;
    }

一旦被填充,承载令牌就被用来验证对其他服务的调用。谢谢你的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-24 13:15:07

如果您使用JWT,您将在JwtAuthProvider插件中配置JWT,这是需要使用UseTokenCookie=false配置的,以便在响应DTO上填充JWT令牌(即不使用令牌Cookies),如在链接文档中解释

代码语言:javascript
运行
复制
new JwtAuthProvider(AppSettings) {
    UseTokenCookie = false
}

尽管您应该考虑使用推荐的JWT令牌cookie作为成功的身份验证,但仍然会产生经过身份验证的_authServiceClient

代码语言:javascript
运行
复制
var authResponse = _authServiceClient.Post(authRequest);

// manual JWT handling is unnecessary when using Token Cookies
//_myOtherServiceClient.BearerToken = authResponse.BearerToken;

因为JWT令牌是在HTTP中返回的,这将节省手动处理/填充Bearer令牌所需的额外工作,包括在v6中自动刷新过期的JWT令牌。

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

https://stackoverflow.com/questions/71603055

复制
相关文章

相似问题

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