ASP.NET 5 OAuthBearerAuthentication:不接受以下身份验证方案:Bearer
Posted
技术标签:
【中文标题】ASP.NET 5 OAuthBearerAuthentication:不接受以下身份验证方案:Bearer【英文标题】:ASP.NET 5 OAuthBearerAuthentication: The following authentication scheme was not accepted: Bearer 【发布时间】:2015-11-07 00:01:13 【问题描述】:更新:
Pinpoint 帮助我将这个原型从发射台上取下来 - 我非常接近,除了:
我需要按照these instructions 升级到 beta6 SDK。 Global.json 现在显示如下:
"projects": [ "src", "test" ],
"sdk":
"version": "1.0.0-beta6"
我更新了 project.json 中的引用:
"webroot": "wwwroot",
"version": "1.0.0-*",
"dependencies":
"Microsoft.AspNet.Mvc": "6.0.0-beta6",
"Microsoft.AspNet.Server.IIS": "1.0.0-beta6",
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta6",
"Microsoft.AspNet.StaticFiles": "1.0.0-beta6",
"System.IdentityModel.Tokens": "5.0.0-beta6-207211625",
"Serilog.Framework.Logging": "1.0.0-beta-43",
"Microsoft.AspNet.Authentication.OAuthBearer": "1.0.0-beta6"
,
"commands":
"web": "Microsoft.AspNet.Hosting --config hosting.ini"
,
"frameworks":
"dnx451":
,
"exclude": [
"wwwroot",
"node_modules",
"bower_components"
],
"publishExclude": [
"node_modules",
"bower_components",
"**.xproj",
"**.user",
"**.vspscc"
]
启动的 Configure 方法中的中间件顺序很重要。 UseOAuthBearerAuthentication 需要在 UseMvc 之前。 Startup.cs 中的 Configure 方法现在如下所示:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
app.UseOAuthBearerAuthentication();
app.UseMvc();
我正在使用 ASP.NET 5 并尝试实现一个非常简单的概念证明来生成和使用 JWT 令牌。我已阅读文章here、here 和here,但this one 最符合我的需求。
为此,我非常认真的阅读了这篇文章,重读了一遍,内化了所有的cmets,然后站出了一个简单的例子。我现在可以生成 JWT 令牌,但是当我尝试调用已使用授权属性 [Authorize("Bearer")] 修饰的控制器操作时,我收到以下消息:
不接受以下身份验证方案:Bearer
由于我没有看到有关如何执行此操作的高保真 A 到 Z 示例,请考虑以下步骤来重现:
在 Visual Studio 2015(我使用的是 Enterprise)中创建一个新的 Web API 项目,方法是选择“新建项目...Web...ASP.NET Web 应用程序”,然后选择“ASP.NET”下的“Web API”选项。 NET 5 预览模板” 使用 beta 5 SDK,global.json 如下所示:
"projects": [ "src", "test" ],
"sdk":
"version": "1.0.0-beta5",
"runtime": "clr",
"architecture": "x86"
引入 JWT 令牌所需的依赖项,project.json 如下所示:
"webroot": "wwwroot",
"version": "1.0.0-*",
"dependencies":
"Microsoft.AspNet.Mvc": "6.0.0-beta6",
"Microsoft.AspNet.Server.IIS": "1.0.0-beta6",
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta6",
"System.IdentityModel.Tokens": "5.0.0-beta5-206011020",
"Microsoft.AspNet.Authentication.OAuthBearer": "1.0.0-beta5"
,
"commands":
"web": "Microsoft.AspNet.Hosting --config hosting.ini"
,
"frameworks":
"dnx451":
,
"exclude": [
"wwwroot",
"node_modules",
"bower_components"
],
"publishExclude": [
"node_modules",
"bower_components",
"**.xproj",
"**.user",
"**.vspscc"
]
Startup.cs(这是一个示例不用于生产)
public class Startup
const string _TokenIssuer = "contoso.com" ;
const string _TokenAudience = "contoso.com/resources" ;
RsaSecurityKey _key = null ;
SigningCredentials _signingCredentials = null ;
public Startup(IHostingEnvironment env)
GenerateRsaKeys();
public void ConfigureServices(IServiceCollection services)
services.AddInstance(_signingCredentials);
services.ConfigureOAuthBearerAuthentication
(
options =>
options.AutomaticAuthentication = true;
options.TokenValidationParameters.IssuerSigningKey = _key ;
options.TokenValidationParameters.ValidAudience = _TokenAudience;
options.TokenValidationParameters.ValidIssuer = _TokenIssuer ;
);
services.ConfigureAuthorization
(
options =>
options.
AddPolicy
(
"Bearer",
new AuthorizationPolicyBuilder().
AddAuthenticationSchemes(OAuthBearerAuthenticationDefaults.AuthenticationScheme).
RequireAuthenticatedUser().
Build()
);
);
services.AddMvc();
public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerfactory)
app.UseMvc();
app.UseOAuthBearerAuthentication();
void GenerateRsaKeys()
using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
_key = new RsaSecurityKey(rsa.ExportParameters(true));
_signingCredentials =
new SigningCredentials
(
_key ,
SecurityAlgorithms.RsaSha256Signature ,
SecurityAlgorithms.Sha256Digest ,
"secret"
);
rsa.PersistKeyInCsp = false;
部分型号:
凭据.cs
public class Credentials
public string user set;get;
public string password set;get;
JwtToken.cs
public class JwtToken
public string access_token set; get;
public string token_type set; get;
用于获取令牌的令牌控制器(这是一个不用于生产的示例),TokenController.cs:
[ Route("[controller]") ]
public class TokenController : Controller
private readonly OAuthBearerAuthenticationOptions _bearerOptions ;
private readonly SigningCredentials _signingCredentials ;
public TokenController
(
IOptions<OAuthBearerAuthenticationOptions> bearerOptions ,
SigningCredentials signingCredentials
)
_bearerOptions = bearerOptions.Options ;
_signingCredentials = signingCredentials ;
// POST: /token
[HttpPost()]
public JwtToken Token([FromBody] Credentials credentials)
// Pretend to validate credentials...
JwtSecurityTokenHandler handler =
_bearerOptions .
SecurityTokenValidators .
OfType<JwtSecurityTokenHandler>() .
First();
JwtSecurityToken securityToken =
handler .
CreateToken
(
issuer : _bearerOptions.TokenValidationParameters.ValidIssuer ,
audience : _bearerOptions.TokenValidationParameters.ValidAudience,
signingCredentials : _signingCredentials ,
subject : new ClaimsIdentity
(
new Claim []
new Claim(ClaimTypes.Name,"somebody"),
new Claim(ClaimTypes.Role,"admin" ),
new Claim(ClaimTypes.Role,"teacher" ),
) ,
expires : DateTime.Today.AddDays(1)
);
string token = handler.WriteToken(securityToken);
return new JwtToken()
access_token = token ,
token_type = "bearer"
;
用于演示提取令牌的值控制器,ValuesController.cs:
[Route("api/[controller]")]
public class ValuesController : Controller
// GET: api/values
[Authorize("Bearer")]
[HttpGet]
public IEnumerable<string> Get()
return new string[] "value1", "value2" ;
// GET api/values/5
[HttpGet("id")]
public string Get(int id)
return "value";
启动postman(或您最喜欢的 REST 客户端)的副本,在 Visual Studio 下启动示例应用程序并发出 POST 请求,类似于 http://localhost:22553/token / 带有 JSON 正文:
"user" : "user",
"password" : "secret"
应用以令牌响应:
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6bnVsbH0.eyJ1bmlxdWVfbmFtZSI6InNvbWVib2R5Iiwicm9sZSI6WyJhZG1pbiIsInRlYWNoZXIiXSwiaXNzIjoiY29udG9zby5jb20iLCJhdWQiOiJjb250b3NvLmNvbS9yZXNvdXJjZXMiLCJleHAiOjE0Mzk1MzU2MDB9.anRgL10XFG_bKDDxY3D2xQSfhPRLGMjUTreQNsP1jDA6eRKwXHf3jtpCwm_saoWyUDFFA2TMI9e_LbP6F5l7vtozCluziE_GQkPkspUSWuWIpQJLPRTTPPZHGKmPmK4MLEl1zPPrggJWbvF9RBw3mMQ0KoMfjSL0vUQ8kZ7VXAel8dnYJccd-CFdnB6aDe79x2E9Se2iLxdhr--R_qgvfz1Fa6tR1dstqLQ-UjYqPWY4SOgBjM3abtjfLLVEzeQMVyezX7Cx9ObMXAGbGvQL6GB_T5RlfAoXWME4jM8Bzhd-07wwd732bBws4OXivj1sSz-qawNTnXmnuccLRtI1uA",
"token_type": "bearer"
从上一个 POST 中复制令牌,然后在 postman 中发出 类似 到 http://localhost:22553/api/values 的 GET 请求,注意添加一个 Authorization 标头值“承载 YOURTOKEN”(例如承载 eyJ0eXAiOiJKV1QiLCJ...)
观察应用程序响应错误:
System.InvalidOperationException 不接受以下身份验证方案:Bearer
堆栈跟踪如下:
at Microsoft.AspNet.Http.Authentication.Internal.DefaultAuthenticationManager.< AuthenticateAsync> d__9.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Http.Authentication.AuthenticationManager.< AuthenticateAsync> d__2.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter< TResult> .GetResult()
at Microsoft.AspNet.Mvc.AuthorizeFilter.< OnAuthorizationAsync> d__5.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Mvc.Core.FilterActionInvoker.< InvokeAuthorizationFilterAsync> d__43.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Mvc.Core.FilterActionInvoker.< InvokeAllAuthorizationFiltersAsync> d__42.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Mvc.Core.FilterActionInvoker.< InvokeAsync> d__40.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Mvc.MvcRouteHandler.< InvokeActionAsync> d__4.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Mvc.MvcRouteHandler.< RouteAsync> d__3.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Mvc.Routing.InnerAttributeRoute.< RouteAsync> d__10.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Routing.RouteCollection.< RouteAsync> d__9.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Builder.RouterMiddleware.< Invoke> d__4.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Hosting.Internal.RequestServicesContainerMiddleware.< Invoke> d__3.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Hosting.Internal.HostingEngine.< > c__DisplayClass29_0.< < Start> b__0> d.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Loader.IIS.RuntimeHttpApplication.< ProcessRequestAsyncImpl> d__10.MoveNext()
--- exception rethrown ---
at Microsoft.AspNet.Loader.IIS.RuntimeHttpApplication.< ProcessRequestAsyncImpl> d__10.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNet.Loader.IIS.HttpApplicationBase.< InvokeProcessRequestAsyncImpl> d__9.MoveNext()
请注意,添加日志记录几乎不会增加额外的洞察力,如以下日志所示:
2015-08-13 13:32:35.969 -07:00 [Information] Request successfully matched the route with name 'null' and template '"api/Values"'.
Exception thrown: 'System.InvalidOperationException' in Microsoft.AspNet.Http.dll
2015-08-13 13:32:36.247 -07:00 [Error] An error occurred while handling the request.
2015-08-13 13:32:36.247 -07:00 System.InvalidOperationException: The following authentication scheme was not accepted: Bearer
我希望有人能理解这个例子中的故障发生在哪里。
【问题讨论】:
【参考方案1】:您必须在MVC之前注册OAuth2承载认证中间件,否则您的用户在到达MVC时将无法认证:
public class Startup
public void Configure(IApplicationBuilder app)
app.UseJwtBearerAuthentication(new JwtBearerOptions
// Your JWT bearer options.
);
app.UseMvc();
【讨论】:
非常感谢您的观察。我以前尝试过这种方法,但假设我犯了一个错误,因为当我尝试调用我的任何控制器方法时收到以下错误:[错误] 处理请求时发生错误。 System.TypeLoadException:来自程序集“Microsoft.AspNet.Authentication.OAuthBearer,版本=1.0.0.0,文化=中性,PublicKeyToken=null”的“Microsoft.AspNet.Authentication.OAuthBearer.OAuthBearerAuthenticationHandler”类型中的方法“ChallengeAsync”没有实施。 此错误可能是由于您在同一应用程序中引用了 beta5 和 beta6 包。确保将所有内容迁移到 beta6(甚至是 DNX 运行时),它应该可以工作。 谢谢,Pinpoint - 这就是确切的答案。我按照 this article 升级了我的 Visual Studio 工具,现在我可以生成和摄取 JWT 令牌。我将编辑原始帖子以反映这些更改。 @Pinpoint,这对你适用于 beta8 吗?对于 beta8,我得到状态 500 和异常 'System.MissingMethodException: Method not found: '!!0 Microsoft.AspNet.Http.HttpContext.GetFeature()'.'。知道如何解决这个问题吗? @AntonS 确保您的 beta8 软件包都具有相同的夜间版本。已向 aspnet/HttpAbstractions 添加大量重大更改。以上是关于ASP.NET 5 OAuthBearerAuthentication:不接受以下身份验证方案:Bearer的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core 托管捆绑包 5 是不是也可以运行 .NET/ASP.NET Core 2.1 应用程序?