[英]ServiceStack Session is null in self-hosted server
There is problem with Session
in Service
, Session
is null
on second call (solved, see bottom of the post). 有有问题的
Session
中Service
, Session
是null
的第二个电话(解决了,看到帖子的底部)。
I have self-hosted server and client that makes calls to server via JsonServiceClient
and ProtoBufServiceClient
. 我有自托管的服务器和客户端,它们通过
JsonServiceClient
和ProtoBufServiceClient
调用服务器。
On start of client application I call: 在客户端应用程序启动时,我致电:
var baseUrl = ConfigGlobal.Host ;
var client = new JsonServiceClient(baseUrl);
var authResponse = client.Post<AuthResponse>("/auth", new Auth
{
UserName = "test1",
Password = "password",
RememberMe = true
});
It works - OnAuthenticated
it's fired in my CustomUserSession : AuthUserSession
. 它的工作原理-
OnAuthenticated
它在我的射击CustomUserSession : AuthUserSession
。
authService.SaveSession(session);
didn't help. 没有帮助。
Then in one class: 然后在一堂课中:
var client = new ProtoBufServiceClient(ConfigGlobal.Host);
client.Put(new ExcelInitialize {Filename = ""}); // OK
Model = client.Get(...); // Session is null
There is a problem in service class in Get
method Session is null
. Get
方法中的服务类中存在问题Session为null
。 If I implement 如果我实施
public CustomUserSession CustomUserSession
{
get
{
return SessionAs<CustomUserSession>();
}
}
I'll get: Only ASP.NET Requests accessible via Singletons are supported. 我将得到:仅支持通过Singleton访问的ASP.NET请求。
container.Register<ICacheClient>(new MemoryCacheClient());
container.Register<ISessionFactory>(c => new SessionFactory(c.Resolve<ICacheClient>()));
Plugins.Add(new AuthFeature(
() => new CustomUserSession(), new IAuthProvider[]
{
new CustomCredentialsAuthProvider(),
new BasicAuthProvider(),
}));
Plugins.Add(new RegistrationFeature());
Send some variables from client and remember them on host until user logs off. 从客户端发送一些变量,并在主机上记住它们,直到用户注销为止。
My Workflow looks like this: 我的工作流程如下所示:
SomeClass1: SomeClass1:
SomeClass2: SomeClass2:
Service G: 服务G:
Service E 服务E
My Custom* classes looks like in Scott answer. 我的Custom *类看起来像Scott的答案。
Here is the code of my problem ready to copy&paste: 这是我要复制并粘贴的问题代码:
private static void Main(string[] args)
{
// Very basic console host
var appHost = new AppHost();
appHost.Init();
appHost.Start("http://*:8082/");
var url = "http://localhost:8082";
var foo = new TestApp.SomeClass1(url);
var bar = new TestApp.SomeClass2(url);
Console.ReadKey();
}
public class AppService : Service
{
public CustomUserSession CustomUserSession
{
get
{
// Returns the typed session
return SessionAs<CustomUserSession>();
}
}
}
public class GService : AppService
{
public object Get(GRequest request)
{
var client = base.TryResolve<EService>();
client.Get(new WRequest());
return new { CustomUserSession.SuperHeroIdentity };
}
}
public class EService : AppService
{
public void Get(WRequest wRequest)
{
Console.WriteLine(CustomUserSession.SuperHeroIdentity);
}
public void Get(ERequest request)
{
Console.WriteLine(CustomUserSession.SuperHeroIdentity);
}
public void Put(ERequest request)
{
Console.WriteLine(CustomUserSession.SuperHeroIdentity);
}
}
public class SomeClass1
{
public SomeClass1(string url)
{
var client = new JsonServiceClient(url);
client.Post<AuthResponse>("/auth", new Auth
{
UserName = "clark.kent",
Password = "kryptonite",
RememberMe = true
});
}
}
public class SomeClass2
{
public SomeClass2(string url)
{
var client = new JsonServiceClient(url);
client.Put(new ERequest());
client.Get(new GRequest());
}
}
public class GRequest : IReturnVoid
{
}
public class ERequest : IReturnVoid
{
}
public class WRequest : IReturnVoid
{
}
The code you have posted looks okay to me. 您发布的代码对我来说还不错。 So it's likely something trivial with your setup.
因此,这可能与您的设置无关紧要。
I have created a simple, self hosted app which also uses a CustomUserSession
and a CustomCredentialsAuthProvider
, hopefully using this as a guide will highlight what is going wrong. 我创建了一个简单的自托管应用程序,该应用程序还使用了
CustomUserSession
和CustomCredentialsAuthProvider
,希望以此为指南将突出显示出问题所在。 Let me know how you get on. 让我知道你是怎么办的。
using ServiceStack.CacheAccess;
using ServiceStack.CacheAccess.Providers;
using ServiceStack.ServiceInterface;
using ServiceStack.ServiceInterface.Auth;
using ServiceStack.ServiceHost;
using ServiceStack.WebHost.Endpoints;
namespace Testv3
{
class MainClass
{
public static void Main()
{
// Very basic console host
var appHost = new AppHost();
appHost.Init();
appHost.Start("http://*:8082/");
Console.ReadKey();
}
}
public class AppHost : AppHostHttpListenerBase
{
public AppHost() : base("Test Service", typeof(TestApp).Assembly) {}
public override void Configure(Funq.Container container)
{
// Cache and session IoC
container.Register<ICacheClient>(new MemoryCacheClient());
container.Register<ISessionFactory>(c => new SessionFactory(c.Resolve<ICacheClient>()));
// Register the Auth Feature with the CustomCredentialsAuthProvider.
Plugins.Add(new AuthFeature(
() => new CustomUserSession(),
new IAuthProvider[]
{
new CustomCredentialsAuthProvider(),
new BasicAuthProvider(),
})
);
}
}
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
// Replace with a database lookup
return (userName == "clark.kent" && password == "kryptonite");
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
var customSession = session as CustomUserSession;
if(customSession != null)
{
// Replace these static values with a database lookup
customSession.FirstName = "Clark";
customSession.LastName = "Kent";
customSession.SuperHeroIdentity = "Superman";
}
authService.SaveSession(customSession, SessionExpiry);
}
}
public class CustomUserSession : AuthUserSession
{
// Our added session property
public string SuperHeroIdentity { get; set; }
}
public static class TestApp
{
[Route("/SuperHeroTime", "GET")]
public class SuperHeroTimeRequest {}
public class TestController : Service
{
public CustomUserSession CustomUserSession
{
get
{
// Returns the typed session
return SessionAs<CustomUserSession>();
}
}
[Authenticate]
public object Get(SuperHeroTimeRequest request)
{
// Return the result object
return new { CustomUserSession.FirstName, CustomUserSession.LastName, Time = DateTime.Now.ToString(), CustomUserSession.SuperHeroIdentity };
}
}
}
}
If you put this index.html
in your bin
folder and navigate to http://localhost:8082/index.html
you can call the service, to test it. 如果将此
index.html
放在bin
文件夹中并导航到http://localhost:8082/index.html
,则可以调用该服务以对其进行测试。
<!doctype html>
<html>
<head>
<title>Test</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
function login()
{
$.ajax({
type: "POST",
url: "/auth/credentials",
contentType: "application/json",
data: JSON.stringify({
UserName: "clark.kent",
Password: "kryptonite",
RememberMe: true
})
}).done(function(result){
getSuperHeroTime();
});
}
function getSuperHeroTime()
{
$.ajax({
type: "GET",
url: "/SuperHeroTime",
contentType: "application/json",
}).done(function(result){
$("#result").html(result.FirstName + " " +
result.LastName + " is " +
result.SuperHeroIdentity + " (" +
result.Time + ")");
});
}
</script>
</head>
<body>
<h1>Super Hero Time</h1>
<button onclick="login()">Go</button>
<div id="result"></div>
</body>
</html>
Having looked at your usage code provided in your edit. 查看了您在编辑中提供的使用代码。 You are calling the Auth method in
SomeClass1
and then that JsonServiceClient
isn't reused. 您在
SomeClass1
中调用Auth方法,然后JsonServiceClient
不被重用。 So your session won't follow. 因此,您的会话将不会进行。 You have to reuse the client, because the client stores the cookies that track your session.
您必须重用客户端,因为客户端存储了跟踪您的会话的cookie。
In SomeClass2
you are effectively calling the service without authenticating, so the session is null
. 在
SomeClass2
您无需进行身份验证即可有效地调用服务,因此会话为null
。 You need to reuse the same JsonServiceClient
for your requests. 您需要为请求重用相同的
JsonServiceClient
。
You could run your authentication method and then pass the session cookies to any subsequent JsonServiceClient
, to save re-authenticating with each client. 您可以运行身份验证方法,然后将会话cookie传递给任何后续的
JsonServiceClient
,以保存与每个客户端的重新身份验证。 It's easy to do: 很容易做到:
var authClient = new JsonServiceClient(url); authclient.Post<AuthResponse>("/auth", new Auth { UserName = "clark.kent", Password = "kryptonite", RememberMe = true }); // Get the session cookies var cookies = authClient.CookieContainer.GetCookies(new Uri(url)); // In your other `JsonServiceClient`s set the cookies before making requests var anotherClient = new JsonServiceClient(url); anotherClient.CookiesCollection.add(cookies); anotherClient.Post( ...
You are also trying to resolve another service within your service using: 您还尝试使用以下方法在服务中解析其他服务:
base.TryResolve<EService>();
You need to use this instead, or you will see the Only ASP.NET Requests accessible via Singletons are supported
exception: 您需要改用此方法,否则将看到“
Only ASP.NET Requests accessible via Singletons are supported
例外:
base.ResolveService<EService>();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.