我已为我的身份验证实现了自定义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;
}
}
答案 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]
属性的解决方案感兴趣。