简体   繁体   English

自托管服务器中的ServiceStack会话为null

[英]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). 有有问题的SessionServiceSessionnull的第二个电话(解决了,看到帖子的底部)。

I have self-hosted server and client that makes calls to server via JsonServiceClient and ProtoBufServiceClient . 我有自托管的服务器和客户端,它们通过JsonServiceClientProtoBufServiceClient调用服务器。

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请求。

My AppHost.cs 我的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());

Goal: 目标:

Send some variables from client and remember them on host until user logs off. 从客户端发送一些变量,并在主机上记住它们,直到用户注销为止。

Edit: 编辑:

My Workflow looks like this: 我的工作流程如下所示:

SomeClass1: SomeClass1:

  • new auth service client->Post(new Auth(...)); 新的身份验证服务客户端->发布(新的身份验证(...)); // login ok //登录确定
  • nothing more 而已

SomeClass2: SomeClass2:

  • new service client->Put(new E); 新服务客户-> Put(new E); // some init. //一些初始化。
  • service client->Get(new G); 服务客户端->获取(新G);

Service G: 服务G:

  • on G request new service client TryResolve(); 在G上请求新服务客户端TryResolve();
  • client->Get(new W) 客户端->获取(新W)

Service E 服务E

  • on E request CustomUserSession accessible 在E请求上CustomUserSession可访问
  • on W request CustomUserSession not accessible. 在W请求上,CustomUserSession无法访问。

My Custom* classes looks like in Scott answer. 我的Custom *类看起来像Scott的答案。

Edit: 编辑:

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
{
}

Solution (for this problem): 解决方案(针对此问题):

  1. Save session cookies in client application and restore them before every call to Webservice. 将会话cookie保存在客户端应用程序中,并在每次调用Webservice之前将其还原。
  2. Use Service::Resolve() instead of Service::TryResolve 使用Service :: Resolve()代替Service :: TryResolve

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. 我创建了一个简单的自托管应用程序,该应用程序还使用了CustomUserSessionCustomCredentialsAuthProvider ,希望以此为指南将突出显示出问题所在。 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>

Update: 更新:

  1. 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( ... 
  2. 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.

相关问题 具有每个请求生存期范围的ServiceStack自托管应用程序 - ServiceStack self-hosted application with per-request lifetime scope 具有嵌入式images / css的ServiceStack Razor(自托管) - ServiceStack Razor (self-hosted) with embedded images/css 在自托管控制台应用程序中使用ServiceStack Mini Profiler - Using ServiceStack Mini Profiler in self-hosted console application 具有SSO的自托管WCF服务器 - Self-hosted WCF Server with SSO 自托管WCF数据服务中的会话支持 - Session support in self-hosted WCF Data Service 如何在自托管服务器中的某些条件下跳过基本身份验证? - How to skip Basic Authentication on certain conditions in self-hosted server? 自托管的Katana服务在SQL Server连接上实现模拟? - Self-hosted Katana service implement impersonation on a SQL Server connection? 如何在自托管 CoreWCF 服务器中获取调用者身份? - How to get caller identity in a self-hosted CoreWCF server? 如何在Windows上运行的自托管ServiceStack中获取用户名 - How do I get the username in a self-hosted ServiceStack running on Windows 如何在自托管 (AppSelfHostBase) 服务堆栈服务 (RequestStream) 上设置文件大小限制? - How to set a file size limit on a self-hosted (AppSelfHostBase) Servicestack service (RequestStream)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM