2012-11-28 25 views
41

これは私をしばらく困惑させました。一般的に遭遇する同様の状況のどれも、明らかにここには当てはまらないようです。私はおそらく明白な何かを逃したが、私はそれを見ることができない。AllowAnonymousがカスタム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") 
     }; 
    } 
} 

最も一般的なシナリオは、以下の2つの承認/の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で

+0

は必ず' System.Web.Mvc.AllowAnonymousAttribute'を使用して作成していませんSystem.Web.Http.AllowAnonymousAttribute'。それは私に起こり、私はそれを3時間後に実現しました... – ToXinE

答えて

69

次のコードがある:

private static bool SkipAuthorization(HttpActionContext actionContext) 
{ 
    Contract.Assert(actionContext != null); 

    return actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any() 
       || actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any(); 
} 

があなたのAuthorizeAttributeクラスでこのメソッドを含め、その後の任意のAllowAnonymous属性が発見された場合は、許可をスキップするあなたOnAuthorizationメソッドの先頭に次の行を追加します。

if (SkipAuthorization(actionContext)) return; 
+1

は、私がカスタムAuthorizationFilterAttributeを追加したときに同じ問題を発見し、これを解決しました。 –

+2

このコードには直感的な振る舞いがあります。コントローラーの '[AllowAnonymous]'属性は、メソッドのすべての認証属性を上書きします**。これを防ぐために、 'IAuthorizationFilter'(またはあなたが使っている基本クラス/インタフェース)に対して' ActionDescriptor'の別のカスタム属性チェックを追加し、匿名コントローラがtrueのときにfalseの場合は認証をスキップします。 – Nick

+2

本当ですが、それは設計上の問題でもあると私は主張します。同じコントローラに安全なアクションと安全でないアクションを混在させる場合は、物事を動かす時が来ます。 – Jammer

18

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(); 
    } 

Soruce:http://weblogs.asp.net/jongalloway/asp-net-mvc-authentication-global-authentication-and-allow-anonymous

+0

ユーザーがmvcではなくWeb APIの動作を要求しました。 –

0

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*/ 
    } 
} 
0

私は、.NET FrameworkやWeb APIの異なるバージョンを使用する必要がありますが、うまくいけば、これは誰かに役立ちます: `

 bool skipAuthorization = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any() || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any(); 
     if (skipAuthorization) 
     { 
      return; 
     } 
関連する問題