3

我已经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;
    }
}

服务栈版本: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;
    }
}
4

2 回答 2

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;
}
于 2014-06-12T09:20:21.997 回答
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]属性的解决方案感兴趣。

于 2014-01-14T22:24:09.103 回答