1

Sessionin有问题ServiceSession正在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方法 Session is中的服务类存在问题null。如果我实施

 public CustomUserSession CustomUserSession
 {
    get
    {
       return SessionAs<CustomUserSession>();
    }
 }

我会得到:仅支持通过单例访问的 ASP.NET 请求。

我的 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());

目标:

从客户端发送一些变量并在主机上记住它们,直到用户注销。

编辑:

我的工作流程如下所示:

某类1:

  • 新的身份验证服务客户端->Post(new Auth(...)); // 登录正常
  • 而已

某类2:

  • 新服务客户端->Put(new E); // 一些初始化。
  • 服务客户端->Get(new G);

服务 G:

  • 在 G 请求新服务客户端 TryResolve();
  • 客户端->获取(新 W)

服务 E

  • 在 E 请求 CustomUserSession 可访问
  • 在 W 请求 CustomUserSession 时无法访问。

我的 Custom* 课程看起来像 Scott 的回答。

编辑:

这是我准备复制和粘贴的问题的代码:

    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. 在客户端应用程序中保存会话 cookie,并在每次调用 Web 服务之前恢复它们。
  2. 使用 Service::Resolve() 代替 Service::TryResolve
4

1 回答 1

1

您发布的代码对我来说看起来不错。因此,您的设置可能微不足道。

我创建了一个简单的自托管应用程序,该应用程序也使用 aCustomUserSession和 a 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不会被重用。所以你的会话不会跟随。您必须重用客户端,因为客户端存储跟踪您的会话的 cookie。

    SomeClass2您无需身份验证的情况下有效地调用服务,因此会话是null. 您需要JsonServiceClient为您的请求重复使用相同的内容。

    您可以运行您的身份验证方法,然后将会话 cookie 传递给任何后续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>();
    
于 2014-01-15T10:51:53.140 回答