如何在Redis中使用我的自定义ServiceStack身份验证提供程序?

时间:2014-01-08 13:19:30

标签: redis servicestack servicestack-bsd servicestack-auth

我已为我的身份验证实现了自定义CredentialsAuthProvider,并将其与内存会话存储中的默认值一起使用。

现在,我尝试将会话存储更改为Redis,并将其添加到Configure()中的AppHost方法:

container.Register<IRedisClientsManager>(c => 
    new PooledRedisClientManager("localhost:6379"));

container.Register<ICacheClient>(c => (ICacheClient)c
    .Resolve<IRedisClientsManager>()
    .GetCacheClient()).ReusedWithin(Funq.ReuseScope.None);

现在,当我进行身份验证时,我可以看到将urn:iauthsession:...的密钥添加到我的Redis服务器中。但是,[Authenticate]属性的所有路由都会出现401 Unauthorized错误。

CustomCredentialsAuthProvider的实现方式如下:

public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
    public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
    {
        if (userName != string.Empty && password != string.Empty)
        {
            // Database call ...
            var session = (CustomSession)authService.GetSession();
            session.ClientId = login.ClientId;
            // Fill session...
            authService.SaveSession(session, SessionExpiry);
            return true;
        }
        return false;
    }
}

ServiceStack版本:3.9.71

编辑:

我尝试覆盖CredentialsAuthProvider IsAuthorized方法,但没有成功。

但是我继承了AuthUserSession的会话对象,它也有IsAuthorized方法。当我从此方法返回true时,Redis会话可以使用Authenticate属性。

public class CustomSession : AuthUserSession
{
    public int ClientId { get; set; }
    ...

    public override bool IsAuthorized(string provider)
    {
        return true;
    }
}

2 个答案:

答案 0 :(得分:3)

Authenticate属性调用IsAuthorized类的AuthUserSession。 在我的情况下,为了使它与Redis缓存客户端一起工作,我已经完成了以下

public override bool IsAuthorized(string provider)
{
    string sessionKey = SessionFeature.GetSessionKey(this.Id);
    ICacheClient cacheClient = AppHostBase.Resolve<ICacheClient>();

    CustomUserSession session = cacheClient.Get<CustomUserSession>(sessionKey);

    if (session == null)
    {
        return false;
    }

    return session.IsAuthenticated;
}

答案 1 :(得分:1)

我无法找到让[Authenticate]属性与Redis存储配合使用的方法。

我必须编写自定义[SessionAuth]属性

public class SessionAuthAttribute : RequestFilterAttribute
{
    public ICacheClient cache { get; set; }
    public string HtmlRedirect { get; set; }

    public SessionAuthAttribute()
    {
    }

    public override void Execute(IHttpRequest req, IHttpResponse res, object requestDto)
    {
        string sessionId = req.GetSessionId();
        if (string.IsNullOrEmpty(sessionId))
        {
            HandleNoSession(req, res);

        }
        else
        {
            var session = cache.Get<CustomSession>("urn:iauthsession:" + sessionId);
            if (session == null || !session.IsAuthenticated)
            {

                HandleNoSession(req, res);
            }
        }
    }

    private void HandleNoSession(IHttpRequest req, IHttpResponse res)
    {

        if (req.ResponseContentType.MatchesContentType(MimeTypes.Html))
        {

            res.RedirectToUrl(HtmlRedirect);
            res.End();

        }
        res.StatusCode = (int)HttpStatusCode.Unauthorized;
        res.Write("not authorized");
        res.Close();
    }
}

在我的AppHost Configure()方法中,我只注册了SessionFeature和IRedisClientsManager / ICacheClient:

Plugins.Add(new SessionFeature());

container.Register<IRedisClientsManager>(c => new PooledRedisClientManager("localhost:6379"));

container.Register<ICacheClient>(c => (ICacheClient)c.Resolve<IRedisClientsManager>()
        .GetCacheClient()).ReusedWithin(Funq.ReuseScope.None);

CustomSession类继承自AuthUserSession:

public class CustomSession : AuthUserSession
{
    public int ClientId { get; set; }
    ...
}

我在/ login / auth上有一个正常的服务路由用于身份验证部分,而/ login / logout路由用于删除会话:

public class LoginService : Service
{
    public ICacheClient cache { get; set; }

    public object Post(AuthRequest request)
    {
        string userName = request.UserName;
        string password = request.Password;

        // check login allowed

        if (IsAllowed)
        {

            var session = SessionFeature.GetOrCreateSession<CustomSession>(cache);

            session.ClientId = login.ClientId;
            ...
            session.IsAuthenticated = true;
            session.Id = SessionFeature.GetSessionId();

            this.SaveSession(session, TimeSpan.FromSeconds(30 * 60));


            return true;
        }

        return false;
    }


    [SessionAuth]
    public object Any(LogoutRequest request)
    {
        this.RemoveSession();
        return true;
    }
}

}

我仍然对使用普通[Authenticate]属性的解决方案感兴趣。

相关问题