我有一个 .NET Core 2.0 应用程序并且有授权问题。我想对特殊要求使用自定义授权。标头和标准默认身份验证。首先,我在 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: 未指定 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 在 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 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__19.MoveNext()\r\n--- 堆栈跟踪从先前引发异常的位置结束---\r\n 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n t System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n 在 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 在 Microsoft.AspNetCore.Mvc。 Internal.ResourceInvoker.d__15.MoveNext()\r\n--- 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 处从先前引发异常的位置结束堆栈跟踪 ---\r\n\r\n在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n 在 Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()\r\n--- 堆栈跟踪从先前抛出异常的位置结束---\r\n 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n 在 System.Runtime.CompilerSe rvices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n 在 Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.d__3.MoveNext()\r\n--- 堆栈跟踪从上一个引发异常的位置结束 ---\r \n 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\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 在 Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()\r\n--- 从先前引发异常的位置结束堆栈跟踪 ---\r\n 在 System.Runtime .ExceptionServices.ExceptionDispatchInfo.Throw()\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.Han D:\Dev\microservicePDP\Template\core.common\Middleware\LoggingMiddleware.cs:line 72 中的 core.common.Middleware.LoggingMiddleware.d__3.MoveNext() 中的 dleNonSuccessAndDebuggerNotification(任务任务)\r\n
阅读 Migrating Authentication and Identity to ASP.NET Core 2.0 后,我在 startup.cs 中添加了此代码
文章引述:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
如果以下条件之一为真,则在 2.0 中定义默认方案: 您希望用户自动登录 您使用 [Authorize] 属性或授权策略而不指定方案
我在 ConfigureServices()
中添加了 AuthenticationScheme
和 DefaultChallengeScheme
。它没有帮助,这里同样的错误。我尝试在 Startup.Configure()
方法中使用 app.UseAuthentication();
,但没有结果。
如何在没有身份验证的情况下使用自定义授权?
AddAuthentication
之后,您又使用了 [Authorize(Policy = Startup.DefaultAuthorizedPolicy)]
?
DefaultChallengeScheme
仅设置为默认授权策略....无论哪种方式尝试我的答案
不要使用授权代替身份验证。我应该完全可以使用标头为所有客户提供服务。
工作代码是:
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));
}
}
启动.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:
public class PhoneNumberAuthenticationOptions : AuthenticationSchemeOptions
{
public Regex PhoneMask { get; set; }// = new Regex("7\\d{10}");
}
您应该定义静态类 SchemesNamesConst
。就像是:
public static class SchemesNamesConst
{
public const string TokenAuthenticationDefaultScheme = "TokenAuthenticationScheme";
}
这对我有用
// using Microsoft.AspNetCore.Authentication.Cookies;
// using Microsoft.AspNetCore.Http;
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
属性使用只读列表。我认为最好实现它而不是 List 。
AddAuthentication().AddCookie()
.AddJTW()
。
您在标记解决方案中的初始陈述并不完全正确。尽管您的新解决方案可能会实现您的原始目标,但仍然可以在保留 AuthorizationHandler 逻辑的同时规避原始错误——前提是您有基本的身份验证方案处理程序,即使它们在功能上是骨架。
广义地说,身份验证处理程序和方案旨在建立+验证身份,这使得授权处理程序/策略需要它们才能运行——因为它们在假设已经建立身份的情况下运行。
ASP.NET Dev Haok 在这里最好地总结了这一点:“今天的身份验证根本不知道授权,它只关心为每个方案生成一个 ClaimsPrincipal。授权必须在一定程度上了解身份验证,因此策略中的 AuthenticationSchemes 是一种机制让您将策略与用于构建有效声明主体以进行授权的方案相关联(或者它只使用默认的 httpContext.User 请求,这确实依赖于 DefaultAuthenticateScheme)。” https://github.com/aspnet/Security/issues/1469
就我而言,我正在研究的解决方案提供了它自己隐含的身份概念,因此我们不需要身份验证方案/处理程序——只需用于授权的标头令牌。因此,在我们的身份概念发生变化之前,我们执行策略的标头令牌授权处理程序可以绑定到一对一的方案骨架。
端点上的标签:
[Authorize(AuthenticationSchemes = "AuthenticatedUserSchemeName", Policy = "AuthorizedUserPolicyName")]
启动.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 各自帖子的设置),但授权处理程序仍然强制执行我们的授权策略。
ValidTokenAuthenticationSchemeOptions
、ValidTokenAuthenticationHandler
、ValidTokenAuthorizationRequirement
?它不是 Microsoft.AspNetCore.Authorization
的一部分,我无法在 Google 上轻松找到它。
上面的许多答案都是正确的,但同时与 authN/authZ 的其他方面令人费解。真正解决有问题的异常是这一行:
services.AddScheme<YourAuthenticationOptions, YourAuthenticationHandler>(YourAuthenticationSchemeName, options =>
{
options.YourProperty = yourValue;
})
不定期副业成功案例分享