问题
So, I have web apps with web.configs like so:
<authorization>
<deny users="?"/>
</authorization>
...
<location path="SomeUnsecuredPage.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
In other words, most pages require authentication and authorization, but some don't.
Then I have an IHttpModule that will be used by all the different applications. All I want to do is check if the current request is "secured" at all. If the page doesn't require authorization I don't want my IHttpModule to do anything at all. I am using FormsAuthentication and I assume that FormsAuthentication already has all of this information cached somewhere, doesn't it? Also, since this check will be running constantly so it has to be very quick.
I am currently subscribing to the HttpApplication.AuthorizeRequest, but surprisingly this event fires even for resources that allow anonymous access.
Any ideas? Thanks for reading!
回答1:
Instead of creating a bootleg principal/identity you can just use a generic identity.
public bool IsAnonymousAccessAllowed()
{
return UrlAuthorizationModule.CheckUrlAccessForPrincipal(Request.Path, new GenericPrincipal(new GenericIdentity(""), new string[0]), Request.RequestType);
}
回答2:
Create a bootleg IPrincipal and then you have to use that. If the bootleg principal has access then anonymous access is allowed.
public static class AnonymousAccessCheck
{
public static bool IsAnonymousAccessAllowed(HttpRequest request)
{
// unfortunately checking if a page allows anonymous access is more complicated than you'd think(I think).
// here we have to create a "Fake" IPrincipal that will only ever have access to
// pages that allow anonymous access. That way if our fake principal has access,
// then anonymous access is allowed
UrlAuthorizationModule urlAuthorizationModule = new UrlAuthorizationModule();
return UrlAuthorizationModule.CheckUrlAccessForPrincipal(request.Path, AnonymousPrincipal.Instance, request.RequestType);
}
private class AnonymousPrincipal : IPrincipal
{
private static AnonymousPrincipal _Instance;
public static AnonymousPrincipal Instance
{
get
{
if (_Instance == null)
_Instance = new AnonymousPrincipal();
return _Instance;
}
}
private AnonymousPrincipal()
{
_Identity = new AnonymousIdentity();
}
private readonly IIdentity _Identity;
#region IPrincipal Members
public IIdentity Identity
{
get { return _Identity; }
}
public bool IsInRole(string role)
{
return false;
}
#endregion
private class AnonymousIdentity : IIdentity
{
#region IIdentity Members
public string AuthenticationType
{
get { return string.Empty; }
}
public bool IsAuthenticated
{
get { return false; }
}
public string Name
{
get { return string.Empty; }
}
#endregion
}
}
}
回答3:
I think if server returns response with 401 Unauthorized status code, resource may require authorization. But sometimes server may redirect to login page, so this method is not very reliable.
回答4:
derp!
HttpContext.Current.SkipAuthorization
回答5:
A more direct approach is the following:
var method = typeof(UrlAuthorizationModule).GetMethod("RequestRequiresAuthorization", BindingFlags.NonPublic | BindingFlags.Static);
var requiresAuthentication = (Boolean)method.Invoke(null, new object[] { HttpContext.Current });
Before using this, make sure that your web site has permissions to perform reflection.
<Rant>
I've never understood why Microsoft hide's so much of their API using "internal" (like this method). In my opinion, if Microsoft had to expose something internally then chances are somebody, somewhere will have need of it as well.
</Rant>
来源:https://stackoverflow.com/questions/3390719/determine-if-current-page-requires-authorization