[英]AllowAnonymous not working with Custom AuthorizationAttribute
这让我难住了一段时间。 常见的类似情况似乎都不适用于这里。 我可能错过了一些明显的东西,但我看不到它。
在我的 Mvc Web 应用程序中,我以这样一种方式使用 Authorize 和 AllowAnonymous 属性,您必须明确地打开一个公开可用的操作,而不是锁定站点的安全区域。 我更喜欢这种方法。 但是,我无法在我的 WebAPI 中获得相同的行为。
我编写了一个从 System.Web.Http.AuthorizeAttribute 继承的自定义授权属性,如下所示:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class MyAuthorizationAttribute : System.Web.Http.AuthorizeAttribute
我已将此注册为过滤器:
public static void RegisterHttpFilters(HttpFilterCollection filters)
{
filters.Add(new MyAuthorizationAttribute());
}
这一切都按预期工作,如果没有凭据,操作将不再可用。 问题是现在下面的方法不允许 AllowAnonymous 属性来做它的事情:
[System.Web.Http.AllowAnonymous]
public class HomeController : ApiController
{
[GET("/"), System.Web.Http.HttpGet]
public Link[] Index()
{
return new Link[]
{
new SelfLink(Request.RequestUri.AbsoluteUri, "api-root"),
new Link(LinkRelConstants.AuthorizationEndpoint, "OAuth/Authorize/", "authenticate"),
new Link(LinkRelConstants.AuthorizationTokenEndpoint , "OAuth/Tokens/", "auth-token-endpoint")
};
}
}
最常见的情况似乎是混淆了两个 Authorize / AllowAnonymous 属性。 System.Web.Mvc 用于 Web 应用程序,而 System.Web.Http 用于 WebAPI(据我所知)。
我使用的两个属性都来自同一个命名空间 - System.Web.Http。 我认为这只会继承基本功能,并允许我在 OnAuthotize 方法中注入我需要的代码。
根据文档, AllowAnonymous 属性在我立即调用的 OnAuthorize 方法中起作用:
public override void OnAuthorization(HttpActionContext actionContext)
{
base.OnAuthorization(actionContext);
任何想法将不胜感激。
有没有人以前遇到过这个问题并找到了根本原因?
在 AuthorizeAttribute 中有以下代码:
private static bool SkipAuthorization(HttpActionContext actionContext)
{
Contract.Assert(actionContext != null);
return actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()
|| actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
}
将此方法包含在您的 AuthorizeAttribute 类中,然后将以下内容添加到 OnAuthorization 方法的顶部以在找到任何 AllowAnonymous 属性时跳过授权:
if (SkipAuthorization(actionContext)) return;
ASP.NET MVC 4:
bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
要么
private static bool SkipAuthorization(AuthorizationContext filterContext)
{
Contract.Assert(filterContext != null);
return filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any()
|| filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any();
}
来源: http ://weblogs.asp.net/jongalloway/asp-net-mvc-authentication-global-authentication-and-allow-anonymous
就我而言,上述解决方案均无效。 我正在使用带有自定义IAuthorizationFilter
.Net Core 3.1,我必须执行以下操作:
public void OnAuthorization(AuthorizationFilterContext context)
{
if (context.ActionDescriptor.EndpointMetadata.OfType<AllowAnonymousAttribute>().Any()) return;
使用 MVC 5
解决此问题的步骤:-
1.更新您的WebAPI项目的匿名属性并使其像
[System.Web.Mvc.AllowAnonymous]
现在转到您的自定义属性类并编写代码
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext filterContext) { if (filterContext == null) { throw new UnauthorizedAccessException("Access Token Required"); } base.OnAuthorization(filterContext); if (filterContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()) { return; } if (filterContext.Request.Headers.Authorization != null) { var response = PTPRestClient.GetRequest(filterContext.Request.Headers.Authorization.ToString(), "api/validate/validate-request"); if (!response.IsSuccessStatusCode) { throw new UnauthorizedAccessException(); } } else { throw new UnauthorizedAccessException("Access Token Required"); } }
这是 ASP.NET Core 2+ 和 ASP.NET Core 3+ 的解决方案。 将其添加到 IAsyncAuthorizationFilter 实现中:
private static bool HasAllowAnonymous(AuthorizationFilterContext context)
{
var filters = context.Filters;
return filters.OfType<IAllowAnonymousFilter>().Any();
}
并像这样检查:
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if(HasAllowAnonymous(context))
return;
}
使用 C#6.0 创建一个扩展 ActionExecutingContext 的静态类。
public static class AuthorizationContextExtensions {
public static bool SkipAuthorization(this ActionExecutingContext filterContext) {
Contract.Assert(filterContext != null);
return filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any()|| filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any();
}
}
现在您的覆盖 filterContext 将能够调用扩展方法,只需确保它们在相同的命名空间中,或者包含正确的 using 语句。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeCustomAttribute : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
if (filterContext.SkipAuthorization()) return;// CALL EXTENSION METHOD
/*NOW DO YOUR LOGIC FOR NON ANON ACCESS*/
}
}
我必须使用不同版本的 .net 框架或 web api,但希望这对某人有所帮助:
bool skipAuthorization = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any() || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
if (skipAuthorization)
{
return;
}
public class MyAuthorizationAuthorize : AuthorizeAttribute, IAuthorizationFilter
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) ||
filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
if (skipAuthorization) return;
}
else filterContext.Result = new HttpUnauthorizedResult();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.