ServiceStack: 在自托管应用程序中访问HttpRequest

7

我目前有一个托管在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
嗨Paaschpa,这发生在DAL层,它与服务层没有直接关系。我可以将上下文传递到DAL中,但那会违反设计原则并使每个层保持独立。 - Rtype
进一步查看后,我发现通过IRequiresRequestContext接口将IHttpRequest和IHttpResponse注入到服务中,该接口位于服务基类中。我基本上想要能够访问相同的内容,以便我可以访问客户端会话存储的缓存。 - Rtype
使用反射器查看服务类,我可以看到:如果 (this.userSession == null) { this.userSession = this.TryResolve<TUserSession>(); 如果 (this.userSession == null) { this.userSession = this.Cache.SessionAs(this.Request, this.Response); } } return (TUserSession)((object)this.userSession);这段代码似乎表明,会话可通过缓存访问。 - Rtype
1个回答

10

对于 ServiceStack 3,您可以通过 HostContext.Instance.Items 字典共享请求数据。对于 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 是否真的是每个请求都独立的? - Rebecca
1
据我所知,它似乎是空的。每次请求时,它都为空,并且没有保留先前调用的任何信息。在servictstack源代码中,有这个(AppHostBase.cs),这表明它在每个请求上都被清空。public virtual void OnEndRequest() { foreach (var item in HostContext.Instance.Items.Values) { Release(item); } HostContext.Instance.EndRequest(); }但像所有事物一样,也许可以尝试一下,看看是否适合您。 - Rtype
那么如何将东西保存回会话中呢? - fractal
说实话,我不确定。我希望Mythz能够加入并提供更多信息。我已经有一段时间没有处理这个问题了,因为我很忙,但如果我找到答案,我会提供更多信息。 - Rtype
我知道这是一篇旧帖子,但人们似乎在对它进行投票。这让我觉得他们知道更好的方法或者这不正确。如果是这样的话,我很想听听正确的方法是什么,或者为什么会有负面评价。 - Rtype
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接