8

servicestack中的会话功能插件是否有替代品?在某些情况下,我无法使用 cookie 来匹配我的服务实现中的授权会话。是否有可能使用请求的 http 标头中的令牌来解析会话?如果浏览器阻止 cookie,首选的解决方案是什么?

4

2 回答 2

7

我正在使用没有内置身份验证和会话提供程序的 ServiceStack。

我使用属性作为请求过滤器来从 cookie、请求标头或字符串参数中收集用户信息(id 和令牌)。您可以在用户登录后提供此信息。您在响应中附加一个新的 cookie,并在呈现视图时在客户端注入 id 和令牌信息,因此您可以将其用于 http 标头和链接的查询参数。

public class AuthenticationAttribute : Attribute, IHasRequestFilter 
{
    public void RequestFilter(IHttpRequest request, IHttpResponse response, object dto)
    {
        var userAuth = new UserAuth { };
        if(!string.IsNullOrWhiteSpace(request.GetCookieValue("auth"))
        {
            userAuth = (UserAuth)request.GetCookieValue("auth");

        } 
        else if (!string.IsNullOrEmpty(request.Headers.Get("auth-key")) &&
            !string.IsNullOrEmpty(request.Headers.Get("auth-id")))
        {
            userAuth.Id = request.Headers.Get("id");
            userAuth.Token = request.Headers.Get("token");
        }
        authenticationService.Authenticate(userAuth.Id, userAuth.token);
    }
    public IHasRequestFilter Copy()
    {
        return new AuthenticationAttribute();
    }
    public int Priority { get { return -3; } } // negative are executed before global requests 
}

如果用户未获得授权,我会在此时重定向他。

我的项目支持 SPA。如果用户使用 xmlhttprequests 使用 API,则身份验证内容通过标头完成。当页面加载时,我在 AngularJS 上注入这些信息,并在所有请求(部分视图、api 消耗等)上重用它。ServiceStack 对这种类型的东西非常强大,您可以轻松地配置您的 AngularJS 应用程序和 ServiceStack 视图引擎以并行工作,验证每个请求,全球化您的应用程序等。

如果您没有 cookie 并且请求不是由 javascript 调用的,您可以支持没有 cookie 的身份验证,如果您始终生成将 id 和 token 作为查询参数传递的链接,并通过表单上的隐藏输入传递它们,例如例子。

于 2013-06-01T17:57:55.377 回答
4

@Guilherme Cardoso:在我当前的解决方案中,我使用的是 PreRequestFilters 和内置会话功能。

我的工作流程/解决方法如下:

当用户获得授权时,我获取了 cookie 并使用 http 标头将其发送给客户端。现在,如果在请求的 http-header(授权)中设置了 cookie,则客户端可以调用服务。

为此,我使用 PreRequestFilter 将伪造的授权标头重定向到请求的 cookie。现在我可以使用会话功能了。感觉像一个黑客,但暂时有效;-)

public class CookieRestoreFromAuthorizationHeaderPlugin : IPlugin
{
    public void Register(IAppHost appHost)
    {
        appHost.PreRequestFilters.Add((req, res) =>
            {
                var cookieValue = req.GetCookieValue("ss-id");

                if(!string.IsNullOrEmpty(cookieValue))
                    return;

                var authorizationHeader = req.Headers.Get("Authorization");

                if (!string.IsNullOrEmpty(authorizationHeader) && authorizationHeader.ToLower().StartsWith("basictoken "))
                {
                    var cookie = Encoding.UTF8.GetString(Convert.FromBase64String(authorizationHeader.Split(' ').Last()));

                    req.Cookies.Add("ss-id",new Cookie("ss-id",cookie));
                    req.Items.Add("ss-id",cookie);
                }
            });
    }
}
于 2013-06-24T15:26:05.960 回答