137

シングルページアプリケーションを構築していて、偽造防止トークンの問題が発生しています。

問題が発生する理由はわかっていますが、修正方法がわかりません。

次の場合にエラーが発生します。

  1. ログインしていないユーザーがダイアログをロードします(生成された偽造防止トークンを使用)
  2. ユーザーがダイアログを閉じる
  3. ユーザーがログインします
  4. ユーザーが同じダイアログを開く
  5. ユーザーがダイアログでフォームを送信

偽造防止トークンはユーザー「」を対象としていますが、現在のユーザーは「ユーザー名」です

これが発生する理由は、私のアプリケーションが100%単一ページであり、ユーザーがajax投稿を介して正常にログインすると/Account/JsonLogin、サーバーから返された「認証済みビュー」で現在のビューを切り替えるだけで、リロードしないためです。ページ。

手順3と4の間にページを単純にリロードしてもエラーが発生しないため、これが理由であることがわかります。

したがって@Html.AntiForgeryToken()、ロードされたフォームでは、ページがリロードされるまで、古いユーザーのトークンが返されるようです。

@Html.AntiForgeryToken()新しい認証済みユーザーのトークンを返すように変更するにはどうすればよいですか?

私は毎回GenericalPrincipalカスタムで新しいものを注入するので、呼び出されるまでに、実際には、プロパティがtrueに設定されたカスタムIDがありますが、ページのリロードを行わない限り、古いユーザーのトークンをレンダリングしているようです。IIdentityApplication_AuthenticateRequest@Html.AntiForgeryToken()HttpContext.Current.User.IdentityIsAuthenticated@Html.AntiForgeryToken

4

10 に答える 10

172

これは、偽造防止トークンがユーザーのユーザー名を暗号化されたトークンの一部として埋め込み、検証を強化するために発生します。最初にユーザーを呼び出したとき@Html.AntiForgeryToken()、ユーザーはログインしていないため、トークンにはユーザー名の空の文字列が含まれます。ユーザーがログインした後、偽造防止トークンを置き換えないと、最初のトークンが匿名ユーザーであり、既知のユーザー名を持つ認証済みユーザーがいます。

この問題を解決するには、いくつかのオプションがあります。

  1. 今回は、SPA に完全な POST を実行させ、ページがリロードされると、更新されたユーザー名が埋め込まれた偽造防止トークンが表示されます。

  2. ログイン直後の部分ビューを表示し@Html.AntiForgeryToken()、別の AJAX リクエストを実行して、既存の偽造防止トークンをリクエストのレスポンスに置き換えます。

AntiForgeryConfig.SuppressIdentityHeuristicChecks = true設定によってユーザー名の検証が無効になるわけではなく、検証の仕組みが変わるだけであることに注意してください。ASP.NET MVC docs、そのプロパティが読み取られるソース コード、およびその構成値に関係なくトークン内のユーザー名が検証されるソース コードを参照してください。

于 2013-03-25T13:09:44.017 に答える
26

エラーを修正するには、[ログインOutputCacheの取得] ページにデータ注釈を次のように配置する必要があります。ActionResult

[OutputCache(NoStore=true, Duration = 0, VaryByParam= "None")] 
public ActionResult Login(string returnUrl)
于 2014-11-10T06:35:41.210 に答える
1

登録プロセス内で、かなり具体的でありながら同様の問題がありました。ユーザーが送信された電子メール リンクをクリックすると、ユーザーはログインし、アカウントの詳細画面に直接送信され、さらに情報を入力します。私のコードは次のとおりです。

    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 を Return RedirectToAction("AccountDetails") に変更すると、問題が解決しました。

于 2016-08-12T11:48:10.877 に答える