Сеанс 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
{
}

Решение (для этой проблемы):

  1. Сохраните сеансовые куки в клиентском приложении и восстанавливайте их перед каждым вызовом Webservice.
  2. Используйте 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>

Обновить:

  1. Посмотрев на ваш код использования, предоставленный в вашем редактировании. Вы вызываете метод 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( ...
    
  2. Вы также пытаетесь разрешить другой сервис в вашем сервисе, используя:

    base.TryResolve<EService>();
    

    Вам нужно использовать это вместо этого, или вы увидите Only ASP.NET Requests accessible via Singletons are supported исключение:

    base.ResolveService<EService>();
    
Другие вопросы по тегам