2016-02-26 43 views
16

ASP.Net WebAPIを使用する場合、状況によっては、または401のいずれかを返すために使用するcustom Authorize attributeがありました。例えばユーザーが認証されていない場合は、401を返します。ユーザーが認証されていても適切な権限がない場合は、403を返します。それにはSee here for more discussionASP.NetコアのAuthorize属性を使用してHTTP 403を返します。

新しいASP.Netコアでは、代わりにポリシーベースのアプローチを採用しているようですが、今度はdon't want you overriding the Authorize attributeのように見えます。しかし、コアMVCは、前任者が持っていた「すべての認証エラーに対して同じ返信401」の脆弱性があるようです。

私が望む動作を得るためにフレームワークをオーバーライドするにはどうすればよいですか?

+0

@blowdartによると、ユーザーが認証されたが権限のないMVC6 Authorize属性が401の代わりに401を返す場合、バグが発生するか、何か間違っています。 – danludwig

+0

私は、シナリオに関係なく401を返していたということを設計したと仮定しました。その動作が期待されない場合は、aspnet/securityにバグを報告します。 – Chad

+0

ここで最後のコメントを参照してください:http://stackoverflow.com/a/31465227/304832 – danludwig

答えて

7

issue hereを開いた後、実際に動作するはずです。

Startup.Configureでは、app.UseMvc()を呼び出すだけで、他のミドルウェアを登録しないと、認証関連ではなく認証済みですが許可がない場合は、401となります。

ただし、認証ミドルウェアをサポートする認証ミドルウェアを登録すると、認証されていない場合は401、アクセス許可がない場合は403になります。私にとっては、で認証できるJwtBearerMiddlewareを使用しました。キー部分は、ミドルウェアを作成するときにAutomaticChallengeオプションを設定することです:Startup.Configure

あなたがコントローラで Userにアクセスできるように
app.UseJwtBearerAuthentication(new JwtBearerOptions 
{ 
    AutomaticAuthenticate = true, 
    AutomaticChallenge = true 
}); 
app.UseMvc(); 

AutomaticAuthenticateが自動的ClaimsPrincipalを設定します。 AutomaticChallengeは、認証ミドルウェアが認証エラーが発生した場合(この場合、401または403を適切に設定して)応答を変更することを許可します。

独自の認証方式を実装する場合は、AuthenticationMiddlewareおよびAuthenticationHandlerから継承し、JWT implementation worksのようになります。

+1

私はJwtBearerAuthenticationを使用していませんが、cookie authを使用しています。 AutomaticChallenge = trueを設定すると、認証に失敗した場合に自動的にリダイレクトされます。私はリダイレクトは望んでいないが、403の。私がドキュメントで見ることができますから、これは可能性がありません。 – steamrolla

+0

Webフォームの日にCookieの認証がデフォルトで「FormsAuthentication」に戻りました。私はその行動がそのモデルからモデル化されていると思う。例えば誰かが認証されていない場合は、それらをログインページにリダイレクトしてから、認証トークンでCookieが設定されます。 Cookieの認証とJWTの動作をしたい場合は、おそらく 'AuthenticationMiddleware'と' AuthenticationHandler'を使ってカスタム認証スキームを実装する必要があります。 – Chad

+0

素晴らしい答えです。私にとって大きな問題を修正しました。ありがとう! – nhwilly

7

私はミドルウェアでそれをやってしまった:

app.UseMvc()を呼び出す前 Startup.Configureに登録する必要があります
public class AuthorizeCorrectlyMiddleware 
{ 
    readonly RequestDelegate next; 

    public AuthorizeCorrectlyMiddleware(RequestDelegate next) 
    { 
     this.next = next; 
    } 

    public async Task Invoke(HttpContext context) 
    { 
     await next(context); 

     if (context.Response.StatusCode == (int)HttpStatusCode.Unauthorized) 
     { 
      if (context.User.Identity.IsAuthenticated) 
      { 
       //the user is authenticated, yet we are returning a 401 
       //let's return a 403 instead 
       context.Response.StatusCode = (int)HttpStatusCode.Forbidden; 
      } 
     } 
    } 
} 

+0

これは私が提案しようとしていますが、どのように特定のコントローラー/アクションにあなたが属性でできるようにそれを適用することができるか分からない。 – danludwig

+1

パイプラインの他のミドルウェアが既に応答を書き始めると、次のミドルウェア/デリゲートを呼び出してHttpResponse(この場合はstatuscodeを設定)に書き込むことができないため、これは危険です。 –

+0

が忘れてしまった....少なくとも、statuscodeを変更する前にcontext.Response.HasStarted == falseをチェックする必要があります。 –

関連する問題