web-dev-qa-db-ja.com

User.Identity.GetUserId()は、ログインに成功した後にnullを返します

現在のユーザーIDを取得する一時変数を定義しましたが、常にnullを返します。

スナップショットは次のとおりです。

userId

どうして?

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();
    }
32
Foo

実際には、ユーザーは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の情報が含まれます。

28
Anders Tornblad

これを試してください:

string userId = SignInManager
.AuthenticationManager
.AuthenticationResponseGrant.Identity.GetUserId();
27
Beedjees

あなたの場合、他のデータを使用して、ログインしたばかりのユーザーを見つけることができます。ログインが成功し、ユーザー名が一意であることがわかっているため、次のように動作します。

 //
// 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." });
    }
}
9
Martijn Lentink

はい、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);
        }
    }

これが誰かを助けることを願っています。

2
HttpContext.User = await _signInManager.CreateUserPrincipalAsync(user);

サインイン後、サインインマネージャーを使用してユーザープリンシパルを作成し、HttpContext.User参照を手動で割り当てることができます。

これにより、通常のサインインページと同じようにユーザーIDにアクセスできるようになります。

var userId = userManager.GetUserId(HttpContext.User);
2
Dustin Gamester

サインイン直後にユーザーに次の操作を実行させます。

var userId = SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity.GetUserId();
var user = SignInManager.UserManager.Users.Where(x => x.Id.Equals(userId)).FirstOrDefault();
0
wecky

ここに私のために働いたものがあります:

await SignInManager.SignInAsync(user, isPersistent: true, rememberBrowser: false);

AuthenticationManager.User = new GenericPrincipal(AuthenticationManager.AuthenticationResponseGrant.Identity, null);

実行されると、現在のリクエストの認証状態を取得します。

0
Dmitry Duka