57

jqueryを使用してasp.netmvcコントローラーアクションに対してajax呼び出しを行っています:

[AcceptVerbs(HttpVerbs.Post)]
        public ActionResult GetWeek(string startDay)
        {
            var daysOfWeek = CompanyUtility.GetWeek(User.Company.Id, startDay);
            return Json(daysOfWeek);
        }

セッションがタイムアウトすると、Userオブジェクトがセッションに保存されるため、この呼び出しは失敗します。セッションが失われたかどうかを確認し、ログインページにリダイレクトするために、カスタムの承認属性を作成しました。これはページリクエストでは正常に機能しますが、ajaxリクエストからリダイレクトできないため、ajaxリクエストでは機能しません。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthorizeUserAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (!httpContext.Request.IsAjaxRequest())
            {//validate http request.
                if (!httpContext.Request.IsAuthenticated
                    || httpContext.Session["User"] == null)
                {
                    FormsAuthentication.SignOut();
                    httpContext.Response.Redirect("~/?returnurl=" + httpContext.Request.Url.ToString());
                    return false;
                }
            }
            return true;
        }
    }

別のスレッドで、ユーザーが認証されておらず、ajaxリクエストを行う場合は、ステータスコードを401(未承認)に設定してから、jsで確認し、ログインページにリダイレクトする必要があることを読みました。ただし、これを機能させることはできません。

protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (Request.IsAjaxRequest() && (!Request.IsAuthenticated || User == null))
            {
                filterContext.RequestContext.HttpContext.Response.StatusCode = 401;
            }
            else
            {
                base.OnActionExecuting(filterContext);
            }
        }

基本的には401に設定されますが、その後コントローラーアクションに進み、オブジェクトエラーのインスタンスに設定されていないオブジェクト参照をスローします。これにより、エラー500がクライアント側のjsに返されます。カスタムのAuthorize属性を変更してajaxリクエストも検証し、認証されていないリクエストに対してfalseを返すと、ajaxリクエストはログインページを返しますが、これは明らかに機能しません。

これを機能させるにはどうすればよいですか?

4

8 に答える 8

86

不正アクセスの場合に401例外をスローする代わりに、JSONを返すカスタム[Authorize]属性を記述して、クライアントスクリプトがシナリオを適切に処理できるようにすることができます。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.Result = new JsonResult
            {
                Data = new 
                { 
                    // put whatever data you want which will be sent
                    // to the client
                    message = "sorry, but you were logged out" 
                },
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

次に、コントローラー/アクションをそれとクライアントで装飾します。

$.get('@Url.Action("SomeAction")', function (result) {
    if (result.message) {
        alert(result.message);
    } else {
        // do whatever you were doing before with the results
    }
});
于 2011-03-09T07:43:38.940 に答える
38

JsonRequestBehaviorをAllowGetに変更しません。代わりに私は提案します:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class MyAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        OnAuthorizationHelp(filterContext);
    }

    internal void OnAuthorizationHelp(AuthorizationContext filterContext)
    {

        if (filterContext.Result is HttpUnauthorizedResult)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.HttpContext.Response.StatusCode = 401;
                filterContext.HttpContext.Response.End();
            }
        }
    }
}

そして、グローバルjsajaxエラーハンドラーを追加します。

   $(document).ajaxError(function (xhr, props) {
        if (props.status === 401) {
            location.reload(); 
        }
   }
于 2012-06-02T22:14:42.277 に答える
10

これは過去の回答ですが、.NET 4.5を使用している場合、これが最短で最も甘い回答だと思います。追加されたSuppressFormsAuthenticationRedirectと呼ばれる小さなプロパティ。trueに設定すると、302 Redirecttologinページは実行されません。

http://msdn.microsoft.com/en-us/library/system.web.httpresponse.suppressformsauthenticationredirect.aspx

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        // returns a 401 already
        base.HandleUnauthorizedRequest(filterContext);
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            // we simply have to tell mvc not to redirect to login page
            filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
        }
    }
}

ajaxリクエストの失敗/エラーコールバックの処理を計画していると仮定すると、401Unauthorizedが発生します。

于 2013-05-11T02:22:34.907 に答える
7

マスターページで、このjqueryスクリプトを追加します------------

<script type="text/javascript">

   $.ajaxSetup({
        statusCode: {
            403: function () {
                window.location.reload();
            }
        }
    });


    OR


    $.ajaxSetup({
        error: function (x, e) {
            if (x.status == 403) {
                window.location.reload(); 
            }
        }
    });

</script>

プロジェクトにTraceFilterという名前のcsファイルを追加し、ActionFilterAttributeを継承する封印されたクラスTraceFilterAttributeを記述します。以下の行を記述して、プロジェクトのApp_StartフォルダーにあるFilterConfig.csにTraceFilterAttributeクラスを追加します。

filters.Add(new TraceFilterAttribute());

TraceFilterAttributeクラスのメソッドOnActionExecuting()をオーバーライドします。これにより、セッションが自動的にチェックされ、セッションnullが見つかった場合は、マスターページで使用可能なスクリプトが呼び出され、そこから選択したページに移動できます。

[AttributeUsage(AttributeTargets.All)]
public sealed class TraceFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext != null)
        {
HttpSessionStateBase objHttpSessionStateBase = filterContext.HttpContext.Session;
                var userSession = objHttpSessionStateBase["etenetID"];
if (((userSession == null) && (!objHttpSessionStateBase.IsNewSession)) || (objHttpSessionStateBase.IsNewSession))
                {
                    objHttpSessionStateBase.RemoveAll();
                    objHttpSessionStateBase.Clear();
                    objHttpSessionStateBase.Abandon();
                    if (filterContext.HttpContext.Request.IsAjaxRequest())
                    {
                        filterContext.HttpContext.Response.StatusCode = 403;
                        filterContext.Result = new JsonResult { Data = "LogOut" };
                    }
                    else
                    {
                        filterContext.Result = new RedirectResult("~/Admin/GoToLogin");
                    }

                }


}
}

}
于 2013-07-01T11:46:14.557 に答える
4

私は同様の問題を抱えていて、これを見つけまし

JSONを返す代わりに、応答が返される直前に、ASP.NETに401コードを返すように強制します。でGlobal.asax

protected void Application_EndRequest()
    {
        var context = new HttpContextWrapper(Context);
        if (context.Request.IsAjaxRequest() && context.Response.StatusCode == 302)
        {
            Context.Response.Clear();
            Context.Response.Write("**custom error message**");
            Context.Response.StatusCode = 401;
        }
    }

次に、JavaScript/jQueryまたは使用しているものでクライアントに処理させることができます

于 2012-12-15T18:37:36.753 に答える
1

これが私のカスタム認証でこれを非常に簡単な方法で処理する方法です。セッションがアウトであるかどうかを確認し、ブール値を使用してこれを未承認として処理し、実際に認証されているが承認されていないかどうかを確認します(未承認のページにリダイレクトするため)または、セッションがタイムアウトしたために認証されていません(ログインにリダイレクト)

 private bool ispha_LoggedIn = false;
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        ispha_LoggedIn = false;
        var session = httpContext.Session;
        bool authorize = false;
        if (httpContext.Session["authenticationInfo"] == null)
        {

            return authorize;
        }

        using (OrchtechHR_MVCEntities db = new OrchtechHR_MVCEntities())
        {
            UserAuthenticationController UM = new UserAuthenticationController();
            foreach (var roles in userAssignedRoles)
            {
                authorize = UM.IsUserInRole(httpContext.User.Identity.Name, roles);

                if (authorize)
                {

                    return authorize;
                }

            }
        }
        ispha_LoggedIn = true;
        return authorize;
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (ispha_LoggedIn==false)
        {
            filterContext.Result = new RedirectResult("~/UserAuthentication/LogIn");
        }
        else
        {
            filterContext.Result = new RedirectResult("~/Dashboard/UnAuthorized");
        }


    }

これが誰かを導くことを願っています、そしてコメントがあればそれを知っていただければ幸いです。

于 2016-05-07T14:55:58.857 に答える
0

HttpExceptionをスローして、JavaScriptでキャッチすることをお勧めします。

throw new HttpException(401, "Auth Failed")
于 2011-03-08T22:11:32.500 に答える
-3

セッションが期限切れになった場合のajax呼び出しで、次のようなものを返します

<script>
$(function(){
    location.reload();
});
</script>

はは...

于 2016-03-31T16:07:45.617 に答える