我已经实现了自定义AuthenticateAttribute,AuthUserSession和CredentialsAuthProvider。在我的AuthenticateAttribute的Execute方法中,我做了:
public override void Execute(IRequest request, IResponse response, object requestDto)
{
var session = request.GetSession() as IMyCustomAuthUserSession;
// Copy certain request headers into a dictionary on my session object
}
我需要存储一些特殊的标题,这些标题会发送给我以供日后使用。未启用身份验证时,此操作正常。启用身份验证并且用户必须登录时,我的CredentialsAuthProvider类的TryAuthenticate方法将触发:
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
var session = authService.GetSession() as IMyCustomAuthUserSession;
}
这些to方法中的会话不一样,因为我在TryAuthenticate方法中获得的会话 - 在AuthenticateAttribute.Execute方法之后触发 - 不包含我存储在那里的头文件。
特殊标题仅在第一次调用Web服务器时发送,因此我需要将它们放入TryAuthenticate方法的新会话中。
我该怎么做?
答案 0 :(得分:1)
在登录之间传递会话数据将很困难,因为会话在身份验证尝试之间失效。通过使用以下命令配置AuthFeature
插件,您可以选择在登录之间保留相同的会话Cookie。
Plugins.Add(new AuthFeature(...) {
GenerateNewSessionCookiesOnAuthentication = false
});
登录时会保留相同的用户ss-id/ss-pid
Cookie。
如果要在经过身份验证的用户会话之外保留数据,您可以use a SessionBag,例如:
//Save
base.SessionBag["cart"] = new Cart { ... };
//Retrieve
var cart = base.SessionBag.Get<Cart>("cart");
另一种解决方案是在自定义Cookie下保留数据,这样在身份验证期间它不会被ServiceStack无效。
您可以注册全局请求过滤器以确保每个客户端/浏览器都具有自定义Cookie ID,例如:
GlobalRequestFilters.Add((req,res,dto) => {
var uniqueId = SessionExtensions.CreateRandomSessionId();
var httpRes = res as IHttpResponse;
httpRes.Cookies.AddPermanentCookie("my-id", uniqueId);
req.Items["my-id"] = uniqueId; //if also needed for this request
});
然后,在后续请求中,您可以在唯一的Cookie ID下保留数据,例如:
var uniqueId = req.GetSessionParam("my-id");
var cacheKey = $"urn:Cart:{uniqueId}";
var cache = req.GetCacheClient();
cache.Set(cacheKey, new Cart { ... });
然后用以下方法检索它:
var uniqueId = req.GetSessionParam("my-id");
var cacheKey = $"urn:Cart:{uniqueId}";
var cache = req.GetCacheClient();
var cart cache.Get<Cart>(cacheKey);