我创建了自己的CustomUserSession,它扩展了AuthUserSession,因此允许我覆盖onAuthenticated并设置一些额外的属性。
我已经注册了我的CustomUserSession,如下所示:
public override void Configure(Funq.Container container)
{
Plugins.Add(new AuthFeature(
() => new CustomUserSession(),
new IAuthProvider[] { new BasicAuthProvider(),
new CredentialsAuthProvider()
}));
当我登录使用CustomUserSession的服务时,一切正常,即我可以看到一个条目被添加到分布式缓存表(CacheEntry)。
但是,当我在配置为使用分布式缓存的第二个(微)服务上调用安全方法时,我收到401 HTTP状态代码(未授权)。
如果我使两个服务都使用AuthUserSession,那么分布式缓存工作正常,我可以在已登录第一个服务的第二个服务上调用安全方法。
这似乎是ServiceStack中的缺陷/问题,即分布式缓存不能与CustomUserSession一起使用?
在实现CustomUserSession时,是否有已知的解决方法或其他方法可以使分布式缓存工作?
根据需要添加更多信息,我的CustomUserSession如下:
public class CustomUserSession : AuthUserSession
{
public bool ProfileCompleted { get; set; }
public bool RegistrationVerified { get; set; }
public IUserAuthManager UserAuthManager { get; set; }
public IRegistrationManager RegistrationManager { get; set; }
public CustomUserSession()
{
HostContext.Container.AutoWire(this);
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo)
{
base.OnAuthenticated(authService, session, tokens, authInfo);
// Check if user profile has been completed
ProfileCompleted = UserAuthManager.ProfileIsComplete(session);
// Check if the user has verified their comms details
RegistrationVerified = UserAuthManager.RegistrationIsVerified(session);
}
public override void OnRegistered(IServiceBase registrationService)
{
base.OnRegistered(registrationService);
var regDto = registrationService.Request.Dto as Register;
if (regDto != null)
{
RegistrationManager.ProcessNewRegistration(regDto);
}
else
{
throw new NullReferenceException("Registration DTO NULL Reference");
}
}
}
服务1的我的AppHost配置方法如下:
public override void Configure(Funq.Container container)
{
Plugins.Add(new AuthFeature(
() => new CustomUserSession(),
new IAuthProvider[] { new BasicAuthProvider(),
new CredentialsAuthProvider()
}));
//Register global CORS Headers
Plugins.Add(new CorsFeature());
Plugins.Add(new RegistrationFeature());
Plugins.Add(new ValidationFeature());
AddGlobalResponseFilter();
SetupAutoMapper();
container.RegisterAs<CustomRegistrationValidator, IValidator<Register>>();
container.RegisterValidators(typeof(AppHost).Assembly);
container.RegisterAs<OrmLiteCacheClient, ICacheClient>();
var connStr = RoleEnvironment.GetConfigurationSettingValue("UserAuthConnStr");
container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(connStr, SqlServerOrmLiteDialectProvider.Instance));
container.Register<IUserAuthRepository>(c => new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));
var userStore = (OrmLiteAuthRepository)container.Resolve<IUserAuthRepository>();
//Create 'CacheEntry' RDBMS table if it doesn't exist already
container.Resolve<ICacheClient>().InitSchema();
RegisterProfileComponents(container);
RegisterExtendedRegComponents(container);
CreateAuthTables(userStore);
ConfigureMessageQueue(container);
}
以下是我的GlobalResponseFilter:
private void AddGlobalResponseFilter()
{
GlobalResponseFilters.Add((httpReq, httpResp, requestDto) =>
{
if (httpReq.OperationName == "Authenticate")
{
if (!httpResp.IsClosed)
{
httpResp.AddHeader("Profile-Complete", ((CustomUserSession)httpReq.GetSession()).ProfileCompleted.ToString());
httpResp.AddHeader("Reg-Verified", ((CustomUserSession)httpReq.GetSession()).RegistrationVerified.ToString());
}
}
});
}
我的第二个(微)服务配置方法包含以下内容:
Plugins.Add(new AuthFeature(
() => new AuthUserSession(),
new IAuthProvider[] {new CredentialsAuthProvider()
}));
//Register global CORS Headers
Plugins.Add(new CorsFeature());
container.RegisterAs<OrmLiteCacheClient, ICacheClient>();
container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(RoleEnvironment.GetConfigurationSettingValue("UserAuthConnStr"), SqlServerOrmLiteDialectProvider.Instance));
container.Register<IUserAuthRepository>(c => new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));
container.Resolve<ICacheClient>().InitSchema();
请注意,第二个服务使用标准的AuthUserSession,只有第一个服务使用CustomUserSession。
我可以在Chrome Rest控制台&amp; Fiddler认为SessionId正在正确传递给第二个服务,但我仍然得到了401响应。
如果我将第一个服务更改为使用标准的AuthUserSession,则一切正常。
**请参阅下面的REQUEST&amp;返回401时的RESPONSE内容:
REQUEST:
GET http://localhost:8088/exercise/analytics?DateFrom=01%2F01%2F2014 HTTP/1.1
Host: localhost:8088
Connection: keep-alive
Accept: application/json
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Cookie: ss-id=X83GVWXwyMHIWXEw6X1k; ss-pid=ABjuJFUqyHkMUvI7ssyv; X-UAId=10005
响应:
HTTP/1.1 401 Unauthorized
Transfer-Encoding: chunked
Vary: Accept
Server: Microsoft-HTTPAPI/2.0
X-Powered-By: ServiceStack/4.022 Win32NT/.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
WWW-Authenticate: credentials realm="/auth/credentials"
Date: Wed, 30 Jul 2014 22:00:44 GMT
0
此致 约翰