Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>EDIT:</strong></p> <p>I wrote above answer a long time ago and now I believe that sending 403 is not proper way to go. 403 has slightly different meaning and it just shouldn't be used. This is corrected attribute using 401. It differs only with additional <code>context.HttpContext.Response.End()</code> in Http401Result and different HTTP code:</p> <pre><code>public class OptionalAuthorizeAttribute : AuthorizeAttribute { private class Http401Result : ActionResult { public override void ExecuteResult(ControllerContext context) { // Set the response code to 401. context.HttpContext.Response.StatusCode = 401; context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue); context.HttpContext.Response.End(); } } private readonly bool _authorize; public OptionalAuthorizeAttribute() { _authorize = true; } //OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller. //That is why parameter is introduced. public OptionalAuthorizeAttribute(bool authorize) { _authorize = authorize; } protected override bool AuthorizeCore(HttpContextBase httpContext) { //When authorize parameter is set to false, not authorization should be performed. if (!_authorize) return true; var result = base.AuthorizeCore(httpContext); return result; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest()) { //Ajax request doesn't return to login page, it just returns 401 error. filterContext.Result = new Http401Result(); } else base.HandleUnauthorizedRequest(filterContext); } } </code></pre> <p><strong>OLD ANSWER:</strong></p> <p>While I like the ideas posted in other answers (which I had an idea about earlier), I needed code samples. Here they are:</p> <p>Modified Authorize attribute:</p> <pre><code>public class OptionalAuthorizeAttribute : AuthorizeAttribute { private class Http403Result : ActionResult { public override void ExecuteResult(ControllerContext context) { // Set the response code to 403. context.HttpContext.Response.StatusCode = 403; context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue); } } private readonly bool _authorize; public OptionalAuthorizeAttribute() { _authorize = true; } //OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller. //That is why parameter is introduced. public OptionalAuthorizeAttribute(bool authorize) { _authorize = authorize; } protected override bool AuthorizeCore(HttpContextBase httpContext) { //When authorize parameter is set to false, not authorization should be performed. if (!_authorize) return true; var result = base.AuthorizeCore(httpContext); return result; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest()) { //Ajax request doesn't return to login page, it just returns 403 error. filterContext.Result = new Http403Result(); } else base.HandleUnauthorizedRequest(filterContext); } } </code></pre> <p><code>HandleUnauthorizedRequest</code> is overridden, so it returns <code>Http403Result</code> when using Ajax. <code>Http403Result</code> changes StatusCode to 403 and returns message to the user in response. There is some additional logic in attribute (<code>authorize</code> parameter), because I turn on <code>[Authorize]</code> in the base controller and disable it in some pages.</p> <p>The other important part is global handling of this response on client side. This is what I placed in Site.Master:</p> <pre><code>&lt;script type="text/javascript"&gt; $(document).ready( function() { $("body").ajaxError( function(e,request) { if (request.status == 403) { alert(request.responseText); window.location = '/Logout'; } } ); } ); &lt;/script&gt; </code></pre> <p>I place a GLOBAL ajax error handler and when ever <code>$.post</code> fails with a 403 error, the response message is alerted and the user is redirected to logout page. Now I don't have to handle the error in every <code>$.post</code> request, because it is handled globally.</p> <p>Why 403, and not 401? 401 is handled internally by MVC framework (that is why redirection to login page is done after failed authorization).</p> <p>What do you think about it?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload