web-dev-qa-db-ja.com

ASP.NET Core 2.0認証ミドルウェア

Core 1.1では@ blowdartのアドバイスに従い、カスタムミドルウェアを実装しました。

https://stackoverflow.com/a/31465227/29821

それはこのように働いた:

  1. ミドルウェアが走った。リクエストヘッダからトークンを取得しました。
  2. トークンを検証し、有効な場合は複数のクレームを含むID(ClaimsIdentity)を作成し、それをHttpContext.User.AddIdentity()で追加しました。
  3. Services.AddAuthorizationを使用したConfigureServicesで、ミドルウェアによって提供される要求を要求するためのポリシーを追加しました。
  4. コントローラ/アクションでは、[Authorize(Roles = "ミドルウェアが追加したロール")]を使用します。

ただし、トークンが有効ではなく(上記の手順2)、クレームが追加されない場合は「authenticationSchemeが指定されていないため、DefaultChallengeSchemeが見つかりませんでした」と表示されます。

だから今私はauthが2.0で変更されたことを読んでいます:

https://docs.Microsoft.com/ja-jp/aspnet/core/migration/1x-to-2x/identity-2x

ASP.NET Core 2.0で同じことを実行するための正しい方法は何ですか?本当にカスタム認証をする例は見当たりません。

76
pbz

それで、この問題を解決しようとした長い一日の後、私はMicrosoftがどうやってコア2.0の新しいシングルミドルウェア設定のためのカスタム認証ハンドラを作って欲しいかを考え出しました。

MSDNのドキュメントをいくつか調べたところ、IAuthenticationHandlerインターフェースを実装するAuthenticationHandler<TOption>というクラスが見つかりました。

そこから、私は https://github.com/aspnet/Security にある既存の認証方式を持つコードベース全体を見つけました。

これらのうちの1つの内部では、MicrosoftがJwtBearer認証方式をどのように実装しているかを示しています。 ( https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer

私はそのコードの大部分を新しいフォルダにコピーし、JwtBearerに関連することをすべてクリアしました。

JwtBearerHandlerクラス(AuthenticationHandler<>を拡張する)では、Task<AuthenticateResult> HandleAuthenticateAsync()のオーバーライドがあります。

私は私たちの古いミドルウェアにカスタムトークンサーバを通してクレームを設定するために追加しました、そしてまだトークンが無効であり、クレームが設定されていないとき200 OKの代わりに401 Unauthorizedを吐き出す許可に関していくつかの問題に遭遇しました。

私はTask HandleChallengeAsync(AuthenticationProperties properties)をオーバーライドしたことに気付きました。それは何らかの理由でコントローラーの[Authorize(Roles="")]経由でパーミッションを設定するために使われます。

このオーバーライドを削除した後、コードは機能し、権限が一致しなかったときに401を正常にスローしました。

ここからの主な注意点は、今度はカスタムミドルウェアを使用できず、AuthenticationHandler<>を介してそれを実装する必要があり、services.AddAuthentication(...)を使用するときはDefaultAuthenticateSchemeおよびDefaultChallengeSchemeを設定する必要があるということです。

これがすべてこのように見えるはずであるという例です:

Startup.cs/ConfigureServices()に次の行を追加します。

services.AddAuthentication(options =>
{
    // the scheme name has to match the value we're going to use in AuthenticationBuilder.AddScheme(...)
    options.DefaultAuthenticateScheme = "Custom Scheme";
    options.DefaultChallengeScheme = "Custom Scheme";
})
.AddCustomAuth(o => { });

Startup.cs/Configure()に次の行を追加します。

app.UseAuthentication();

新しいファイルCustomAuthExtensions.csを作成します。

public static class CustomAuthExtensions
{
    public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions)
    {
        return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
    }
}

新しいファイルCustomAuthOptions.csを作成します。

public class CustomAuthOptions: AuthenticationSchemeOptions
{
    public CustomAuthOptions()
    {

    }
}

新しいファイルを作成するCustomAuthHandler.cs

internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
{
    public CustomAuthHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
    {
        // store custom services here...
    }
    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        // build the claims and put them in "Context"; you need to import the Microsoft.AspNetCore.Authentication package
        return AuthenticateResult.NoResult();
    }
}
166
Zac

参照している記事が指摘しているように、Core 1.xからCore 2.0へのIdentityの変更はかなりあります。主な変更点は、ミドルウェアのアプローチから脱却し、依存性注入を使用してカスタムサービスを設定することです。これにより、より複雑な実装向けにIdentityをカスタマイズする際の柔軟性が大幅に向上します。それで、あなたはあなたが上で言及したミドルウェアアプローチから離れて、そしてサービスに向かって移動したいです。この目標を達成するには、参照されている記事の移行手順に従ってください。 app.UseIdentityapp.UseAuthenticationに置き換えます。 UseIdentityは推奨されなくなり、将来のバージョンではサポートされなくなります。カスタムクレーム変換を挿入してクレームに対して承認を実行する方法の完全な例については 、このブログ投稿 を参照してください。

3
Kevin Junghans