問題描述
我在 .net core 2 應(yīng)用程序中實現(xiàn)了 JWT 身份驗證,它工作正常.
i have implementation of JWT Authentication in .net core 2 application, it work fine.
我想在 asp.net web api 2 應(yīng)用程序中使用此實現(xiàn)和結(jié)構(gòu),但出現(xiàn)錯誤
i want to use this implementation and structure in asp.net web api 2 application but i get error
我的結(jié)構(gòu):
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 :
my token controller methode for generate and return 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 應(yīng)用程序中,我使用 OWIN 啟動類來驗證我的 token 用于所有具有 Authorize的控制器strong> 屬性.
in .net core 2 application i use OWIN Startup class to validate my token for all controllers which have Authorize attribute.
控制器示例:
namespace solution.Controllers
{
public class ExampleController : ApiController
{
[HttpPost]
[Route("api/Example")]
[Authorize(Policy = "Session")]
public void Run()
{
// do something;
}
}
}
用于驗證 JWT 令牌的我的 owin 啟動類:
my owin startup class for validating JWT token :
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 中使用這種結(jié)構(gòu),只改變 owin 類,可以嗎?請幫助我進行任何更改
i want to use this structure in asp.net web api only change owin class, it's possible? please help me for any change
推薦答案
將我的實現(xiàn)從 .net core 2 轉(zhuǎn)移到 asp.net web api 2
structure change for transfer my implementation from .net core 2 to asp.net web api 2
我使用 System.IdentityModel.Tokens.Jwt
命名空間來生成和驗證 JWT 令牌.
i use System.IdentityModel.Tokens.Jwt
namespace for generate and validate JWT token.
.net core 2 兼容 System.IdentityModel.Tokens.Jwt version="5.1.4"
但 asp.net web api 2 兼容 System.IdentityModel.Tokens.Jwt 版本="4.0.2"
.net core 2 compatible with System.IdentityModel.Tokens.Jwt version="5.1.4"
but asp.net web api 2 compatible with System.IdentityModel.Tokens.Jwt version="4.0.2"
包版本中的相同更改對代碼進行了更改,我使用 System.IdentityModel.Tokens
命名空間而不是 Microsoft.IdentityModel.Tokens
因為更改了軟件包版本.
The same change in the package version made changes to the code, also the part of code i use the System.IdentityModel.Tokens
namespace instead of Microsoft.IdentityModel.Tokens
because of changing package versions.
代碼更改:
JwtTokenBuilder 類:
在這個類中改變SigningCredentials
參數(shù)設(shè)置
in this class change SigningCredentials
parameter setting
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 令牌.
My main change was in Startup OWIN class and change Microsoft.Owin.Security.Jwt
package version from "3.1.0" to "3.0.0" for validate JWT token for incoming requests.
實現(xiàn):
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
);
}
}
}
這篇關(guān)于將 JWT 身份驗證實現(xiàn)從 .net core 2 轉(zhuǎn)移到 asp.net web api 2的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!