3

環境:ASP.NET MVC 4、Visual Studio 2012

この[Authorize]属性は、ユーザーが有効なログインCookieを持っていることを確認しますが、ユーザーが実際に存在することは確認しません。これは、ユーザーのコンピューターが永続化されたクレデンシャルCookieを保持しているときに、そのユーザーが削除された場合に発生します。このシナリオでは、ログインしている非ユーザーは、[Authorize]属性でマークされたコントローラーアクションを実行できます。

解決策は非常に単純なように思われます。拡張AuthorizeAttributeし、AuthorizeCoreルーチンで、ユーザーが存在することを確認します。

私が自分で使用するためにこのコードを書く前に、属性のこのギャップのある穴に対するすぐに使える解決策を誰かが知っているかどうかを知りたいと思い[Authorize]ます。

4

2 に答える 2

3

特別な認証グローバルアクションフィルターが必要です。

問題の解決策は次のとおりです。コントローラアクションが呼び出される前に実行されるグローバルアクションフィルタを導入する必要があります。このイベントの名前はOnActionExecutingです。また、このグローバルアクションフィルター内で、ユーザーが有効な認証Cookieを持っているが、永続性(DB)にはもう存在しない(そしてそのCookieを削除する必要がある)というシナリオを処理することもできます。

アイデアを得るためのコード例は次のとおりです。

    public class LoadCustomPrincipalAttribute : ActionFilterAttribute 
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
                CustomIdentity customIdentity;

                if (HttpContext.Current.User.Identity.IsAuthenticated)
                {        
                    UserData userData = UserRepository.GetUserByName(HttpContext.Current.User.Identity.Name);

                    if (userData == null)
                    {
                      //TODO: Add here user missing logic, 
                      //throw an exception, override with the custom identity with "false" - 
                      //this boolean means that it have IsAuthenticated on false, but you
                      //have to override this in CustomIdentity!
                      //Of course - at this point you also remove the user cookie from response!
                    }

                    customIdentity = new CustomIdentity(userData, true);
                }
                else
                {
                    customIdentity = new CustomIdentity(new UserData {Username = "Anonymous"}, false);
                }

                HttpContext.Current.User = new CustomPrincipal(customIdentity);

            base.OnActionExecuting(filterContext);
        }
    }

お役に立てば幸いです。

このアクションフィルターをグローバルフィルターとして登録することを忘れないでください。あなたはこれを次のように行うことができます:

    private static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new LoadCustomPrincipalAttribute());
    }

これを追加するだけです。放っておいてAuthorizeAttributeください。意図したとおりに機能するはずです。状態をチェックするだけHttpContext.Current.User.Identity.IsAuthenticated == trueです。それを上書きする必要がある状況がありますが、これはそうではありません。開始する前に、適切なユーザー/認証処理が本当に必要ですAuthorizeAttribute

于 2013-03-09T18:55:51.393 に答える
0

ピーターに同意しました。これが私がAngularJsアプリに対して行ったことです。ロックアウト日をチェックする属性を作成します。YourAppUserManagerを正しいものに変更します。

public class LockoutPolicyAttribute : ActionFilterAttribute
{
    public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            var now = DateTime.UtcNow;

            var currentUserId = Convert.ToInt32(HttpContext.Current.User?.Identity?.GetUserId());

            var user = await HttpContext.Current.GetOwinContext().GetUserManager<YourAppUserManager>().FindByIdAsync(currentUserId);

            if (user?.LockedOutUntil >= now)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse((HttpStatusCode)423, "Account Lockout");
                return;
            }
        }

        base.OnActionExecuting(actionContext);
    }
}

次に、ログインページにリダイレクトするステータスコード423のAngularJsインターセプトサービスを用意します。

switch (response.status) {
            case 423: //Account lockout sent by the server.
                AuthService.logOut();
                window.location.href = '/login';
于 2017-08-29T19:49:49.880 に答える