加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net – HttpClient不会从CookieContainer发送cookie

发布时间:2020-12-16 07:00:47 所属栏目:asp.Net 来源:网络整理
导读:我正在使用Visual Studio 2012开发带有 WPF(.NET 4.0)客户端的ASP WebAPI(ASP MVC 4)应用程序.客户端需要登录到服务器.我使用FormsAuthentication和身份验证cookie登录.登录已经在ASP MVC中正常工作. 问题在于,尽管登录在服务器上成功执行并且cookie被发送回
我正在使用Visual Studio 2012开发带有 WPF(.NET 4.0)客户端的ASP WebAPI(ASP MVC 4)应用程序.客户端需要登录到服务器.我使用FormsAuthentication和身份验证cookie登录.登录已经在ASP MVC中正常工作.

问题在于,尽管登录在服务器上成功执行并且cookie被发送回客户端,但是在后续调用服务器时不会发送cookie,即使CookieContainer与auth cookie集重用也是如此.

这是代码的简化版本:

客户

public async Task<UserProfile> Login(string userName,string password,bool rememberMe)
{           
    using (var handler = new HttpClientHandler() { CookieContainer = this.cookieContainer })
    using (var httpClient = new HttpClient(handler))
    {
        httpClient.BaseAddress = new Uri("http://localhost:50000/");

        httpClient.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

        var result = await httpClient.PostAsJsonAsync("api/auth/login",new
        {
            username = userName,password = password,rememberMe = rememberMe
        });

        result.EnsureSuccessStatusCode();

        var userProfile = await result.Content.ReadAsAsync<UserProfile>();

        if (userProfile == null)
            throw new UnauthorizedAccessException();

        return userProfile;
    }
}

public async Task<ExamSubmissionResponse> PostItem(Item item)
{
    using (var handler = new HttpClientHandler() { CookieContainer = this.cookieContainer })
    using (var httpClient = new HttpClient(handler))
    {
        httpClient.BaseAddress = new Uri("http://localhost:50000/");

        var result = await httpClient.PostAsJsonAsync("api/Items/",item);
    }
}

服务器

[HttpPost]
public HttpResponseMessage Login(LoginModel model)
{
    if (this.ValidateUser(model.UserName,model.Password))
    {
        // Get user data from database

        string userData = JsonConvert.SerializeObject(userModel);

        var authTicket = new FormsAuthenticationTicket(
            1,model.UserName,DateTime.Now,DateTime.Now.AddMinutes(10 * 15),model.RememberMe,userData
        );              

        string ticket = FormsAuthentication.Encrypt(authTicket);
        var cookie = new CookieHeaderValue(FormsAuthentication.FormsCookieName,ticket);
        var response = Request.CreateResponse(HttpStatusCode.Created,userModel);
        response.Headers.AddCookies(new CookieHeaderValue[] { cookie });

        return response;
    }
    return null;
}

首先,我使用Fiddler2调试了问题(我使用基地址作为“http://localhost.fiddler:50000 /”来查看本地流量).然后我怀疑小提琴手可能会干扰,所以我只是使用Visual Studio 2012进行了调试.

我试过并验证了什么:

> Login方法到达服务器
>使用客户端发送的数据对用户进行成功验证
> cookie在服务器上设置
> cookie在响应中(与fiddler验证)
>操作后,cookie位于CookieContainer中.这里有一个奇怪的事情:容器中cookie的域名设置为“localhost”(使用VS2012调试器验证).不应该是“http:// localhost:50000”?当我尝试使用cookieContainer.GetCookies(新的Uri(“http:// localhost:50000”))获取容器的cookie时,它什么都不返回.当我使用cookieContainer.GetCookies(新的Uri(“localhost”))尝试它时,它给我一个无效的Uri错误.不知道这里发生了什么.
>在发出PostItem请求之前,cookie就在容器中.当达到语句httpClient.PostAsJsonAsync时,在HttpClient中正确设置容器.
> cookie没有发送到服务器(我用fiddler和Global.asax.cs中的Application_PostAuthenticateRequest方法检查它,验证this.Request.Cookies)

我怀疑由于CookieContainer中的域不匹配而没有发送cookie,但是为什么域首先没有在CookieContainer中设置?

解决方法

您的问题是您没有在从Web Api控制器发回的cookie上设置任何路径.

有两件事可以控制发送cookie的位置:

> cookie的域名
> cookie的路径

关于域名,共识似乎是端口号不再(但仍可能)成为评估cookie域的一个因素.有关端口号如何影响域的详细信息,请参阅this question.

关于路径:Cookie与其域中的特定路径相关联.在您的情况下,Web Api发送cookie而不指定其路径.默认情况下,cookie将与创建cookie的请求/响应的路径相关联.

在您的情况下,cookie将具有路径api / auth / login.这意味着cookie将被发送到此路径的子路径(缺少更好的术语),但不会发送到父路径或兄弟路径.

要测试这个,请尝试:

cookieContainer.GetCookies(new Uri("http://localhost/api/auth/login")

这应该给你cookie.这应该是这样的:

cookieContainer.GetCookies(new Uri("http://localhost/api/auth/login/foo/bar")

另一方面,这些将找不到cookie:

cookieContainer.GetCookies(new Uri("http://localhost/")
cookieContainer.GetCookies(new Uri("http://localhost/api/")
cookieContainer.GetCookies(new Uri("http://localhost/api/auth/")
cookieContainer.GetCookies(new Uri("http://localhost/api/auth/foo")
cookieContainer.GetCookies(new Uri("http://localhost/api/Items/")

要解决此问题,只需在发送共鸣之前将路径“/”(或者可能是“/ api”)添加到cookie:

...
string ticket = FormsAuthentication.Encrypt(authTicket);
var cookie = new CookieHeaderValue(FormsAuthentication.FormsCookieName,ticket);
cookie.Path = "/";
var response = Request.CreateResponse(HttpStatusCode.Created,userModel);
response.Headers.AddCookies(new CookieHeaderValue[] { cookie });
...

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读