[英]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.