我正在使用 Visual Studio 2012 开发带有 WPF (.NET 4.0) 客户端的 ASP WebAPI (ASP MVC 4) 应用程序。客户端需要登录到服务器。我使用带有身份验证 cookie 的 FormsAuthentication 来登录。登录已经在 ASP MVC 中正常工作。
问题在于,虽然在服务器上成功执行了登录并且将cookie发送回客户端,但在后续调用服务器时并没有发送cookie,即使CookieContainer
与 auth cookie 集一起重用。
这是代码的简化版本:
CLIENT
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);
}
}
SERVER
[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/
”查看本地流量)。然后我怀疑fiddler可能会干扰,所以我就用Visual Studio 2012进行调试。
我已经尝试和验证过的:
通过 Login 方法到达服务器
使用客户端发送的数据成功验证用户身份
cookie是在服务器上设置的
cookie在响应中(用fiddler验证)
操作完成后,cookie 位于 CookieContainer 中。这里有一个奇怪的事情:容器中cookie的域设置为“localhost”(用VS2012调试器验证)。不应该是“http://localhost:50000
"?当我尝试使用获取容器的cookie时cookieContainer.GetCookies(new Uri("http://localhost:50000"))
它什么也不返回。当我尝试使用cookieContainer.GetCookies(new Uri("localhost"))
它给了我一个无效的 Uri 错误。不知道这里发生了什么。
cookie 就在之前的容器中PostItem
提出请求。当语句在 HttpClient 中正确设置容器时httpClient.PostAsJsonAsync
到达了。
cookie 没有发送到服务器(我用 fiddler 检查了它并在Application_PostAuthenticateRequest
Global.asax.cs 中的方法,验证this.Request.Cookies
)
我怀疑由于域不匹配而未发送 cookieCookieContainer
,但是为什么域没有按照应有的方式设置CookieContainer
首先?