Post-ServiceStack 中的注册操作

Post-registration action in ServiceStack

我已经将 ServiceStack 用于几个项目并且非常喜欢它。也就是说,这是我第一次尝试以任何方式处理用户身份验证,所以如果我在这里的理解或实施中犯了任何基本错误,请原谅我。

我需要能够跟踪用户的自定义属性,例如他们的用户类型和关联的公司。为此,我创建了一个单独的 "User" class,其中仅包含有关我要跟踪的用户的详细信息以及自定义位。我喜欢这样,因为例如,我可以将 UserTypeId 存储为 User 的 属性,并将 [Reference] 存储为实际的 UserType 对象。这让我使用服务代码中其他地方的 LoadReferences 将嵌套数据发送回客户端。

为了执行其中任何一项,我需要获取自定义用户对象以发送回浏览器(它是一个网络应用程序)。到目前为止,我已经实现了一个 CustomCredentialsAuthProvider,它将用户对象添加到 AuthResponse,如下所示:

public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
    {
        //let normal authentication happen
        var authResponse = (AuthenticateResponse)base.Authenticate(authService, session, request);

        using (var db = authService.TryResolve<IDbConnectionFactory>().OpenDbConnection())
        {
            User user = db.LoadSingleById<User>(int.Parse(authResponse.UserId));

            //return your own class, but take neccessary data from AuthResponse
            return new
            {
                SessionId = authResponse.SessionId,
                ReferrerUrl = authResponse.ReferrerUrl,
                ResponseStatus = authResponse.ResponseStatus,
                UserSession = user
            };
        }
    }

这很好用。为了在应用程序中处理用户配置文件管理,我 post 任何需要的更新都会写入用户 table 以及 IUserAuthRepository(均使用当前会话 UserAuthId 作为密钥)。

好的,这就是所有的基础工作。如果可能的话,我现在需要做的是允许用户 A 注册另一个用户 B 而无需将他们的会话切换到用户 B。据我所知,Register 方法 returns 只是用户 ID创建...

{"userId":"1019","responseStatus":{}}

...并将会话 cookie 设置为新创建的用户会话。我想我需要一种方法来防止这种自动会话分配,并且能够独立于其他任何事情注册新用户并获取他们的 ID。这可能吗?

在相关说明中,我希望能够在注册后立即取回整个用户配置文件,而不仅仅是 "userId"。就目前而言,我需要立即进行另一个服务器调用以获取用户详细信息(根据 session.UserAuthId 从用户中提取)。

提前致谢!

自定义身份验证服务响应

我建议您始终 return ServiceStack 服务中的具体 class(即,而不是匿名对象)这有助于为 DTO 类型生成元数据服务,并让您反序列化类型化 API 中的响应。

您还应该考虑遵守 Authenticate 服务合同(所有客户都期望)并继续 return AuthenticateResponse 类型。您可以使用 Dictionary<string,string> Meta 属性 将附加元数据附加到 return 类型,例如:

var r = (AuthenticateResponse)base.Authenticate(authService, session, request);

using (var db = authService.TryResolve<IDbConnectionFactory>().Open())
{
    User user = db.LoadSingleById<User>(int.Parse(r.UserId));

    r.Meta = new Dictionary<String,String> {
        {"customId", user.CustomId},
        //etc
    };

    return r;
}

如果您选择 return 不同的类型,您的服务仍然可以工作,但这样它就不会破坏期望接收类型 AuthenticateResponse.[=25 的 .NET 服务客户端=]

自定义注册实现

对于自定义注册而不是使用现有的 RegisterService 实现,请复制并创建您自己的版本来执行您想要的操作。

注册服务使用 IAuthRepository 依赖来创建新用户:

public IAuthRepository AuthRepo { get; set; }

它转换为 IUserAuthRepository 以便它可以访问更丰富的 API,例如:

var userAuthRepo = AuthRepo.AsUserAuthRepository(GetResolver());

在这里您可以通过填充 UserAuth class 的实例来注册新用户,例如:

var newUserAuth = request.ConvertTo<UserAuth>();
newUserAuth.PrimaryEmail = request.Email;

您可以使用它来创建新用户:

userAuthRepo.CreateUserAuth(newUserAuth, request.Password)

这只是将新的 UserAuth 信息保存到已注册的 IUserAuthRepository

由于您现在正在使用自己的 Register class 实现,它不会影响您现有的会话,您可以 return 任何您喜欢的响应。