transfer JWT Authentication implementation from .net core 2 to asp.net web api 2
我在.net core 2应用程序中实现了JWT身份验证,它可以正常工作。
我想在asp.net Web api 2应用程序中使用此实现和结构,但出现错误
我的结构:
JwtTokenBuilder类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | using System; using System.Collections.Generic; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Linq; namespace solution.Authentication { public sealed class JwtTokenBuilder { private SecurityKey securityKey = null; private string subject =""; private string issuer =""; private string audience =""; private Dictionary<string, string> claims = new Dictionary<string, string>(); private DateTime expireTime = DateTime.UtcNow.AddMinutes(30); public JwtTokenBuilder AddSecurityKey(SecurityKey securityKey) { this.securityKey = securityKey; return this; } public JwtTokenBuilder AddSubject(string subject) { this.subject = subject; return this; } public JwtTokenBuilder AddIssuer(string issuer) { this.issuer = issuer; return this; } public JwtTokenBuilder AddAudience(string audience) { this.audience = audience; return this; } public JwtTokenBuilder AddClaim(string type, string value) { this.claims.Add(type, value); return this; } public JwtTokenBuilder AddClaims(Dictionary<string, string> claims) { this.claims.Union(claims); return this; } public JwtTokenBuilder AddExpiry(DateTime expireTime) { this.expireTime = expireTime; return this; } public JwtToken Build() { EnsureArguments(); var claims = new List<Claim> { new Claim(JwtRegisteredClaimNames.Sub, this.subject), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) } .Union(this.claims.Select(item => new Claim(item.Key, item.Value))); var token = new JwtSecurityToken( issuer: this.issuer, audience: this.audience, claims: claims, expires: this.expireTime, signingCredentials: new SigningCredentials( this.securityKey, SecurityAlgorithms.HmacSha256)); return new JwtToken(token); } #region" private" private void EnsureArguments() { if (this.securityKey == null) throw new ArgumentNullException("Security Key"); if (string.IsNullOrEmpty(this.subject)) throw new ArgumentNullException("Subject"); if (string.IsNullOrEmpty(this.issuer)) throw new ArgumentNullException("Issuer"); if (string.IsNullOrEmpty(this.audience)) throw new ArgumentNullException("Audience"); } #endregion } } |
令牌对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System; using System.IdentityModel.Tokens.Jwt; namespace solution.Authentication { public sealed class JwtToken { private JwtSecurityToken token; internal JwtToken(JwtSecurityToken token) { this.token = token; } public DateTime ValidTo => token.ValidTo; public string access_token => new JwtSecurityTokenHandler().WriteToken(this.token); } } |
安全密钥类别:
1 2 3 4 5 6 7 8 9 10 11 12 13 | using Microsoft.IdentityModel.Tokens; using System.Text; namespace solution.Authentication { public static class JwtSecurityKey { public static SymmetricSecurityKey Create(string secret) { return new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret)); } } } |
我的令牌控制器方法,用于生成和返回令牌:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | private JwtToken getToken(User user) { DateTime startTime = DateTime.Now; DateTime expireTime = DateTime.Now.AddMinutes(60); var token = new JwtTokenBuilder() .AddSecurityKey(JwtSecurityKey.Create("SecurityKey")) .AddSubject("Subject") .AddIssuer("Issuer") .AddAudience("Audience") .AddClaim("Username", user.UserName) .AddExpiry(expireTime) .Build(); return token; } |
在.net core 2应用程序中,我使用OWIN Startup类来验证具有授权属性的所有控制器的令牌。
控制器示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | namespace solution.Controllers { public class ExampleController : ApiController { [HttpPost] [Route("api/Example")] [Authorize(Policy ="Session")] public void Run() { // do something; } } } |
我的owin启动类,用于验证JWT令牌:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | using System; using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Threading.Tasks; namespace solution { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer ="Issuer", ValidAudience ="Audience", IssuerSigningKey = JwtSecurityKey.Create("SecurityKey") }; options.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { return Task.CompletedTask; }, OnTokenValidated = context => { return Task.CompletedTask; } }; }); services.AddAuthorization(options => { options.AddPolicy("Session", policy => policy.RequireClaim("SessionId")); }); services.AddSignalR(); services.AddCors(options => { options.AddPolicy("CorsPolicy", builder => builder .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials()); }); services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.Use(async (context, next) => { await next(); if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value) && !context.Request.Path.Value.StartsWith("/api/", StringComparison.OrdinalIgnoreCase)) { context.Request.Path ="/index.html"; await next(); } }); app.UseDeveloperExceptionPage(); app.UseAuthentication(); app.UseMvcWithDefaultRoute(); app.UseDefaultFiles(); app.UseStaticFiles(); app.UseCors(policyName:"CorsPolicy"); app.UseSignalR(routes => { }); } } } |
我只想在asp.net网络api中使用此结构更改owin类,这可能吗?
请帮助我进行任何更改
更改结构,以将我的实现从.net核心2转移到asp.net Web API 2
我使用
.net core 2与
兼容
对软件包版本的相同更改也更改了代码,由于更改了软件包版本,我的代码部分也使用了
代码更改:
JwtTokenBuilder类:
在此类更改
1 2 3 4 5 6 7 8 9 | var token = new JwtSecurityToken( issuer: this.issuer, audience: this.audience, claims: claims, expires: this.expireTime, signingCredentials: new System.IdentityModel.Tokens.SigningCredentials( this.securityKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature , Microsoft.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature)); |
安全密钥类别:
更改安全密钥生成方法
1 2 3 4 5 6 7 8 9 10 11 12 13 | using System.IdentityModel.Tokens; using System.Text; namespace solution.Authentication { public static class JwtSecurityKey { public static SymmetricSecurityKey Create(string secret) { return new InMemorySymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)); } } } |
控制器属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 | namespace solution.Controllers { public class ExampleController : ApiController { [HttpPost] [Route("api/Example")] [System.Web.Http.Authorize] public void Run() { // do something; } } } |
我的主要更改是在Startup OWIN类中,将
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | using Microsoft.Owin; using Owin; using System.Web.Http; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Jwt; [assembly: OwinStartup(typeof(solution.Startup))] namespace solution { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); HttpConfiguration config = new HttpConfiguration(); config.MapHttpAttributeRoutes(); ConfigureOAuth(app); app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); app.UseWebApi(config); } public void ConfigureOAuth(IAppBuilder app) { var issuer ="issuer"; var audience ="audience"; var secret = JwtSecurityKey.Create("SecurityKey").GetSymmetricKey(); // Api controllers with an [Authorize] attribute will be validated with JWT var option = new JwtBearerAuthenticationOptions { AuthenticationMode = AuthenticationMode.Active, AllowedAudiences = new[] { audience }, IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[] { new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret) } }; app.UseJwtBearerAuthentication( option ); } } } |