基于cookie的会话/身份验证的替代方案

8

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

2个回答

7

我使用ServiceStack,但没有使用内置的auth和session提供程序。

我使用一个属性作为请求过滤器,从cookie、请求头或字符串参数中收集用户信息(id和token)。 您可以在用户登录后提供此信息。您可以将一个新的cookie附加到响应中,并在渲染视图时在客户端注入id和token信息,因此您可以用于链接的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作为查询参数传递,并通过表单的隐藏输入传递它们,例如。

4

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

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

当用户得到授权时,我获取Cookie并通过使用HTTP标头将其发送到客户端。现在,如果请求的HTTP标头(Authorization)中设置了Cookie,则客户端可以调用服务。

为了实现这一点,我使用PreRequestFilter将虚假的授权标头重定向到请求的Cookie。现在我能够使用会话功能。感觉像是一个hack,但目前起作用 ;-)

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);
                }
            });
    }
}

谢谢,这是我通过Ajax / Angular实现CORS的最后一步,使我能够获取在我的Auth调用中返回的会话ID,并将其添加为相应Ajax调用中的自定义标头,然后无需在服务堆栈中创建自定义身份验证提供程序即可使用标准提供程序来获取标头而不是cookie。 - James Eby

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