[asp.net-mvc-4] 위변조 방지 토큰은 “”사용자를위한 것이지만 현재 사용자는 “username”입니다.

단일 페이지 응용 프로그램을 작성하고 위조 방지 토큰에 문제가 있습니다.

문제가 발생하는 이유를 알고 있으며 문제를 해결하는 방법을 모르겠습니다.

다음과 같은 경우 오류가 발생합니다.

  1. 로그인하지 않은 사용자는 대화 상자를 생성합니다 (위조 방지 토큰 생성).
  2. 사용자가 대화 상자를 닫습니다.
  3. 사용자 로그인
  4. 사용자는 같은 대화 상자를 엽니 다
  5. 사용자가 대화 상자에서 양식을 제출

위변조 방지 토큰은 “”사용자를위한 것이지만 현재 사용자는 “username”입니다.

내 응용 프로그램이 100 % 단일 페이지이며, 사용자가 성공적으로 아약스 게시물을 통해 로그인 할 때 때문에 이런 일이 발생하는 이유는 /Account/JsonLogin, 단순히 서버에서 반환 된 “인증 된 뷰”로 현재보기를 전환하지만 를 다시로드하지 않습니다 페이지.

3 단계와 4 단계 사이에 페이지를 간단히 다시로드하면 오류가 없기 때문에 이것이 이유라는 것을 알고 있습니다.

따라서 @Html.AntiForgeryToken()로드 된 양식에서 페이지를 다시로드 할 때까지 여전히 이전 사용자의 토큰을 반환하는 것으로 보입니다 .

@Html.AntiForgeryToken()인증 된 새로운 사용자에 대한 토큰을 반환하도록 변경 하려면 어떻게 해야합니까?

호출 할 때 마다 GenericalPrincipal사용자 정의 IIdentity에 새 항목 을 삽입합니다 . 실제로 속성이 true로 설정된 사용자 정의 ID 는 페이지를 다시로드하지 않으면 여전히 이전 사용자에 대한 토큰을 렌더링하는 것 같습니다.Application_AuthenticateRequest@Html.AntiForgeryToken()HttpContext.Current.User.IdentityIsAuthenticated@Html.AntiForgeryToken



답변

위조 방지 토큰은 더 나은 유효성 검사를 위해 사용자의 사용자 이름을 암호화 된 토큰의 일부로 포함하기 때문에 발생합니다. 처음 호출 할 @Html.AntiForgeryToken()때 사용자가 로그인하지 않았으므로 토큰에 사용자 이름에 대한 빈 문자열이 표시됩니다. 사용자가 로그인 한 후 위조 방지 토큰을 바꾸지 않으면 초기 토큰이 사용 되었기 때문에 유효성 검사를 통과하지 못합니다. 익명의 사용자이며 이제 사용자 이름이 알려진 인증 된 사용자가 있습니다.

이 문제를 해결하기위한 몇 가지 옵션이 있습니다.

  1. 이번에는 SPA가 전체 POST를 수행하도록하고 페이지가 다시로드 될 때 업데이트 된 사용자 이름이 포함 된 위조 방지 토큰을 갖게됩니다.

  2. @Html.AntiForgeryToken()로그인 한 직후에 부분적으로 확인하고 다른 AJAX 요청을 수행하고 기존 위조 방지 토큰을 요청의 응답으로 바꿉니다.

  3. 위조 방지 유효성 검사가 수행하는 신원 확인을 비활성화하십시오. Application_Start 메소드에 다음을 추가하십시오 AntiForgeryConfig.SuppressIdentityHeuristicChecks = true..


답변

오류를 해결하려면 다음과 같이 로그인 정보 페이지 OutputCache에 데이터 주석 을 배치해야합니다 ActionResult.

[OutputCache(NoStore=true, Duration = 0, VaryByParam= "None")]
public ActionResult Login(string returnUrl)


답변

내 응용 프로그램에서 여러 번 발생하므로 Google에서 사용하기로 결정했습니다!

이 오류에 대한 간단한 설명을 찾았습니다! 사용자가 로그인 버튼을 두 번 클릭하고 있습니다! 다른 사용자가 아래 링크에서 그것에 대해 이야기하는 것을 볼 수 있습니다.

위조 방지 토큰을 제공 한 MVC 4는 사용자 “”을위한 것이지만 현재 사용자는 “user”입니다.

도움이 되길 바랍니다! =)


답변

나는 같은 문제가 있었고,이 더러운 해킹은 적어도 더 깨끗한 방식으로 고칠 수있을 때까지 해결되었습니다.

    public ActionResult Login(string returnUrl)
    {
        if (AuthenticationManager.User.Identity.IsAuthenticated)
        {
            AuthenticationManager.SignOut();
            return RedirectToAction("Login");
        }


답변

이미 인증 된 상태에서 로그인하면 메시지가 나타납니다.

이 도우미는 [ValidateAntiForgeryToken]속성 과 정확히 동일한 기능을 수행 합니다.

System.Web.Helpers.AntiForgery.Validate()

[ValidateAntiForgeryToken]컨트롤러 에서 속성을 제거 하고이 헬퍼를 조치 방법에 배치하십시오.

따라서 사용자가 이미 인증 된 경우 홈 페이지로 리디렉션하거나이 확인 후 유효한 위조 방지 토큰 확인을 계속하지 않으면

if (User.Identity.IsAuthenticated)
{
    return RedirectToAction("Index", "Home");
}

System.Web.Helpers.AntiForgery.Validate();

오류를 재현하려면 다음과 같이 진행하십시오. 로그인 페이지에 있고 인증되지 않은 경우. 탭을 복제하고 두 번째 탭으로 로그인 한 경우 그리고 로그인 페이지의 첫 번째 탭으로 돌아와서 페이지를 다시로드하지 않고 로그인하려고하면 …이 오류가 발생합니다.


답변

프로덕션 서버에서 거의 동일한 예외가 발생합니다.

왜 그런가요?

유효한 자격 증명을 사용하여 사용자 로그인 한 후 한 번 로그인하여 다른 페이지로 리디렉션하면 뒤로 버튼을 누르면 로그인 페이지가 표시되고이 예외가 발생할 때 유효한 자격 증명을 다시 입력했습니다.

해결하는 방법?

이 줄을 추가하고 완벽하게 작동하면 오류가 발생하지 않습니다.

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]


답변

등록 과정에서 상당히 구체적이지만 비슷한 문제가있었습니다. 사용자가 이메일 링크를 클릭하면 로그인되어 계정 정보 화면으로 바로 전송되어 추가 정보를 채 웁니다. 내 코드는 다음과 같습니다

    Dim result = Await UserManager.ConfirmEmailAsync(userId, code)
    If result.Succeeded Then
        Dim appUser = Await UserManager.FindByIdAsync(userId)
        If appUser IsNot Nothing Then
            Dim signInStatus = Await SignInManager.PasswordSignInAsync(appUser.Email, password, True, shouldLockout:=False)
            If signInStatus = SignInStatus.Success Then
                Dim identity = Await UserManager.CreateIdentityAsync(appUser, DefaultAuthenticationTypes.ApplicationCookie)
                AuthenticationManager.SignIn(New AuthenticationProperties With {.IsPersistent = True}, identity)
                Return View("AccountDetails")
            End If
        End If
    End If

Return View ( “AccountDetails”)가 토큰 예외를 제공한다는 것을 알았습니다. ConfirmEmail 함수는 AllowAnonymous로 장식되었지만 AccountDetails 함수에는 ValidateAntiForgeryToken이 있었기 때문에 추측하고 있습니다.

Return to Return RedirectToAction ( “AccountDetails”)을 변경하면 문제가 해결되었습니다.