Visual Studio 2012 を使用して、WPF (.NET 4.0) クライアントで ASP WebAPI (ASP MVC 4) アプリケーションを開発しています。クライアントはサーバーにログインする必要があります。FormsAuthentication と認証 Cookie を使用してログインします。ログインは、ASP MVC で既に正常に機能しています。
問題は、ログインがサーバー上で正常に実行され、Cookie がクライアントに送り返されても、サーバーへの後続の呼び出しで Cookie が送信されないことCookieContainer
です。
コードの簡略版は次のとおりです。
クライアント
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 は CookieContainer にあります。ここで奇妙なことがあります:コンテナー内の Cookie のドメインは "localhost" として設定されます (VS2012 デバッガーで検証)。"
http://localhost:50000
"ではないでしょうか? それを使用してコンテナのクッキーを取得しようとすると、cookieContainer.GetCookies(new Uri("http://localhost:50000"))
何も返されません。使用してみるとcookieContainer.GetCookies(new Uri("localhost"))
、無効な Uri エラーが発生します。ここで何が起こっているのかわかりません。PostItem
Cookie は、要求が行われる直前にコンテナー内にあります。httpClient.PostAsJsonAsync
ステートメントに到達すると、コンテナーは HttpClient で正しく設定されます。Cookieはサーバーに送信されません(フィドラーで確認
Application_PostAuthenticateRequest
し、Global.asax.csのメソッドで確認しましたthis.Request.Cookies
)
のドメインの不一致が原因で Cookie が送信されていないと思われCookieContainer
ますが、そもそもドメインが適切に設定されていないのはなぜCookieContainer
ですか?