現在のユーザーIDを取得する一時変数を定義しましたが、常にnullを返します。
スナップショットは次のとおりです。
どうして?
UPDATE:
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return Json(new { success = false, ex = "Fail to login." });
}
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, isPersistent: true, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
string userId = User.Identity.GetUserId();
return Json(new { success = true });
case SignInStatus.Failure:
return Json(new { success = false, ex = "Email or password was incorrect." });
default:
return Json(new { success = false, ex = "Fail to login." });
}
}
更新2:
クライアント側では、ajaxを使用して/Account/Login
:
var loginAjax = function (email, password, callback) {
$.ajax({
url: '/Account/Login',
type: 'POST',
data: { Email: email, Password: password },
success: function (data) {
$('body').css('cursor', 'default');
if (data.success) {
callback(true)
} else {
$('#login-error').text(data.ex)
}
},
error: function () {
$('#login-error').text('Không thể kết nối đến máy chủ.')
}
});
callback(false)
};
// I've got email and password in another function to check valid or not
loginAjax(email, password, function (success) {
$('body').css('cursor', 'default');
switch (success) {
case true:
signin(function () {
$('.login').html('');
window.location.href = '/?type=Promotion';
});
break
case false:
$('#Email-active').hide();
$('#Password-active').hide();
$('#Password').val('');
$('#login-btn').removeClass('disabled').attr('onclick', '$(this).addClass("disabled").removeAttr("onclick"); running()');
break
}
});
クライアント側のSignalR:
var signalR = $.connection.chat;
var signin = function (callback) {
$.connection.hub.start().done(function () {
signalR.server.signinToSignalR();
callback()
})
};
サーバー側のSignalR:
public void SigninToSignalR()
{
// this's always null
string userId = HttpContext.Current.User.Identity.GetUserId();
}
実際には、ユーザーはnotサインインしています-現在のリクエストのコンテキストではありません(POST /Account/Login
リクエスト)、これはUser.Identity
がデータを取得する場所です。サインインするために現在(そして明らかに成功している)を試みているユーザーのIDを抽出したい場合は、何らかのステップをハイジャックするなど、他の方法でそれを行う必要がありますSignInManager.PasswordSignInAsync
への呼び出し内。独自のMembershipProvider
を実装している場合、これは簡単です。
それ以外の場合、次のリクエストを待機する必要があります次のリクエスト(一部のコントローラーのアクションメソッドで処理されるリクエストはすべて正常に処理されます)User.Identity
を希望どおりに。
Login
メソッドが呼び出されると、リクエストコンテキストは既に評価されており、多くのデータが利用可能です。たとえば、HTTPヘッダー、Cookieなど。これは、User.Identity
のようなすべてのコンテキスト情報が見つかる場所です。
SignInManager.PasswordSignInAsync(...)
を呼び出すと、これはrequest contextの値に影響を与えませんnot。ブラウザは、数ミリ秒前に送信したものについて考えを変えていません。影響するのは、ユーザーIDとセッションIDを含むcookieを追加するresponse contextです。その後、このCookieはブラウザに送信され、ブラウザはリクエストが連続するたびにサーバーに送り返します。したがって、これより後のすべてのリクエスト(ユーザーがサインアウトするか、Cookieが古くなるまで)には、解釈するUser.Identity
の情報が含まれます。
これを試してください:
string userId = SignInManager
.AuthenticationManager
.AuthenticationResponseGrant.Identity.GetUserId();
あなたの場合、他のデータを使用して、ログインしたばかりのユーザーを見つけることができます。ログインが成功し、ユーザー名が一意であることがわかっているため、次のように動作します。
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return Json(new { success = false, ex = "Fail to login." });
}
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, isPersistent: true, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
string userId = UserManager.FindByName(model.Email)?.Id;
return Json(new { success = true });
case SignInStatus.Failure:
return Json(new { success = false, ex = "Email or password was incorrect." });
default:
return Json(new { success = false, ex = "Fail to login." });
}
}
はい、Andersが言ったように、User.IdentityとUser.IsInRoleは同じログインアクション内では機能しません。したがって、新しいアクションにリダイレクトする必要があるため、ログインアクションの内部でaddを実行します。
return RedirectToAction( "MyNewLoginRoute"、new {returnUrl = returnUrl});
以下はコード例です。
var result = SignInManager.PasswordSignIn(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
// below is the new line modification
return RedirectToAction("LoginRoute", new {returnUrl=returnUrl });
次に、以下のように新しいアクションLoginRouteを追加します。
// below method is new to get the UserId and Role
public ActionResult LoginRoute(string returnUrl) //this method is new
{
if (String.IsNullOrWhiteSpace(returnUrl))
{
if (User.IsInRole("Admin"))
{
return RedirectToLocal("/Admin");
}
else if (User.IsInRole("Partner"))
{
return RedirectToLocal("/Partner/Index/");
}
else if (User.IsInRole("EndUser"))
{
ApplicationDbContext db = new ApplicationDbContext();
// know the partner
int partnerID = db.Users.Where(x => x.UserName == User.Identity.Name).FirstOrDefault().PartnersTBLID;
return RedirectToLocal("/Partner/List/" + partnerID.ToString());
}
}
else
{
return RedirectToLocal(returnUrl);
}
}
これが誰かを助けることを願っています。
HttpContext.User = await _signInManager.CreateUserPrincipalAsync(user);
サインイン後、サインインマネージャーを使用してユーザープリンシパルを作成し、HttpContext.User参照を手動で割り当てることができます。
これにより、通常のサインインページと同じようにユーザーIDにアクセスできるようになります。
var userId = userManager.GetUserId(HttpContext.User);
サインイン直後にユーザーに次の操作を実行させます。
var userId = SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity.GetUserId();
var user = SignInManager.UserManager.Users.Where(x => x.Id.Equals(userId)).FirstOrDefault();
ここに私のために働いたものがあります:
await SignInManager.SignInAsync(user, isPersistent: true, rememberBrowser: false);
AuthenticationManager.User = new GenericPrincipal(AuthenticationManager.AuthenticationResponseGrant.Identity, null);
実行されると、現在のリクエストの認証状態を取得します。