HttpClient没有看到" Set-Cookie"头

时间:2014-04-19 21:00:12

标签: c# asp.net-mvc asp.net-web-api

我有一个MVC登录表单:

[HttpPost]
    public ActionResult Login(LoginViewModel viewModel)
    {
        if (viewModel.Username == "alex" && viewModel.Password == "password")
        {
            FormsAuthentication.SetAuthCookie(viewModel.Username, false);
            return RedirectToAction("Index", "Home");
        }

        return View();
    }

使用MVC登录操作的控制台应用客户端:

private static void GetPerson()
    {
        Console.WriteLine("Username:");
        string username = Console.ReadLine();

        Console.WriteLine("Password:");
        string password = Console.ReadLine();

        using (HttpClient httpClient = new HttpClient())
        {
            HttpRequestMessage authRequest = new HttpRequestMessage();
            authRequest.Method = HttpMethod.Post;
            authRequest.RequestUri = new Uri(@"http://localhost:4391/Account/Login");
            authRequest.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
            {
                new KeyValuePair<string, string>("Username", username),
                new KeyValuePair<string, string>("Password", password)
            });

            HttpResponseMessage authResponse = httpClient.SendAsync(authRequest).Result;
            IEnumerable<string> cookieValues;
            authResponse.Headers.TryGetValues("Set-Cookie", out cookieValues);

        }
    }

问题:authResponse.Headers.TryGetValues(&#34; Set-Cookie&#34;,out cookieValues)没有找到&#34; Set-Cookie&#34;标题所以cookieValues出现了&#34; null&#34;。

我在MVC中运行Fiddler for Login操作,这是我得到的:

HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Location: /
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 5.1
X-AspNet-Version: 4.0.30319
Set-Cookie:   .ASPXAUTH=A6A22208AECA1F3E25B43C834BE058A5019F3A9C55AED099FFAD5B0FE7B289EC2C3F87C157B0C1ED338D1DF0A6469E6C5DE8D9DB7A99D54D992EA10F26424BA579C262B7CD247CA4193879E058A233B7A0BC98E10503440B79EB988239C43696; path=/; HttpOnly
X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNcYWxleGFuZGVyXGRvY3VtZW50c1x2aXN1YWwgc3R1ZGlvIDIwMTNcUHJvamVjdHNcRm9ybVZhbHVlc0F1dGhXZWJBUElcRm9ybVZhbHVlc0F1dGhXZWJBUElcQWNjb3VudFxMb2dpbg==?=
X-Powered-By: ASP.NET
Date: Sat, 19 Apr 2014 20:09:23 GMT
Content-Length: 428

Fiddler表示我得到了&#34; Set-Cookie&#34;回来但为什么HttpClient没有看到它?

3 个答案:

答案 0 :(得分:1)

想出来 - MVC动作发送2个回复一个回复一个cookie,第二个回复没有cookie。 HttpClient显示最新的响应,这就是为什么它无法找到&#34; Set Cookie&#34;报头中。

但是!

似乎HttpClient从内部的第一个响应中保存cookie,并且在同一域下的安全页面上请求HttpClient自动应用该保存的cookie。

在我的例子中,如果我将连接到&#34; localhost:4391 / api / Person / 1&#34;使用HttpClient,我将获得未经授权。所以我的目标是去&#34; localhost:4391 /帐户/登录&#34;使用HttpClient,登录,获取生成的cookie然后转到&#34; localhost:4391 / api / Person / 1&#34;并发送该cookie,但正如我之前提到的,HttpClient自动执行此操作,我不需要从第一个请求中提取cookie到登录页面。

所以下面的代码可以根据需要运行!

private static void GetPerson()
    {
        Console.WriteLine("Username:");
        string username = Console.ReadLine();

        Console.WriteLine("Password:");
        string password = Console.ReadLine();

        HttpClient httpClient = new HttpClient();

        HttpRequestMessage authRequest = new HttpRequestMessage();
        authRequest.Method = HttpMethod.Post;
        authRequest.RequestUri = new Uri(@"http://localhost:4391/Account/Login");
        authRequest.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
            {
                new KeyValuePair<string, string>("Username", username),
                new KeyValuePair<string, string>("Password", password)
            });

        HttpResponseMessage authResponse = httpClient.SendAsync(authRequest).Result;

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, @"http://localhost:4391/api/Person/1");
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        HttpResponseMessage response = httpClient.SendAsync(request).Result;

        if (!response.IsSuccessStatusCode)
        {
            Console.WriteLine("Username or password is incorrect");
            return;
        }

        response.Content.ReadAsAsync<Person>().ContinueWith((x) => {
                Person person = x.Result;

                Console.WriteLine("First name: {0}", person.FirstName);
                Console.WriteLine("Last name: {0}", person.LastName);
            });
    }

但是如果我在控制器中的动作看起来如此,那么回到抓住那个cookie我就能完成它:

[HttpPost]
    public ActionResult Login(string username, string password) 
    {
        if (username == password) 
        {
            FormsAuthentication.SetAuthCookie(username, true);
            return new HttpStatusCodeResult(HttpStatusCode.OK);
        }
        return new HttpUnauthorizedResult();
    }

答案 1 :(得分:0)

你可以尝试像这样设置auth cookie吗

HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, authTicket);
Response.Cookies.Add(cookie);

参考这篇文章,它可能会有所启发。 http://weblog.west-wind.com/posts/2012/Nov/29/SetCookie-Headers-getting-stripped-in-ASPNET-HttpHandlers

答案 2 :(得分:0)

我研究了很多,但在另一种语言的网站上找到了一个。解决方案是为会话开始和结束添加一个空的事件处理程序: protected void Session_Start(object sender,EventArgs e) { } protected void Session_End(object sender,EventArgs e) { }