将 JWT 身份验证实现从 .net core 2 转移到 asp.net web api 2
Posted
技术标签:
【中文标题】将 JWT 身份验证实现从 .net core 2 转移到 asp.net web api 2【英文标题】:transfer JWT Authentication implementation from .net core 2 to asp.net web api 2 【发布时间】:2018-06-23 06:48:11 【问题描述】:我在 .net core 2 应用程序中实现了 JWT 身份验证,它工作正常。
我想在 asp.net web api 2 应用程序中使用此实现和结构,但出现错误
我的结构:
JwtTokenBuilder 类:
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
令牌对象:
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);
安全密钥类:
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));
我的令牌控制器方法 generate 并返回 token :
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 启动类来验证我的 token 用于所有具有 Authorize 的控制器strong> 属性。
控制器示例:
namespace solution.Controllers
public class ExampleController : ApiController
[HttpPost]
[Route("api/Example")]
[Authorize(Policy = "Session")]
public void Run()
// do something;
用于验证 JWT 令牌的我的 owin 启动类:
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 web api 中使用这种结构,只改变 owin 类,可以吗? 请帮助我进行任何更改
【问题讨论】:
【参考方案1】:将我的实现从 .net core 2 转移到 asp.net web api 2
的结构更改我使用 System.IdentityModel.Tokens.Jwt
命名空间来生成和验证 JWT 令牌。
.net core 2 与 System.IdentityModel.Tokens.Jwt version="5.1.4"
兼容,但 asp.net web api 2 与 System.IdentityModel.Tokens.Jwt version="4.0.2"
兼容
包版本中的相同更改对代码进行了更改,由于更改包版本,我使用System.IdentityModel.Tokens
命名空间而不是Microsoft.IdentityModel.Tokens
的部分代码。
代码更改:
JwtTokenBuilder 类:
在这个类中更改SigningCredentials
参数设置
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));
安全密钥类:
更改安全密钥生成方式
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));
控制器属性:
namespace solution.Controllers
public class ExampleController : ApiController
[HttpPost]
[Route("api/Example")]
[System.Web.Http.Authorize]
public void Run()
// do something;
我的主要更改是在 Startup OWIN 类中并将 Microsoft.Owin.Security.Jwt
包版本从“3.1.0”更改为“3.0.0”以验证传入请求的 JWT 令牌。
实现:
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
);
【讨论】:
您如何获得IssuerSecurityTokenProviders
?我只有IssuerSecurityKeyProviders
。以上是关于将 JWT 身份验证实现从 .net core 2 转移到 asp.net web api 2的主要内容,如果未能解决你的问题,请参考以下文章