Сеанс ServiceStack равен нулю на сервере, размещенном самостоятельно
Есть проблема с Session
в Service
, Session
является null
на второй звонок (решено, см. внизу поста).
У меня есть собственный сервер и клиент, который делает звонки на сервер через JsonServiceClient
а также ProtoBufServiceClient
,
При запуске клиентского приложения я звоню:
var baseUrl = ConfigGlobal.Host ;
var client = new JsonServiceClient(baseUrl);
var authResponse = client.Post<AuthResponse>("/auth", new Auth
{
UserName = "test1",
Password = "password",
RememberMe = true
});
Оно работает - OnAuthenticated
это уволено в моем CustomUserSession : AuthUserSession
,
authService.SaveSession(session);
не помогло
Тогда в одном классе:
var client = new ProtoBufServiceClient(ConfigGlobal.Host);
client.Put(new ExcelInitialize {Filename = ""}); // OK
Model = client.Get(...); // Session is null
Существует проблема в классе обслуживания в Get
Сессия метода null
, Если я реализую
public CustomUserSession CustomUserSession
{
get
{
return SessionAs<CustomUserSession>();
}
}
Я получу: Поддерживаются только запросы ASP.NET, доступные через Singletons.
Мой AppHost.cs
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());
Цель:
Отправьте некоторые переменные из клиента и запомните их на хосте, пока пользователь не выйдет из системы.
Редактировать:
Мой рабочий процесс выглядит так:
SomeClass1:
- новый клиент службы аутентификации->Post(новый Auth(...)); // логин в порядке
- ничего более
SomeClass2:
- новый сервис client->Put(новый E); // некоторая инициация
- обслуживание клиента->Get(новый G);
Служба G:
- по запросу G новый сервис клиента TryResolve();
- клиент-> Получить (новый W)
Сервис E
- на E запрос CustomUserSession доступен
- по запросу W CustomUserSession не доступен.
Мои пользовательские * классы выглядят как в ответе Скотта.
Редактировать:
Вот код моей проблемы, готовый для копирования и вставки:
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
{
}
Решение (для этой проблемы):
- Сохраните сеансовые куки в клиентском приложении и восстанавливайте их перед каждым вызовом Webservice.
- Используйте Service::Resolve() вместо Service::TryResolve
1 ответ
Код, который вы разместили, выглядит хорошо для меня. Так что, скорее всего, что-то тривиально с вашей настройкой.
Я создал простое, самостоятельно размещенное приложение, которое также использует CustomUserSession
и CustomCredentialsAuthProvider
Надеюсь, что использование этого руководства поможет вам понять, что происходит не так. Дайте мне знать, как вы поживаете.
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 };
}
}
}
}
Если вы положите это 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>
Обновить:
Посмотрев на ваш код использования, предоставленный в вашем редактировании. Вы вызываете метод Auth в
SomeClass1
и тогда этоJsonServiceClient
не используется повторно Так что ваша сессия не будет следовать. Вы должны повторно использовать клиента, потому что клиент хранит куки, которые отслеживают ваш сеанс.В
SomeClass2
Вы фактически вызываете сервис без аутентификации, поэтому сеансnull
, Вы должны повторно использовать то же самоеJsonServiceClient
для ваших запросов.Вы можете запустить свой метод аутентификации и затем передать куки сеанса любому последующему
JsonServiceClient
, чтобы сохранить повторную аутентификацию с каждым клиентом. Это легко сделать: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( ...
Вы также пытаетесь разрешить другой сервис в вашем сервисе, используя:
base.TryResolve<EService>();
Вам нужно использовать это вместо этого, или вы увидите
Only ASP.NET Requests accessible via Singletons are supported
исключение:base.ResolveService<EService>();