如何在 AuthUserSession 中存储 PreRequestFilter 信息

How to store PreRequestFilter information in AuthUserSession

我正在使用 ServiceStack 构建 Web 服务,它必须支持多个供应商。 Web 服务为所有供应商提供基本相同的功能,但有一些例外。

为了尽可能多地重复使用功能,我提出了以下 URL 方案:

http://localhost/brand1/templates
http://localhost/brand2/templates

"brand1" 和 "brand2" 不是服务,但 "templates" 是。模板服务的请求 DTO 将有一个名为 "Brand" 的 属性,如下所示:

[Route("/{Brand}/templates", "GET")]
public class GetTemplates
{
    public Brand Brand { get; set; }
}

所以在模板服务中我知道我在处理哪个品牌。这个方案效果不错。

我想不通的是这个。服务的用户必须经过身份验证,我无法弄清楚在用户经过身份验证后如何处理服务的重定向,因为我必须传递品牌信息。我创建了自己的 CustomAuthProvider class 继承了 CredentialsAuthProvider。在 TryAuthenticate 方法中,如果我知道它是什么,我可以将 authService.GetSession().ReferrerUrl 属性 设置为正确的品牌。

到目前为止,我发现获取此信息的唯一方法是注册 PreRequestFilter。我的想法是,由于 URL(例如 http://localhost/brand1/templates)包含我可以将其存储在我自己的 AuthUserSession class 中的品牌。我不知道该怎么做。我有一个传递给 AuthFeature 构造函数的 "SessionFactory" 方法。但是我应该在那里做什么?我如何获得我在 PreRequestFilter 中获得的品牌?将它存储在 AppHost 的字段中是否安全?我认为不是因为并发问题。如何将 PreRequestFilter 绑定到 SessionFactory 方法?

我希望我已经足够清楚地解释我的问题了吗?

您可以将 Url 设置为在 ServiceStack Authentication 期间重定向到的不同位置,按优先顺序排列如下:

  1. Session.ReferrerUrl Url 如果已填充
  2. /auth 发出请求时 Continue QueryString、FormData 参数(即 Authenticate.Continue 属性)
  3. HTTP Referer HTTP Header
  4. 当前AuthProvider使用的回调Url

我对解决方案想得太多了,因为我没有意识到我在 CredentialsAuthProvider 的 TryAuthenticate 方法的 IServiceBase 参数中拥有我需要的所有信息 class。

最后我得出以下解决方案:

public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
    public override bool TryAuthenticate(IServiceBase authService, 
               string userName, string password)
    {
        var session = authService.GetSession();
        var origQuery = authService.Request.UrlReferrer.Query;          

        session.ReferrerUrl = "/error";

        var queryString = origQuery.Substring(10);  // strip "redirect="
        var decodedUrl = HttpUtility.UrlDecode(queryString);

        if (!string.IsNullOrWhiteSpace(decodedUrl))
        {
            var query = new Uri(decodedUrl);
            session.ReferrerUrl = query.AbsolutePath;
        }

        return DoAuthentication(userName, password);
    }
}