我正试图在ServiceStack中实现电子邮件确认。我花了5天的时间试图弄清楚所有的认证机制,我必须说,这是非常复杂的。代码不容易读懂。
例如,我很难知道:
IAuthProvider.OnAuthenticated?有时候这似乎是可选的。IAuthSession.PopulateSession?它和IAuthProvider.PopulateSession有什么区别?IRequest.SaveSession?IAuthTokens是什么?为什么他们会在某个时候被合并?是因为用户可以通过许多不同的提供程序进行身份验证,而我们需要合并IAuthTokens吗?它们像索赔一样吗?Session.FromToken只适用于JWT吗?IAuthWithRequest.PreAuthenticate和IAuthProvider.Authenticate有什么不同?在这两种方法中,应该采取什么不同的做法?据我所知,每个请求都会调用PreAuthenticate,并在使用/auth/{provider} (在本例中为/auth/email)时调用身份验证。我是不是遗漏了什么?撇开这些问题不谈,为了解决问题,我尝试了两种方法:
1. Override the default `UserAuth` with `CustomUserAuth` by adding a `bool EmailConfirmed {get;set;}` field.
2. When user signs up, an email is sent to the user with a secret token. This token is stored somewhere.
3. When the user clicks on the link ([https://blabla.com/auth/email?token=abcdef](https://blabla.com/auth/email?token=abcdef)), the `EmailConfirmationAuthProvider.PreAuthenticate` will mark the `CustomUserAuth.EmailConfirmed` as true if the token is valid and not expired. The token is deleted so impossible to authenticate again with that token.
4. I don't know how to add the `EmailConfirmed = true` to the session, nor how to add it on subsequent logins. And I don't know how not to get in the way of other authentication mechanisms.
EmailConfirmationService1. (Same steps as 1.1 and 1.2)
2. When the user clicks on the link ([https://blabla.com/email-confirmation?token=abcdef](https://blabla.com/email-confirmation?token=abcdef)), the `EmailConfirmationService` will mark the `CustomUserAuth.EmailConfirmed` as true if the token is valid and not expired. Token is deleted and impossible to re-use the same token.
3. I don't know how the session can be re-populated from the `CustomUserAuth`, especially if the user is already authenticated with a JWT token (if `JwtAuthProvider` is part of the `AuthFeature.AuthProviders`). I want to find a way to add a EmailConfirmed flag to the session for all subsequent logins of that user. I didn't find how to "modify" the JWT token (by adding a EmailConfirmed = true), and send it back as a cookie so that it's not necessary to check if the email is confirmed on every request.
基本上,我想限制访问所有标记为[Authenticate]的服务的用户已经确认了他们的电子邮件地址。如果我错了,请纠正我,但这应该只适用于使用凭据注册的用户(如果用户登录GoogleAuthProvider.则不应使用电子邮件确认)。还是应该这样?)
这条规则的例外情况是,某些服务(标记为属性(比如[AllowUnconfirmedEmail]) )允许用户向他们的地址重新发送确认邮件(比如他们输入了错误的电子邮件地址)。EmailConfirmationService允许通过身份验证的用户向新地址发送新的确认信息。一旦该确认电子邮件被点击,CustomUserAuth.Email & CustomUserAuth.PrimaryEmail将被更新使用新的地址。
发布于 2019-05-07 03:55:01
请参考ServiceStack认证文档中的高级图表来解释基于会话的Auth提供者和Auth提供者是如何工作的.
这些问题中有很多是内部实现细节,当不同的Auth提供者需要它们时,就会调用它们。可以添加要在会议和8月活动中发布的自定义逻辑的用户可重写事件。
PreAuthenticate()由Auth提供者调用,它对每个请求进行身份验证,比如API密钥和JWT Auth提供程序。通过Authenticate()提供程序进行身份验证时会调用/auth。
实施am电子邮件确认
实现用户需要确认的电子邮件的最简单方法可能是实现一个自定义UserSession验证,如下所示:
public class CustomUserSession : AuthUserSession
{
public override IHttpResult Validate(IServiceBase authService, IAuthSession session,
IAuthTokens tokens, Dictionary<string, string> authInfo)
{
using (var db = HostContext.AppHost.GetDbConnection(authService.Request))
{
var userAuthId = int.Parse(session.UserAuthId);
if (!db.Exists<CustomUserAuth>(x => x.Id == userAuthId && x.EmailConfirmed))
return HttpError.Conflict($"Email not confirmed") as IHttpResult;
}
return null;
}
}因此,它只允许身份验证,如果用户有一个确定的电子邮件地址。
有关如何使用带有其他元数据(如扩展UserAuth表 )的自定义UserAuth表,请参见EmailConfirmed。
然后,您的电子邮件服务将是一个服务,它接受一个随机字符串,如Guid (无论是在CustomUserAuth中还是在一个单独的表中),这些字符串引用了哪些用户已经确认了他们的电子邮件。或者,电子邮件中的链接可以再次包含电子邮件,在这种情况下,您可以将其与CustomUserAuth表中的CustomUserAuth字段中的现有电子邮件进行匹配。
如果要在同一个请求中对用户进行身份验证,则可以通过以下方式配置未经过密码验证的请求来允许CredentialsAuthProvider:
new CredentialsAuthProvider {
SkipPasswordVerificationForInProcessRequests = true,
}它将允许您在同一个“进程中”请求中使用用户名进行身份验证:
using (var service = base.ResolveService<AuthenticateService>()) //In Process
{
return service.Post(new Authenticate {
provider = AuthenticateService.CredentialsProvider,
UserName = request.UserName,
UseTokenCookie = true, // if using JWT
});
}您可以使用只使用HTTP会话验证用户身份的UseTokenCookie,尽管不需要使用JWT。
这个解决方案并不是必需的,但是您可以通过实现CreatePayloadFilter向JWT令牌添加额外的信息,并通过实现PopulateSessionFilter在用户会话中填充额外的元数据。
我不知道如何将EmailConfirmed = true添加到会话中
您可以通过在自定义UserSession上实现OnAuthenticated()来填充AuthUserSession。
基本上,我希望限制用户访问所有被标记为身份验证的服务,这些用户已经确认了他们的电子邮件地址。
如上文所述,在自定义AuthUserSession中覆盖AuthUserSession将确保只有已确认电子邮件的用户才能进行身份验证。
对于某些服务,这条规则的例外情况是
没有“部分身份验证用户”的概念,您可以进行身份验证(并将经过身份验证的UserSession附加到请求或缓存中),或者没有。我只允许认证,如果他们已经确认了他们的电子邮件,只有更新他们的确认电子邮件,如果他们已经确认了他们的建议电子邮件,他们想要更改为。
https://stackoverflow.com/questions/56014658
复制相似问题