Ajax problem Call to action Method on the controller requiring an authenticated user

Using a technique that I found in a recent ASP.NET MVC book, I have a controller action method that returns a partial view for an ajax request and a full action view for a regular receive request - it checks the IsAjaxRequest property of the Request object to determine what type of action needs to be returned. The partial view returned by the action method returns HTML for displaying a table of records from the database. The controller containing the action method is marked with the Authorize attribute, so only registered users can call controller methods. I use forms authentication with a 30 minute timeout and expiration.

The problem occurs after the user has reached the 30 minute timeout. Since the controller is marked with the Authorize attribute, calling the action method after the timeout exposes the user to the login page. However, since this is an ajax call, the html for my login page is returned and displayed in the middle of the page, which should contain an HTML record table, which is usually returned by the action method in a partial view. The ajax call doesn't actually work, just returning html for the wrong page.

Has anyone encountered and encountered this problem? I try not to move all my code on the server side, which processes ajax calls to a separate controller, which does not require an authenticated user, but this seems like my only alternative at the moment. Even this will not lead to the behavior that I would expect, because it will allow the user to continue using the web page even after the 30-minute timeout has been reached - it will not be redirected to the login page.

Thanks for any advice.


Edit

The solution below with a custom attribute, AuthorizeAttribute, seems to direct me in the right direction, but I can't even get to this code. It appears that the code in the custom attribute, AuthorizeAttribute, is never reached after the expiration timeout. Forms authentication seems to cause a redirect to the login page long before the attribute code. The custom attribute AuthorizeAttribute is the only one on my controller. I also have the following web.config values ​​(the timeout value is set extremely low to cause a timeout for testing):

<authentication mode="Forms"> <forms loginUrl="~/Account/Login" timeout="1" slidingExpiration="true" defaultUrl="~/ErrorReport/Index" requireSSL="true" protection="All"/> </authentication> <authorization> <deny users="?"/> <allow users="*"/> </authorization> <location path="Content"> <system.web> <authorization> <allow users="*"/> </authorization> </system.web> </location> <location path="Scripts"> <system.web> <authorization> <allow users="*"/> </authorization> </system.web> </location> 

Are web.config authorization elements interfering? Should I use them with ASP.NET MVC?

+4
source share
2 answers

I actually have a blog post queued about it, which I will add to the comment when it was posted, but what’s happening here right now.

At a high level, when the ASP.NET runtime sees a 401 response code, it automatically converts it to a redirect and sends the user to the login page. What you want to do is workaround, which is 401 .

In MVC, when you use AuthorizeAttribute , it checks if the user is allowed, and if not, returns HttpUnauthorizedResult . This basically forces the runtime to redirect the user to the login page. What you want to do is override this behavior.

To do this, extend the AuthorizeAttribute as such:

 public class AuthorizeWithAjaxAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.HttpContext.Response.StatusCode = 200; filterContext.Result = /* Some result recognized by the client */ } } } 

When you make an AJAX request, and the response data is equal to what you return as the result of the filter context, just redirect the user to the login page through javascript.

+6
source

Yes, this problem is quite common. This also has a simple solution - in the part of the Javascript that handles the AJAX response, check that there is a timeout before using the response. If a timeout occurs, redirect the user to the login page.

Alternatively, if the server side of the script itself checks the session timeout (which is similar to your case), it becomes even easier. Do not return the entire login page, but simply return the "need_login" flag. Alternatively, just write a Javascript handler to check if the return value is "need_login" and load the login page, if true.

+1
source

All Articles