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" ] }
>启动配置方法中的中间件顺序很重要. 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最符合我的需求.
为此,我非常仔细地阅读文章,重新阅读,内部化所有的评论,然后站起来一个简单的例子.我现在可以生成一个JWT令牌,但是当我尝试使用授权属性[Authorize(“Bearer”)]来调用我的控制器操作时,我收到以下消息:
The following authentication scheme was not accepted: Bearer
由于我没有看到如何做到这一点的高保真A到Z的例子,请考虑以下步骤来重现:
>在Visual Studio 2015中创建一个新的Web API项目(我正在使用Enterprise),选择“新建项目… Web … ASP.NET Web应用程序”,然后选择“ASP.NET 5”下的“Web API”选项预览模板“
>使用beta 5 SDK,global.json如下所示:
{ "projects": [ "src","sdk": { "version": "1.0.0-beta5","runtime": "clr","architecture": "x86" } }
>引入JWT令牌所需的依赖项,project.json如下所示:
{ "webroot": "wwwroot","dependencies": { "Microsoft.AspNet.Mvc": "6.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","bower_components" ],"publishExclude": [ "node_modules","**.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; } } }
>一些型号:
Credentials.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" ),"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下启动示例应用程序,并使用与JSON主体类似的http:// localhost:22553 / token /
{ "user" : "user","password" : "secret" }
该应用程序使用令牌进行响应:
{ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6bnVsbH0.eyJ1bmlxdWVfbmFtZSI6InNvbWVib2R5Iiwicm9sZSI6WyJhZG1pbiIsInRlYWNoZXIiXSwiaXNzIjoiY29udG9zby5jb20iLCJhdWQiOiJjb250b3NvLmNvbS9yZXNvdXJjZXMiLCJleHAiOjE0Mzk1MzU2MDB9.anRgL10XFG_bKDDxY3D2xQSfhPRLGMjUTreQNsP1jDA6eRKwXHf3jtpCwm_saoWyUDFFA2TMI9e_LbP6F5l7vtozCluziE_GQkPkspUSWuWIpQJLPRTTPPZHGKmPmK4MLEl1zPPrggJWbvF9RBw3mMQ0KoMfjSL0vUQ8kZ7VXAel8dnYJccd-CFdnB6aDe79x2E9Se2iLxdhr--R_qgvfz1Fa6tR1dstqLQ-UjYqPWY4SOgBjM3abtjfLLVEzeQMVyezX7Cx9ObMXAGbGvQL6GB_T5RlfAoXWME4jM8Bzhd-07wwd732bBws4OXivj1sSz-qawNTnXmnuccLRtI1uA","token_type": "bearer" }
>从先前的POST复制令牌,然后在邮递员中创建一个类似于http:// localhost:22553 / api / values的GET请求,注意添加一个授权头,其值为“bearer YOURTOKEN”(例如承载权限为yeetok .)
>请注意,该应用程序响应错误:
System.InvalidOperationException
The following authentication scheme was not accepted: 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
我希望有人可能会了解这个例子发生的故障.