问题
Problem
Long story short, how can you prevent unauthorized ChildActions to return a 401 code and return an empty result instead.
Context
My application uses NTLM to authenticate on the network. I also want to handle anonymous identification, for non NTLM capable devices or if someone goes through some proxy.
One the the web application, there is controller/actions that absolutely require to be logged in to be viewable and some other that are viewable as anonymous. For the ones that authentication is mandatory where I initially used the following:
[Authorize()]
public class SomeController : BaseController
Which works as expected and returns a 401 Status Code (Unauthorized).
The problem starts on the page that allows anonymous. Because those pages have parts that uses RenderAction to render pieces that requires authentication.
On local developpement server on front end everything looks fine, but with IIS any page that have any small piece that requires authentication it returns 401 page. So I created a custom Authorize attribute:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public bool Ignore401ChildAction { get; set; }
public CustomAuthorizeAttribute()
: base() {
this.Ignore401ChildAction = true;
}
protected override void HandleUnauthorizedRequest( AuthorizationContext filterContext ) {
base.HandleUnauthorizedRequest( filterContext );
if( this.Ignore401ChildAction && filterContext.IsChildAction ) {
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
}
And then on frontend it seems to produce correct behavior with and without IIS. However in the backend, even if the page renders completly it returns a 401
So I added the following to my CustomAttribute instead of TrySkipIisCustomErrors
filterContext.HttpContext.Response.StatusCode = 200;
filterContext.Result = new EmptyResult();
In anonymous everything is fine, but when NTLM is enabled server doesn't request authentication when the controller doesnt have that CustomAuthorize attribute. It seems like its only requesting the crendetials when their mandatory instead of when they're available.
Thank you,
EDIT
After lot of searching, digging and fiddling, realized that true problem is that Anonymous identification will take precedence over Windows/NTLM. If Anonymous and Windows authentication are enabled, Windows will only execute if anonymous authentication fails.
SOLUTION
(not perfect and kind of hackish but it works)Add the following function to your BaseController then call from the views that do not mandatory require authentication, or simply call it from your _Layout view.
NOTE: Even though page will render correctly as anonymous, a 401 status code will still be returned.
[CustomAuthorize]
public ActionResult Auth() {
return new EmptyResult();
}
来源:https://stackoverflow.com/questions/12091116/how-to-prevent-unauthorized-child-action-to-return-401