簡體   English   中英

從Mono運行時ServiceStack不發送cookie

[英]ServiceStack not sending cookies when run from Mono

這個問題似乎只存在於在Ubuntu上運行的Mono(在我的情況下是2.10版)中。 即使在Windows上使用Mono,我的控制台程序也可以在Windows上按預期運行。

我的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; 
        }
    }

很簡單。 這樣做的目的是簡單地返回現有的服務客戶端或具有已包括的auth令牌的新客戶端。 在其他地方,它似乎都可以正常工作。

要在程序其他位置使用客戶端從API服務器獲取某些對象,請調用以下代碼:

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

如上所述,執行此控制台應用程序將在Windows和Mono for Windows上按預期運行。 客戶端被調用,轉到服務器並按預期獲取對象列表。

但是,在Linux上,我嘗試使用“〜$ mono MyApp.exe / arg1 / arg2 / arg3”運行該應用程序,但響應為302,嘗試將我重定向到登錄位置。 自然地,這表明從未向ServiceStack告知有關此特定請求的現有會話。 所以...為了確保我仔細查看了托管我們API的機器(它本身由Apache / mod_mono托管),它看起來好像初始身份驗證(使用憑據身份驗證提供程序)正在按預期工作,我得到了一個SS-使用的ID等

深入研究我看了發送到Apache的標頭。 從Windows執行此控制台應用程序時,對DueRequest的請求(如上所示)中應包含具有ss-id的cookie。 但是,當在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");
        }
    }
}

預期結果:

有餅干嗎?
設置cookie? 真正
有餅干嗎? 真正


順便說一句,只是從您的代碼中觀察到一個問題。 希望您不要指出這個問題 您最好更改一下:

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時,我做了同樣的事情。 ;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM