development

Ajax 호출에서 세션 시간 초과 처리

big-blog 2020. 12. 28. 22:28
반응형

Ajax 호출에서 세션 시간 초과 처리


asp.net mvc 컨트롤러 작업에 jquery를 사용하여 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로 설정되지만 컨트롤러 작업으로 계속 진행되고 개체 오류의 인스턴스로 설정되지 않은 개체 참조를 throw 한 다음 오류 500을 다시 클라이언트 측 js로 반환합니다. 사용자 지정 Authorize 속성을 변경하여 ajax 요청을 확인하고 인증되지 않은 요청에 대해 false를 반환하면 ajax 요청이 분명히 작동하지 않는 로그인 페이지를 반환하게됩니다.

이 작업을 어떻게 수행합니까?


[Authorize]클라이언트 스크립트가 시나리오를 정상적으로 처리 할 수 ​​있도록 허용하는 무단 액세스의 경우 401 예외를 발생시키는 대신 JSON을 반환 하는 사용자 지정 속성을 작성할 수 있습니다.

[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
    }
});

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

글로벌 js ajax 오류 핸들러를 추가하십시오.

   $(document).ajaxError(function (xhr, props) {
        if (props.status === 401) {
            location.reload(); 
        }
   }

이것은 과거의 답변이지만 .NET 4.5를 사용하는 경우 가장 짧고 가장 달콤한 대답이라고 생각합니다. SuppressFormsAuthenticationRedirect라는 작은 속성이 추가되었습니다. true로 설정하면 302 로그인 페이지로 리디렉션을 수행하지 않습니다.

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 요청 실패 / 오류 콜백을 처리 할 계획이라고 가정하면 401 Unauthorized가 발생합니다.


마스터 페이지에서이 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");
                    }

                }


}
}

}

비슷한 문제가 있었는데 이것을 발견 했습니다.

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 또는 사용중인 모든 항목에서 처리하도록 할 수 있습니다.


여기에 내 사용자 지정 인증에서 이것을 매우 간단한 방식으로 처리하는 방법이 있습니다. 세션이 종료되었는지 확인하고 부울을 사용하여 권한이없는 것으로 처리하여 실제로 인증되었지만 권한이 없는지 확인합니다 (승인되지 않은 페이지로 리디렉션). 또는 세션 시간 초과로 인해 인증되지 않았습니다 (로그인으로 리디렉션).

 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");
        }


    }

Hope if this guides someone and please if there're comments its appreciated to know them though.


You might want to try to throw HttpException and catch it in your javascript.

throw new HttpException(401, "Auth Failed")

on ajax call if session expired return something like this

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

haha...

ReferenceURL : https://stackoverflow.com/questions/5238854/handling-session-timeout-in-ajax-calls

반응형