【问题标题】:ServiceStack: Accessing the HttpRequest in a selfhosted applicationServiceStack:在自托管应用程序中访问 HttpRequest
【发布时间】:2013-04-04 03:49:29
【问题描述】:

我目前有一个 IIS 托管应用程序,我想切换到使用自托管方法。

但我无法访问会话,因此我可以检索当前用户的用户名。

这是我在 IIS 下托管时使用的代码,效果很好:

/// <summary>
/// A basic wrapper for the service stack session, to allow access to it lower down in the DAL layer without tying us to servicestack.
/// </summary>
public class ServiceStackAuthTokenService : IAuthTokenService
{
    /// <summary>
    /// GetCurrentAuthToken.
    /// </summary>
    /// <returns>A string representing the users auth name.</returns>
    public string GetCurrentAuthToken()
    {
        // Grab the current request.
        var req = HttpContext.Current.Request.ToRequest();
        var res = HttpContext.Current.Response.ToResponse();

        // Fetch the authentication service.
        var authService = EndpointHost.AppHost.TryResolve<AuthService>();
        authService.RequestContext = new HttpRequestContext(req, res, null);

        // Grab the session.
        var session = authService.GetSession(false);

        // Return the username.
        return session.UserName;
    }

    public string UserPropertyName
    {
        get { return "UserName"; }
    }
}

这是使用以下代码添加到应用程序主机的::

container.RegisterAutoWiredAs<ServiceStackAuthTokenService, IAuthTokenService>()

运行自托管时,HttpContext.Current 为空,如何在自托管应用程序下访问请求?

谢谢!

更新 我尝试过的其他事情:

根据这里的帖子:https://groups.google.com/forum/#!msg/servicestack/jnX8UwRWN8A/_XWzTGbnuHgJ

建议使用:

container.Register>(c => AuthService.CurrentSessionFactory);

这只是返回一个新的 IAuthSession。

该帖子中的用户正在做的正是我想要实现的目标。

Mythz 在上一篇文章中说:

需要明确的是,为了形成引用用户会话的会话密钥,您需要 ss-id 或 ss-pid cookie(由 ss-opts 确定)。 您可以从 IHttpRequest 对象或 ASP.NET 中的 HttpContext.Current.Request 单例中获取 cookie,因此无论您注入的任何 IAuthUserSession 工厂都需要获取可以为其提供 cookie 的东西,即 IRequestContext、IHttpRequest、IService 等。

但我仍然看不到访问 IHttpRequest 的方法。

【问题讨论】:

  • GetCurrentAuthToken() 何时/何地在您的应用程序中被调用?如果它在服务中,您可以将 IHttpRequest 和 IHttpResponse 传递给 GetCurrentAuthToken(base.Request, base.Response) 等方法。
  • 您好 Paaschpa,它发生在与服务层没有直接关系的 DAL 层。我可以将上下文传递给 DAL,但这会违反设计并使每一层保持独立。
  • 进一步研究后,我可以看到 IHttpRequest 和 IHttpResponse 正在通过服务基类中的 IRequiresRequestContext 接口注入到服务中。我基本上希望能够访问相同的东西,这样我就可以访问存储客户端会话的缓存。
  • 使用反射器查看服务类我可以看到 if (this.userSession == null) { this.userSession = this.TryResolve(); if (this.userSession == null) { this.userSession = this.Cache.SessionAs(this.Request, this.Response); } } return (TUserSession)((object)this.userSession);这段代码似乎表明,会话可以通过缓存访问。

标签: session authentication servicestack


【解决方案1】:

对于 ServiceStack 3,您可以通过 HostContext.Instance.Items Dictionary 共享请求数据。对于 ServiceStack 4,您应该使用 HostContext.RequestContext.Items 字典。

例如,在您的应用主机配置中添加请求过滤器以保存值:

// Put the session into the hostcontext.
RequestFilters.Add((req, res, requestDto) =>
{
  HostContext.Instance.Items.Add("Session", req.GetSession());
});

然后在您的身份验证令牌类中将其拉出:

public string GetCurrentAuthToken()
{
  var session = HostContext.Instance.Items["Session"] as AuthUserSession;

   if (session != null)
   {
     return session.UserName;
   }

   throw new Exception("No attached session found.");
}

【讨论】:

  • HostContext.Instance 真的是每个请求吗?
  • 据我所知,确实如此。在每次请求时,它似乎都是空的,并且没有保留来自先前调用的信息。在 servictstack 源中 (AppHostBase.cs) 中有这个,这表明它在每个请求时都被清空。 public virtual void OnEndRequest() { foreach (var item in HostContext.Instance.Items.Values) { Release(item); } HostContext.Instance.EndRequest();但就像所有事情一样,不妨试一试,看看是否适合你。
  • 那么如何将内容保存回会话中?
  • 说实话,我不确定。我希望 Mythz 能加入进来,给我们一些额外的信息。由于我一直很忙,所以我已经有一段时间没有做这个了,但是如果我遇到并回答我会提供更多信息。
  • 我知道这是一个旧帖子,但人们似乎反对它。这对我来说表明他们知道更好的方法,否则这是不正确的。如果是这种情况,我很想知道正确的做法是什么,或者为什么投反对票。
猜你喜欢
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多