c# - 从 Mono 运行时 ServiceStack 不发送 cookie

标签 c# linux cookies mono servicestack

这个问题似乎只存在于在 Ubuntu 上运行的 Mono(在我的例子中是版本 2.10)中。我的控制台程序在 Windows 上按预期运行,即使在 Windows 上使用 Mono 时也是如此。

我在我们的 API 上有一项服务需要身份验证。访问它的客户端像往常一样进行身份验证并卡在 ss-id 上,稍后放入 cookie 并添加到 JsonServiceClient cookie 容器中。我以这种方式调用 JsonServiceClient:

internal class ApiClient
{
    // Service client
    private JsonServiceClient _ServiceClient;
    internal JsonServiceClient ServiceClient
    {
        get
        {
            if (_ServiceClient == null)
            {
                _ServiceClient = new JsonServiceClient(globals.ApiUrl);
            }

            var CookieQuery = (from c in globals.AuthCookieContainer
                               where c.Name == "ss-id"
                               where !c.Expired
                               select c);

            if (CookieQuery.Count() > 0)
            {
                _ServiceClient.CookieContainer.Add(CookieQuery.FirstOrDefault());
            }

            return _ServiceClient; 
        }
        set
        {
            _ServiceClient = value; 
        }
    }

很简单。其目的是简单地返回现有服务客户端或已包含身份验证 token 的新服务客户端。它似乎在我使用它的其他任何地方都工作得很好。

为了在程序的其他地方使用客户端从 API 服务器获取一些对象,我调用如下:

return ClientClass.ServiceClient.Get(new ServiceModel.DueRequest()).Result;

如上所述,执行此控制台应用程序在 Windows 和 Mono for Windows 上按预期运行。客户端被调用,连接到服务器并按预期抓取对象列表。

但在 Linux 上,我尝试使用“~$ mono MyApp.exe/arg1/arg2/arg3”运行应用程序,它以 302 响应,尝试将我重定向到登录位置。自然地,这表明 ServiceStack 从未被告知我针对此特定请求的现有 session 。所以...为了确保我仔细查看了托管我们的 API 的机器(它本身由 Apache/mod_mono 托管),它看起来好像初始身份验证(使用 credentialsauthprovider)正在按预期工作,我正在取回 SS-要使用的ID等

深入挖掘,我查看了发送到 Apache 的 header 。从 Windows 执行此控制台应用程序时,带有 ss-id 的 cookie 应包含在 DueRequest 请求中(如上所示)。 但是,当在 Linux 上使用 Mono 运行完全相同的可执行文件时,cookie 不存在。同样,这是运行完全相同版本的可执行文件和 ServiceStack DLL。

我不得不猜测这更多是 Mono 的问题,我只是想知道在 Linux/ServiceStack 上一起使用 Mono 之前是否有人遇到过这种行为。

更多信息

为了确认没有发送 cookie,我继续在 API 服务器本身(运行 Apache/mod_mono 的服务器)上启动 TCPdump:

tcpdump -i eth0 -s 1024 -l -A port 80 | egrep -w 'cookie|Cookie'

当从“正在工作”的客户端发出请求时,我看到:

Set-Cookie: ss-pid=xZ/1TG8ED1dhxntBOPLA; path=/; expires=Sat, 04 Feb 2034 20:48:09 GMT; HttpOnly
Cookie: ss-id=xZ/1TG8ED1dhxntBOPLA

从 Linux 终端使用 Mono 运行时:

Set-Cookie: ss-pid=TTIJ2tYOXjRwUwCfv/sn; path=/; expires=Sat, 04 Feb 2034 20:49:17 GMT; HttpOnly

服务器显然使用 cookie 进行响应...但在第二个示例中,客户端从未发送过 cookie。

最佳答案

我一直使用 Mono,没有这个问题。我创建了一个完全可用的控制台应用程序(如下) 并在 Mono 2.10.6 和 Mono 3.2.6 上进行了测试。 ServiceStack v4.0.9

我建议您试用该应用程序,看看它是否通过。

测试应用:

using System;
using ServiceStack;

namespace TestCookies
{
    class MainClass
    {
        public static void Main()
        {
            // Very basic console host
            var appHost = new AppHost(500);
            appHost.Init();
            appHost.Start("http://*:9000/");

            // Make client request
            var client = new JsonServiceClient("http://localhost:9000");
            Console.WriteLine("Has cookie? {0}", client.Get(new HasCookieRequest()));
            client.Get(new SetCookieRequest());
            Console.WriteLine("Set cookie? {0}", client.CookieContainer.Count > 0);
            Console.WriteLine("Has cookie? {0}", client.Get(new HasCookieRequest()));
            Console.ReadKey();
        }
    }

    public class AppHost : AppHostHttpListenerPoolBase
    {
        public AppHost(int poolSize) : base("Cookie Test Service", poolSize, typeof(CookieTestService).Assembly) {}

        public override void Configure(Funq.Container container)
        {
            Config = new HostConfig {
                DebugMode = true,
            };
        }
    }

    [Route("/SetCookie","GET")]
    public class SetCookieRequest : IReturnVoid {}

    [Route("/HasCookie","GET")]
    public class HasCookieRequest : IReturn<bool> {}

    public class CookieTestService : Service
    {
        public void Get(SetCookieRequest request)
        {
            Response.SetCookie("ss-id","1234567890",DateTime.Now.AddDays(1));
        }

        public bool Get(HasCookieRequest request)
        {
            return Request.Cookies.ContainsKey("ss-id");
        }
    }
}

预期结果:

Has cookie? False
Set cookie? True
Has cookie? True


顺便说一句,只是从您的代码中观察到的有点偏离主题。希望您不会觉得指出这一点是厚颜无耻的。你最好改变这个:

var CookieQuery = (from c in globals.AuthCookieContainer
                   where c.Name == "ss-id"
                   where !c.Expired
                   select c);

if (CookieQuery.Count() > 0)
{
    _ServiceClient.CookieContainer.Add(CookieQuery.FirstOrDefault());
}

进入这个:

var cookie = (from c in globals.AuthCookieContainer
              where c.Name == "ss-id"
              where !c.Expired
              select c).FirstOrDefault();

if (cookie!=null)
{
    _ServiceClient.CookieContainer.Add(cookie);
}

当您调用 .Count() 时,CookieQuery 将被计算,然后当您调用 FirstOrDefault() 时,它将被再次计算。第二种方式不行,效率更高。它非常小,但是当我开始使用 Linq 时,我也做了同样的事情。 ;)

关于c# - 从 Mono 运行时 ServiceStack 不发送 cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21562779/

相关文章:

javascript - 在 node.js 中输出完整的错误对象

regex - txt文件删除url到最后 "/"得到文件

cookies - 使用 cookie 进行本地主机开发

c# - 请求建议 : How to Log WCF Web Service Request Info to a database

c# - 在运行时设置 String.Format

c# - C# 中用于人脸检测的图像腐 eclipse

c# - 自 C# 以来的 C++ 代码等效吗?

c - Linux内核模块tcp连接

javascript - jquery:检查窗口是否已滚动一次并执行某些操作

使用 JAX-RS 进行 JavaScript cookie 管理