没有指定authenticationScheme,也没有找到默认认证和自定义授权的DefaultChallengeScheme
No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization
我有一个 .NET Core 2.0 应用程序,但遇到授权问题。我想对特殊请求使用自定义授权。 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 was specified, and there was no DefaultChallengeScheme found.\r\n at Microsoft.AspNetCore.Authentication.AuthenticationService.d__11.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.ChallengeResult.d__14.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__19.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at React.AspNet.BabelFileMiddleware.d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at core.common.Middleware.LoggingMiddleware.d__3.MoveNext() in D:\Dev\microservicePDP\Template\core.common\Middleware\LoggingMiddleware.cs:line 72
阅读 Migrating Authentication and Identity to ASP.NET Core 2.0 后,我在 startup.cs
中添加了这段代码
文章引述:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
Define a default scheme in 2.0 if one of the following conditions is true:
You want the user to be automatically signed in
You use the [Authorize] attribute or authorization policies without specifying schemes
我在ConfigureServices()
中添加了AuthenticationScheme
和DefaultChallengeScheme
。它没有帮助,这里有同样的错误。我尝试在 Startup.Configure()
方法中使用 app.UseAuthentication();
,但没有结果。
如何在没有身份验证的情况下使用自定义授权?
当我在设置默认身份验证方案之前使用策略时。我修改了 DefaultPolicy
所以它略有不同。然而,同样适用于添加策略。
services.AddAuthorization(options =>
{
options.AddPolicy(DefaultAuthorizedPolicy, policy =>
{
policy.Requirements.Add(new TokenAuthRequirement());
policy.AuthenticationSchemes = new List<string>()
{
CookieAuthenticationDefaults.AuthenticationScheme
}
});
});
请注意默认情况下 AuthenticationSchemes
属性 使用只读列表。我认为实现它而不是 List 会更好。
不要使用授权代替身份验证。我应该获得使用 header.
为所有客户提供服务的全部权限
工作代码是:
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,但它是空的。我发现相同的 class PhoneNumberAuthenticationOptions:
public class PhoneNumberAuthenticationOptions : AuthenticationSchemeOptions
{
public Regex PhoneMask { get; set; }// = new Regex("7\d{10}");
}
您应该定义静态 class SchemesNamesConst
。类似于:
public static class SchemesNamesConst
{
public const string TokenAuthenticationDefaultScheme = "TokenAuthenticationScheme";
}
您在标记的解决方案中的初始陈述不完全正确。虽然您的新解决方案可能会实现您最初的目标,但仍然可以在保留您的 AuthorizationHandler 逻辑的同时规避最初的错误——前提是您有基本的身份验证方案处理程序,即使它们是功能性骨骼。
从广义上讲,身份验证处理程序和方案旨在建立 + 验证身份,这使得授权 Handlers/policies 需要它们才能发挥作用——因为它们 运行 假设身份已经存在已成立。
ASP.NET Dev Haok 在这里总结得最好:"Authentication today isn't aware of authorization at all, it only cares about producing a ClaimsPrincipal per scheme. Authorization has to be aware of authentication somewhat, so AuthenticationSchemes in the policy is a mechanism for you to associate the policy with schemes used to build the effective claims principal for authorization (or it just uses the default httpContext.User for the request, which does rely on DefaultAuthenticateScheme)."
https://github.com/aspnet/Security/issues/1469
在我的例子中,我正在研究的解决方案提供了它自己隐含的身份概念,因此我们不需要身份验证 schemes/handlers--just header 令牌来进行授权。因此,在我们的身份概念发生变化之前,我们执行策略的 header 令牌授权处理程序可以绑定到 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 各自帖子的设置),但授权处理程序仍然执行我们的授权策略。
这对我有用
// 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");
});
上面的许多答案都是正确的,但同时与 authN/authZ 的其他方面混淆了。 实际上 解决了有问题的异常是这一行:
services.AddScheme<YourAuthenticationOptions, YourAuthenticationHandler>(YourAuthenticationSchemeName, options =>
{
options.YourProperty = yourValue;
})
我有一个 .NET Core 2.0 应用程序,但遇到授权问题。我想对特殊请求使用自定义授权。 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 was specified, and there was no DefaultChallengeScheme found.\r\n at Microsoft.AspNetCore.Authentication.AuthenticationService.d__11.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.ChallengeResult.d__14.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__19.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at React.AspNet.BabelFileMiddleware.d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at core.common.Middleware.LoggingMiddleware.d__3.MoveNext() in D:\Dev\microservicePDP\Template\core.common\Middleware\LoggingMiddleware.cs:line 72
阅读 Migrating Authentication and Identity to ASP.NET Core 2.0 后,我在 startup.cs
中添加了这段代码文章引述:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
Define a default scheme in 2.0 if one of the following conditions is true: You want the user to be automatically signed in You use the [Authorize] attribute or authorization policies without specifying schemes
我在ConfigureServices()
中添加了AuthenticationScheme
和DefaultChallengeScheme
。它没有帮助,这里有同样的错误。我尝试在 Startup.Configure()
方法中使用 app.UseAuthentication();
,但没有结果。
如何在没有身份验证的情况下使用自定义授权?
当我在设置默认身份验证方案之前使用策略时。我修改了 DefaultPolicy
所以它略有不同。然而,同样适用于添加策略。
services.AddAuthorization(options =>
{
options.AddPolicy(DefaultAuthorizedPolicy, policy =>
{
policy.Requirements.Add(new TokenAuthRequirement());
policy.AuthenticationSchemes = new List<string>()
{
CookieAuthenticationDefaults.AuthenticationScheme
}
});
});
请注意默认情况下 AuthenticationSchemes
属性 使用只读列表。我认为实现它而不是 List 会更好。
不要使用授权代替身份验证。我应该获得使用 header.
为所有客户提供服务的全部权限工作代码是:
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,但它是空的。我发现相同的 class PhoneNumberAuthenticationOptions:
public class PhoneNumberAuthenticationOptions : AuthenticationSchemeOptions
{
public Regex PhoneMask { get; set; }// = new Regex("7\d{10}");
}
您应该定义静态 class SchemesNamesConst
。类似于:
public static class SchemesNamesConst
{
public const string TokenAuthenticationDefaultScheme = "TokenAuthenticationScheme";
}
您在标记的解决方案中的初始陈述不完全正确。虽然您的新解决方案可能会实现您最初的目标,但仍然可以在保留您的 AuthorizationHandler 逻辑的同时规避最初的错误——前提是您有基本的身份验证方案处理程序,即使它们是功能性骨骼。
从广义上讲,身份验证处理程序和方案旨在建立 + 验证身份,这使得授权 Handlers/policies 需要它们才能发挥作用——因为它们 运行 假设身份已经存在已成立。
ASP.NET Dev Haok 在这里总结得最好:"Authentication today isn't aware of authorization at all, it only cares about producing a ClaimsPrincipal per scheme. Authorization has to be aware of authentication somewhat, so AuthenticationSchemes in the policy is a mechanism for you to associate the policy with schemes used to build the effective claims principal for authorization (or it just uses the default httpContext.User for the request, which does rely on DefaultAuthenticateScheme)." https://github.com/aspnet/Security/issues/1469
在我的例子中,我正在研究的解决方案提供了它自己隐含的身份概念,因此我们不需要身份验证 schemes/handlers--just header 令牌来进行授权。因此,在我们的身份概念发生变化之前,我们执行策略的 header 令牌授权处理程序可以绑定到 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 各自帖子的设置),但授权处理程序仍然执行我们的授权策略。
这对我有用
// 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");
});
上面的许多答案都是正确的,但同时与 authN/authZ 的其他方面混淆了。 实际上 解决了有问题的异常是这一行:
services.AddScheme<YourAuthenticationOptions, YourAuthenticationHandler>(YourAuthenticationSchemeName, options =>
{
options.YourProperty = yourValue;
})