ネットコア2.0アプリと承認の問題があります。特別なrequest.headerおよび標準のデフォルト認証でカスタム認証を使用したい。最初に、startup.csに構成を追加します。
public IServiceProvider ConfigureServices(IServiceCollection services)
{
...
services.AddAuthorization(options =>
{
options.AddPolicy(DefaultAuthorizedPolicy, policy =>
{
policy.Requirements.Add(new TokenAuthRequirement());
});
});
services.AddSingleton<IAuthorizationHandler, AuthTokenPolicy>();
...
}
およびAuthTokenPolicy.cs
public class AuthTokenPolicy : AuthorizationHandler<TokenAuthRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TokenAuthRequirement requirement)
{
var filterContext = context.Resource as AuthorizationFilterContext;
var response = filterContext.HttpContext.Response;
try
{
// some validation code
var isValidToken = isValidTokenTask.Result;
if (!isValidToken)
{
response.StatusCode = 401;
return Task.CompletedTask;
}
response.StatusCode = 200;
context.Succeed(requirement);
}
catch (Exception)
{
return Task.CompletedTask;
}
return Task.CompletedTask;
}
}
およびHomeController.cs内
[Authorize(Policy = Startup.DefaultAuthorizedPolicy)]
public async Task<IActionResult> IsVisible()
AuthTokenPolicyで間違ったrequest.headerを使用すると、表示されます。しかし、ログにはエラーが表示されます:
System.InvalidOperationException:no authenticationSchemeが指定されておらず、DefaultChallengeSchemeが見つかりませんでした。\ r\n Microsoft.AspNetCore.Authentication.AuthenticationService.d__11.MoveNext()\ r\n ---例外の前の場所からのスタックトレースの終了スローされました---\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r\n System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ r\n at Microsoft.AspNetCore.Mvc。 ChallengeResult.d__14.MoveNext()\ r\n ---例外がスローされた以前の場所からのスタックトレースの終了---\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r\n System .Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__19.MoveNext()\ r\n ---例外がスローされた前の場所からのスタックトレースの終了---\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r\na t System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()\ r\n ---例外の前の場所からのスタックトレースの終了スローされました---\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r\n System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ r\n at Microsoft.AspNetCore.Mvc。 Internal.ResourceInvoker.d__15.MoveNext()\ r\n ---例外がスローされた前の場所からのスタックトレースの終わり---\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r\n System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ r\n at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()\ r\n ---例外がスローされた前の場所からのスタックトレースの終了---\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r\n at System.Runtime.CompilerSe rvices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ r\n at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.d__3.MoveNext()\ r\n ---例外がスローされた前の場所からのスタックトレースの終了---\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r\n System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ r\n React.AspNet.BabelFileMiddleware.d__5.MoveNext()\ r\n ---例外がスローされた前の場所からのスタックトレースの終わり---\r\n System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\ r\n System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(タスクタスク)\ r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()\ r\n ---例外がスローされた以前の場所からのスタックトレースの終了---\r\n System.Runtime .ExceptionServices.ExceptionDispatchInfo.Throw()\ r\n System.Runtime.CompilerServices.TaskAwaiter.HanでdleNonSuccessAndDebuggerNotification(Task task)\ r\n core.common.Middleware.LoggingMiddleware.d__3.MoveNext()at D:\ Dev\microservicePDP\Template\core.common\Middleware\LoggingMiddleware.cs:line 72
認証とIDのASP.NET Core 2.0への移行 を読んだ後、startup.csにこのコードを追加しました
記事からの引用:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
次の条件のいずれかに該当する場合、2.0でデフォルトのスキームを定義します。ユーザーに自動的にサインインさせたい
ConfigureServicesにAuthenticationSchemeとDefaultChallengeSchemeを追加しました。助けにはなりませんでした。同じエラーです。 app.UseAuthentication()を使用してみました。 StartUp.csのConfigureで、結果はありません。誰かが認証なしでカスタム認証を使用する方法を説明できますか?
オーケー。正解は、認証の代わりに承認を使用しないことです。ヘッダーを使用してすべてのクライアントにサービスを提供するための完全なアクセス権を取得する必要があります。作業コードは次のとおりです。
public class TokenAuthenticationHandler : AuthenticationHandler<TokenAuthenticationOptions>
{
public IServiceProvider ServiceProvider { get; set; }
public TokenAuthenticationHandler (IOptionsMonitor<TokenAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IServiceProvider serviceProvider)
: base (options, logger, encoder, clock)
{
ServiceProvider = serviceProvider;
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync ()
{
var headers = Request.Headers;
var token = "X-Auth-Token".GetHeaderOrCookieValue (Request);
if (string.IsNullOrEmpty (token)) {
return Task.FromResult (AuthenticateResult.Fail ("Token is null"));
}
bool isValidToken = false; // check token here
if (!isValidToken) {
return Task.FromResult (AuthenticateResult.Fail ($"Balancer not authorize token : for token={token}"));
}
var claims = new [] { new Claim ("token", token) };
var identity = new ClaimsIdentity (claims, nameof (TokenAuthenticationHandler));
var ticket = new AuthenticationTicket (new ClaimsPrincipal (identity), this.Scheme.Name);
return Task.FromResult (AuthenticateResult.Success (ticket));
}
}
Startup.cs:
#region Authentication
services.AddAuthentication (o => {
o.DefaultScheme = SchemesNamesConst.TokenAuthenticationDefaultScheme;
})
.AddScheme<TokenAuthenticationOptions, TokenAuthenticationHandler> (SchemesNamesConst.TokenAuthenticationDefaultScheme, o => { });
#endregion
そして、mycontroller.cs
[Authorize(AuthenticationSchemes = SchemesNamesConst.TokenAuthenticationDefaultScheme)]
public class MainController : BaseController
{ ...}
TokenAuthenticationOptionsが見つかりませんが、空でした。同じクラスPhoneNumberAuthenticationOptionsが見つかりました:
namespace Project.Auth{
public class PhoneNumberAuthenticationOptions : AuthenticationSchemeOptions
{
public Regex PhoneMask { get; set; }// = new Regex("7\\d{10}");
}}
次のような静的クラスSchemesNamesConstを定義する必要があります。
namespace Common.Const{
public static class SchemesNamesConst
{
public const string SchemesNamesConst= "TokenAuthenticationScheme";
}}
これは私のために働いた
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
options =>
{
options.LoginPath = new PathString("/auth/login");
options.AccessDeniedPath = new PathString("/auth/denied");
});
デフォルトの認証スキームを設定する前にポリシーを使用した場合も同様です。 DefaultPolicy
を変更したため、少し異なりました。ただし、ポリシーを追加する場合も同様に機能するはずです。
services.AddAuthorization(options =>
{
options.AddPolicy(DefaultAuthorizedPolicy, policy =>
{
policy.Requirements.Add(new TokenAuthRequirement());
policy.AuthenticationSchemes = new List<string>()
{
CookieAuthenticationDefaults.AuthenticationScheme
}
});
});
デフォルトでは、AuthenticationSchemes
プロパティが読み取り専用リストを使用することを考慮してください。リストの代わりにそれを実装する方が良いと思います。
Asp.Netコアプロジェクトを使用してVisual Studioでこれを実行しているときに、アプリケーションが突然以下のようなエラーメッセージで開始されない場合は、「ブラウザーリンクを有効にする」のチェックを外してください。
エラー:
Conversion> [13:31:10 ERR] Connection id "0HLJ153E20LDJ", Request id "0HLJ153E20LDJ:00000003": An unhandled exception was thrown by the application.
Conversion> System.ObjectDisposedException: The response has been aborted due to an unhandled application exception. ---> System.FormatException: Invalid ETag name
Conversion> at Microsoft.Net.Http.Headers.EntityTagHeaderValue..ctor(StringSegment tag, Boolean isWeak)
Conversion> at Microsoft.Net.Http.Headers.EntityTagHeaderValue..ctor(StringSegment tag)
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleWareUtil.AddToETag(ResponseHeaders responseHeader, Int32 port)
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware.<>c__DisplayClass7_0.<ExecuteWithFilter>b__0()
Conversion> at Microsoft.AspNetCore.Http.HttpResponse.<>c.<.cctor>b__30_0(Object callback)
Conversion> at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.FireOnStartingMayAwait(Stack`1 onStarting)
Conversion> --- End of inner exception stack trace ---
Conversion> at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAbortedException()
Conversion> at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.InitializeResponseAsync(Int32 firstWriteByteCount)
Conversion> at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.WriteAsync(ReadOnlyMemory`1 data, CancellationToken cancellationToken)
Conversion> at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
Conversion> at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count)
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.ScriptInjectionFilterStream.<>c__DisplayClass37_0.<<CreateResponseHandler>b__0>d.MoveNext()
Conversion> --- End of stack trace from previous location where exception was thrown ---
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.SocketReader.ReadBytesIntoResponseHandler(Int64 totalBytesToRead, ResponseHandler handler, CancellationToken cancellationToken)
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.HttpSocketAdapter.ResponseReader.ReadBytesIntoResponse(Int64 bytesToRead)
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.HttpSocketAdapter.ResponseReader.ReadChunkedContent()
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.HttpSocketAdapter.ResponseReader.ReadResponse()
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.DelayConnectingHttpSocketAdapter.Microsoft.VisualStudio.Web.BrowserLink.IHttpSocketAdapter.WaitForResponseComplete()
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.ScriptInjectionFilterStream.WaitForFilterComplete()
Conversion> at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware.ExecuteWithFilter(IHttpSocketAdapter injectScriptSocket, String requestId, HttpContext httpContext)
Conversion> at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Conversion> at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Conversion> at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext)
Conversion> at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
マークされたソリューションの最初の声明は完全に真実ではありません。新しいソリューションは元の目標を達成する可能性がありますが、AuthorizationHandlerロジックを保持しながら元のエラーを回避することも可能です-provided基本認証スキームがあります機能的にスケルトンであっても、適切なハンドラー。
大まかに言えば、認証ハンドラーとスキームはIDを確立+検証することを意図しており、認証ハンドラー/ポリシーが機能するために必要になります-IDが既に確立されていると仮定して実行されるためです。
ASP.NET Dev Haokは、この最高のベストをここに要約します。承認のための有効なクレームプリンシパルを構築するために使用されるスキームにポリシーを関連付けるために(または、DefaultAuthenticateSchemeに依存する要求に対してデフォルトのhttpContext.Userを使用するだけです)。 https://github.com/aspnet/Security/issues/1469
私の場合、私が取り組んでいるソリューションは独自の暗黙的なIDの概念を提供していたため、認証スキーム/ハンドラーは不要で、承認用のヘッダートークンだけでした。したがって、IDの概念が変更されるまで、ポリシーを実施するヘッダートークン認証ハンドラーを1対1スキームのスケルトンに結び付けることができます。
エンドポイントのタグ:
[Authorize(AuthenticationSchemes = "AuthenticatedUserSchemeName", Policy = "AuthorizedUserPolicyName")]
Startup.cs:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "AuthenticatedUserSchemeName";
}).AddScheme<ValidTokenAuthenticationSchemeOptions, ValidTokenAuthenticationHandler>("AuthenticatedUserSchemeName", _ => { });
services.AddAuthorization(options =>
{
options.AddPolicy("AuthorizedUserPolicyName", policy =>
{
//policy.RequireClaim(ClaimTypes.Sid,"authToken");
policy.AddAuthenticationSchemes("AuthenticatedUserSchemeName");
policy.AddRequirements(new ValidTokenAuthorizationRequirement());
});
services.AddSingleton<IAuthorizationHandler, ValidTokenAuthorizationHandler>();
空の認証ハンドラーと認可ハンドラーの両方が呼び出されます(OPのそれぞれのポストへのセットアップと同様)が、認可ハンドラーは引き続き認可ポリシーを実施します。