ASP.NET Core Identity実戦(4)ライセンスプロセス
10566 ワード
皆さん、こんにちは、私はrocket robinです.この文章は一緒にAspを勉強します.Net Coreのライセンスプロセス
以前の記事では、認証と認可は2つの別々のプロセスであり、認証プロセスはIdentityに属していないと述べています.同じライセンス・プロシージャもIdentityではありません.ライセンス・プロシージャがIdentityシリーズに配置されている理由は、認証プロシージャと同じです.メンバー・システムと一緒に配置すると分かりやすいです.
ライセンスプロセスがどこで発生しているかを明らかにする前に、ポリシーのライセンスを知っていれば、このセクションをすばやく参照することができます.
以前に作成したアイテムを開き、Demoというコントローラを追加します.コントローラコードは次のとおりです.
前に登録したアカウントでシステムにログインし、
次にログインを終了し、
この2つの小さな例から,Authorizeプロパティがログインしていないユーザをブロックしているなど,Authorizeプロパティが要求をブロックしていると容易に推測できるだろうか.
Authorizeプロパティがリクエストをブロックしたのではなく、このメソッドにアクセスするために許可される必要があることをマークしただけで、本当にリクエストをブロックしたのは「Mvcミドルウェア」です.ActionはMvcによって実行され、Mvcが実行されるとActionのAuthorizeプロパティが確認され、ライセンス操作を行うかどうか(成功したライセンスはアクセスでき、失敗したらブロックされる(例えばログインにジャンプする)、およびどのようにライセンスするか(動物園の例では、2番目の警備員は確実な状況に応じて決定される)、すなわちカスタムライセンス(ロールなど)が決定されます.
また、アクションメソッドに
今、私たちは2つの点を知っています.認証プロセスAuthenticationは、Authenticationミドルウェアの で発生する.承認プロセスAuthorizationは、Mvcミドルウェアの で発生する.
企業アプリケーションで最も一般的なのは、ロールベースのライセンスです.ロールのライセンスを実現する方法は2つあります.1つは、
ただし、この方法は推奨されません.これでは、「ロール」と「Uri」のバインドを「コードにハードコーディングされています」とします.多くのシーンでは適切ではありません.これから説明するポリシーベースのライセンスでは、ライセンスロジックをカスタマイズできます.これにより、柔軟性が向上します.
デルのライセンスルールは、ユーザーがロール「admin」またはロール「super-admin」を持つという、上のコードクリップと同じ効果を達成することを要求していると仮定し、この目標を徐々に実現します.
ポリシーの名前
次に
では、私たちの
次に、
このプロセッサの動作は、現在のユーザが
前述したように、ロール認可の論理(後述するHandler)と特定の認可のデータを分離しています.
それから、さっき書いた
最後に、元のAttributeを交換します.
これで、最も基本的なポリシーベースのライセンスが完了します.
本明細書の例は簡単であり、すべてのライセンス特性を使用していないため、より詳細な使用方法の参考資料が多く、本稿ではあまり紹介しません.また、ASPを参考にすることができます.NET Coreでは、ポリシーに基づいたライセンスにより、ポリシーのライセンスに関する内容を学習します.
AuthenticationSchemeを指定するコードは、次のようになります.
前ブログでASP.NET Core Identity実戦(3)認証の過程で、Authenticationミドルウェアには複数のHandlerを配置することができ、1つはデフォルトでアクティブ化されているが、残りはパッシブ呼び出しであり、現在、Authorize特性の中で1つのHandlerを選択して実行している.例えば、Authenticationミドルウェアに2つのHandler--CookieAuthenticationHandlerとJwtAuthenticationHandlerを配置し、CookieAuthenticationHandlerによってデフォルトとして指定されていますが、Jwt認証を経由する場合はどうすればいいですか?
ここで重要な問題は、HttpContextがAuthenticationミドルウェアを通過した後にMvcミドルウェアに到着し、MvcがActionで指定されたAuthenticationHandlerを確認したときに、Authenticationプロセスが終了したことである.
どうやってやったの?
また、HttpContextには
2番目のリロードを見ると、AuthenticationSchemeの名前が指定されているので、MvcミドルウェアがAttributeがAuthenticationSchemeを指定したことを検出すると、指定されたAuthenticationHandlerを再選択して要求を認証します.
古いAspでNet時代、私たちはMvcFilterというものを知っています.今も残っています.もしあなたがそれを知らないなら、少し理解することをお勧めします.公式ドキュメントを参照することをお勧めします.
このセクションのタイトルのように、ライセンスは
schemeが指定されている場合は、再認証、ない場合は、前のAuthenticationミドルウェアのライセンス結果を使用します.
この中で再び深く検討する価値があるのは
ライセンスは合計3ステップに分かれています IAuthorizeHandlerの例(前に1つ書いた)(1つ以上かもしれない) を入手実行許可(Handlerごとに許可) がなくなった このコードは簡単です.
ここで我々がプロジェクトに書いたコードと関係があるのはIAuthorizeHandlerの例であり,本稿では
これで授権プロセスは終わり、授権後にどのように操作するかなどの知識点があります.これらは難しくありません.
前情提要
以前の記事では、認証と認可は2つの別々のプロセスであり、認証プロセスはIdentityに属していないと述べています.同じライセンス・プロシージャもIdentityではありません.ライセンス・プロシージャがIdentityシリーズに配置されている理由は、認証プロシージャと同じです.メンバー・システムと一緒に配置すると分かりやすいです.
手がける
ライセンスプロセスがどこで発生しているかを明らかにする前に、ポリシーのライセンスを知っていれば、このセクションをすばやく参照することができます.
以前に作成したアイテムを開き、Demoというコントローラを追加します.コントローラコードは次のとおりです.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IdentityDemo.Controllers
{
[Produces("application/json")]
[Route("api/demo")]
public class DemoController : Controller
{
[Authorize]
[HttpGet]
public object Get()
{
return new
{
User.Identity.Name,
User.Identity.IsAuthenticated
...
前に登録したアカウントでシステムにログインし、
/api/demo
にアクセスすると、次の結果が得られます.{
"name": "[email protected]",
"isAuthenticated": true
}
次にログインを終了し、
/api/demo
に再アクセスすると、ログインページにジャンプします.このプロセスでAuthorize
のプロパティが重要な役割を果たします.次に、Authorizeプロパティを削除し、前の2つの操作を繰り返します.ログインしていない結果は次のとおりです.{
"name": null,
"isAuthenticated": false
}
この2つの小さな例から,Authorizeプロパティがログインしていないユーザをブロックしているなど,Authorizeプロパティが要求をブロックしていると容易に推測できるだろうか.
認証プロセスの発生地
Authorizeプロパティがリクエストをブロックしたのではなく、このメソッドにアクセスするために許可される必要があることをマークしただけで、本当にリクエストをブロックしたのは「Mvcミドルウェア」です.ActionはMvcによって実行され、Mvcが実行されるとActionのAuthorizeプロパティが確認され、ライセンス操作を行うかどうか(成功したライセンスはアクセスでき、失敗したらブロックされる(例えばログインにジャンプする)、およびどのようにライセンスするか(動物園の例では、2番目の警備員は確実な状況に応じて決定される)、すなわちカスタムライセンス(ロールなど)が決定されます.
また、アクションメソッドに
[Authorize]
のタグを付けるだけであれば、IsAuthenticatedがtrueであるかどうか、すなわち認証フェーズ(Authenticationミドルウェア)が認証に合格したかどうかを検証するのがデフォルトの動作です.今、私たちは2つの点を知っています.
ポリシー・ベースの柔軟なライセンス
企業アプリケーションで最も一般的なのは、ロールベースのライセンスです.ロールのライセンスを実現する方法は2つあります.1つは、
Authorize
の特性に直接書かれています.[Authorize(Roles = "admin,super-admin,")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task Test()
ただし、この方法は推奨されません.これでは、「ロール」と「Uri」のバインドを「コードにハードコーディングされています」とします.多くのシーンでは適切ではありません.これから説明するポリシーベースのライセンスでは、ライセンスロジックをカスタマイズできます.これにより、柔軟性が向上します.
ポリシー・ポリシー・ベースの認可
デルのライセンスルールは、ユーザーがロール「admin」またはロール「super-admin」を持つという、上のコードクリップと同じ効果を達成することを要求していると仮定し、この目標を徐々に実現します.
まず、DIに必要なpolicyを登録します。
services.AddAuthorization(options =>
{
options.AddPolicy("role-policy", policy =>
{
policy.AddRequirements(new RoleRequirement("admin","super-admin"));
});
});
ポリシーの名前
role-policy
を指定し、このポリシーの要件を指定しました.要件は主にポリシーの初期値を設定するためです.ポリシー登録時に要件を変更して、権限を柔軟に制御できます.次に
RoleRequirement
を作成しますpublic class RoleRequirement : IAuthorizationRequirement
{
public IEnumerable Roles { get; }
public RoleRequirement(params string[] roles)
{
Roles = roles ?? throw new ArgumentNullException(nameof(roles));
...
では、私たちの
RoleRequirement
の主な機能は、含まれるロールを決定することです.含まれるロールはコンストラクション関数で決定されるので、ロール認可の論理(後述するHandler)と具体的な認可のデータを分離します.次に、
RoleRequirement
に対応するプロセッサを実装します.public class RoleHandler : AuthorizationHandler
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
{
foreach (var item in requirement.Roles)
{
if (context.User.IsInRole(item))
{
context.Succeed(requirement);
return Task.CompletedTask;
}
}
context.Fail();
return Task.CompletedTask;
...
このプロセッサの動作は、現在のユーザが
RoleRequirement
によって指定された任意のロールにいるかどうかを検証することです.ここで、context.Succeed(requirement);
は認証に成功したことを示し、認証に失敗した場合、 context.Fail();
を呼び出す必要はありません.この例では、 context.Fail();
を呼び出すと、認証に失敗することを保証できます.RoleRequirement
のプロセッサは1つしかないので、これは問題ありません.前述したように、ロール認可の論理(後述するHandler)と特定の認可のデータを分離しています.
RoleHandler
はユーザーにどのような役割があるか分からないため、RoleHandler
はユーザーがどのような役割を持っているかを検証する方法しか知らないが、具体的にユーザーがどのような役割を持っているかは、RoleRequirement
によって決定され、これは注目点の分離と単一の職責という2つのプログラミング概念に合致している.それから、さっき書いた
RoleHandler
をDiに登録します.services.AddSingleton();
最後に、元のAttributeを交換します.
// [Authorize(Roles = "admin,super-admin,")]
[Authorize(Policy ="role-policy")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task Test()
これで、最も基本的なポリシーベースのライセンスが完了します.
本明細書の例は簡単であり、すべてのライセンス特性を使用していないため、より詳細な使用方法の参考資料が多く、本稿ではあまり紹介しません.また、ASPを参考にすることができます.NET Coreでは、ポリシーに基づいたライセンスにより、ポリシーのライセンスに関する内容を学習します.
認証時にAuthenticationSchemeを指定する
AuthenticationSchemeを指定するコードは、次のようになります.
// [Authorize(Roles = "admin,super-admin,")]
[Authorize(AuthenticationSchemes ="jwt"/* , AuthenticationHandler */, Policy ="role-policy")] [HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task Test()
前ブログでASP.NET Core Identity実戦(3)認証の過程で、Authenticationミドルウェアには複数のHandlerを配置することができ、1つはデフォルトでアクティブ化されているが、残りはパッシブ呼び出しであり、現在、Authorize特性の中で1つのHandlerを選択して実行している.例えば、Authenticationミドルウェアに2つのHandler--CookieAuthenticationHandlerとJwtAuthenticationHandlerを配置し、CookieAuthenticationHandlerによってデフォルトとして指定されていますが、Jwt認証を経由する場合はどうすればいいですか?
ここで重要な問題は、HttpContextがAuthenticationミドルウェアを通過した後にMvcミドルウェアに到着し、MvcがActionで指定されたAuthenticationHandlerを確認したときに、Authenticationプロセスが終了したことである.
どうやってやったの?
また、HttpContextには
AuthenticateAsync
という拡張メソッドがあり、HttpContextの拡張メソッドとしては、いつでも認証操作を呼び出すことができることを意味します.namespace Microsoft.AspNetCore.Authentication
{
public static class AuthenticationHttpContextExtensions
{
public static Task AuthenticateAsync(this HttpContext context);
public static Task AuthenticateAsync(this HttpContext context, string scheme);
...
2番目のリロードを見ると、AuthenticationSchemeの名前が指定されているので、MvcミドルウェアがAttributeがAuthenticationSchemeを指定したことを検出すると、指定されたAuthenticationHandlerを再選択して要求を認証します.
ライセンスの発生地-AuthorizationFilter
古いAspでNet時代、私たちはMvcFilterというものを知っています.今も残っています.もしあなたがそれを知らないなら、少し理解することをお勧めします.公式ドキュメントを参照することをお勧めします.
このセクションのタイトルのように、ライセンスは
Microsoft.AspNetCore.Mvc.Authorization.AuthorizationFilter
で発生します.ライセンスのロジックは似ています.先に認証を行います
schemeが指定されている場合は、再認証、ない場合は、前のAuthenticationミドルウェアのライセンス結果を使用します.
public virtual async Task Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator.AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
{
if (policy.AuthenticationSchemes != null && policy.AuthenticationSchemes.Count > 0)
{
ClaimsPrincipal newPrincipal = null;
foreach (var scheme in policy.AuthenticationSchemes)
{
var result = await context.AuthenticateAsync(scheme);
if (result != null && result.Succeeded)
{
newPrincipal = SecurityHelper.MergeUserPrincipal(newPrincipal, result.Principal);
}
}
if (newPrincipal != null)
{
context.User = newPrincipal;
return AuthenticateResult.Success(new AuthenticationTicket(newPrincipal, string.Join(";", policy.AuthenticationSchemes)));
}
else
{
context.User = new ClaimsPrincipal(new ClaimsIdentity());
return AuthenticateResult.NoResult();
}
}
return (context.User?.Identity?.IsAuthenticated ?? false)
? AuthenticateResult.Success(new AuthenticationTicket(context.User, "context.User"))
: AuthenticateResult.NoResult();
}
この中で再び深く検討する価値があるのは
context.AuthenticateAsync(scheme)
で、これはHttpAbstractionsプロジェクトにおける拡張方法であり、その実現は: public static Task AuthenticateAsync(this HttpContext context, string scheme) =>
context.RequestServices.GetRequiredService().AuthenticateAsync(context, scheme);
IAuthenticationService
Authenticationミドルウェアでも見たことがありますが、AuthenticationミドルウェアもIAuthenticationService
を使用しています.前の記事で述べたように、アイデンティティ認証ミドルウェアはパイプでの認証を担当していますが、認証自体はアイデンティティ認証ミドルウェアに縛られているわけではありません.前のブログASP.NET Core Identity実戦(3)認証プロセスの最後に認証されたソースコード再承認
ライセンスは合計3ステップに分かれています
public async Task AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable requirements)
{
//
var authContext = _contextFactory.CreateContext(requirements, user, resource);
var handlers = await _handlers.GetHandlersAsync(authContext);
//
foreach (var handler in handlers)
{
await handler.HandleAsync(authContext);
if (!_options.InvokeHandlersAfterFailure && authContext.HasFailed)
{
break;
}
}
// ( )
var result = _evaluator.Evaluate(authContext);
if (result.Succeeded)
{
_logger.UserAuthorizationSucceeded(GetUserNameForLogging(user));
}
else
{
_logger.UserAuthorizationFailed(GetUserNameForLogging(user));
}
return result;
}
ここで我々がプロジェクトに書いたコードと関係があるのはIAuthorizeHandlerの例であり,本稿では
RoleHandler
を書いた.これで授権プロセスは終わり、授権後にどのように操作するかなどの知識点があります.これらは難しくありません.