JWT签名与验签
签名Token生产
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens;namespace CoreTest.Controllers {public class TokenController : Controller{private ITokenHelper _tokenHelper = null;public TokenController(ITokenHelper tokenHelper){_tokenHelper = tokenHelper;}public IActionResult Index(string code, string pwd){User user = TemporaryData.GetUser(code);if (null != user && user.Password.Equals(pwd)){return Ok(_tokenHelper.CreateToken(user));}return BadRequest();}[HttpPost][Authorize]public IActionResult Index(){return Ok(_tokenHelper.RefreshToken(Request.HttpContext.User));}}public interface ITokenHelper{Token CreateAccessToken(User user);ComplexToken CreateToken(User user);ComplexToken CreateToken(Claim[] claims);Token RefreshToken(ClaimsPrincipal claimsPrincipal);}public class TokenHelper : ITokenHelper{private IOptions_options;public TokenHelper(IOptions options){_options = options;}public Token CreateAccessToken(User user){Claim[] claims = new Claim[] { new Claim(ClaimTypes.NameIdentifier, user.Code), new Claim(ClaimTypes.Name, user.Name) };return CreateToken(claims, TokenType.AccessToken);}public ComplexToken CreateToken(User user){Claim[] claims = new Claim[] { new Claim(ClaimTypes.NameIdentifier, user.Code), new Claim(ClaimTypes.Name, user.Name)//下面两个Claim用于测试在Token中存储用户的角色信息,对应测试在FlyLolo.JWT.API的两个测试Controller的Put方法,若用不到可删除, new Claim(ClaimTypes.Role, "TestPutBookRole"), new Claim(ClaimTypes.Role, "TestPutStudentRole")};return CreateToken(claims);}public ComplexToken CreateToken(Claim[] claims){return new ComplexToken { AccessToken = CreateToken(claims, TokenType.AccessToken), RefreshToken = CreateToken(claims, TokenType.RefreshToken) };}/// /// 用于创建AccessToken和RefreshToken。/// 这里AccessToken和RefreshToken只是过期时间不同,【实际项目】中二者的claims内容可能会不同。/// 因为RefreshToken只是用于刷新AccessToken,其内容可以简单一些。/// 而AccessToken可能会附加一些其他的Claim。/// /// /// /// private Token CreateToken(Claim[] claims, TokenType tokenType){var now = DateTime.Now;var expires = now.Add(TimeSpan.FromMinutes(tokenType.Equals(TokenType.AccessToken) ? _options.Value.AccessTokenExpiresMinutes : _options.Value.RefreshTokenExpiresMinutes));//设置不同的过期时间var token = new JwtSecurityToken(issuer: _options.Value.Issuer,audience: tokenType.Equals(TokenType.AccessToken) ? _options.Value.Audience : _options.Value.RefreshTokenAudience,//设置不同的接受者 claims: claims,notBefore: now,expires: expires,signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_options.Value.IssuerSigningKey)), SecurityAlgorithms.HmacSha256));return new Token { TokenContent = new JwtSecurityTokenHandler().WriteToken(token), Expires = expires };}public Token RefreshToken(ClaimsPrincipal claimsPrincipal){var code = claimsPrincipal.Claims.FirstOrDefault(m => m.Type.Equals(ClaimTypes.NameIdentifier));if (null != code){return CreateAccessToken(TemporaryData.GetUser(code.Value.ToString()));}else{return null;}}}public class User{public string Code { get; set; }public string Name { get; set; }public string Password { get; set; }}public class Token{public string TokenContent { get; set; }public DateTime Expires { get; set; }}public enum TokenType{AccessToken = 1,RefreshToken = 2}public class ComplexToken{public Token AccessToken { get; set; }public Token RefreshToken { get; set; }}public class JWTConfig{public string Issuer { get; set; }public string Audience { get; set; }public string IssuerSigningKey { get; set; }public int AccessTokenExpiresMinutes { get; set; }public string RefreshTokenAudience { get; set; }public int RefreshTokenExpiresMinutes { get; set; }}public static class TemporaryData{private static List Users = new List (){new User { Code = "001", Name = "张三", Password = "111111" },new User { Code = "002", Name = "李四", Password = "222222" }};public static User GetUser(string code){return Users.FirstOrDefault(m => m.Code.Equals(code));}} }
appsettings.json
{"Logging": {"LogLevel": {"Default": "Warning"}},"AllowedHosts": "*","JWT": {"Issuer": "FlyLolo","Audience": "TestAudience","IssuerSigningKey": "FlyLolo1234567890","AccessTokenExpiresMinutes": "30","RefreshTokenAudience": "RefreshTokenAudience","RefreshTokenExpiresMinutes": "10080"} }
Startup.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CoreTest.Controllers; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens;namespace CoreTest {public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.Configure(Configuration.GetSection("User"));services.AddSingleton ();services.Configure (Configuration.GetSection("JWT"));JWTConfig config = new JWTConfig();Configuration.GetSection("JWT").Bind(config);services.AddAuthentication(options => {options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options => {options.TokenValidationParameters = new TokenValidationParameters{ValidIssuer = config.Issuer,ValidAudience = config.RefreshTokenAudience,IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.IssuerSigningKey))};});services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts();}app.UseHttpsRedirection();app.UseAuthentication();app.UseMvc(route =>{route.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}");});}} }
Token验证
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc;namespace ClientTest.Controllers {[Route("api/[controller]")][ApiController][Authorize]public class BookController : ControllerBase{// GET: api/[HttpGet][AllowAnonymous]public IEnumerable<string> Get(){return new string[] { "ASP", "C#" };}// POST api/ [HttpPost]public JsonResult Post(){return new JsonResult("Create Book ...");}}public class JWTConfig{public string Issuer { get; set; }public string Audience { get; set; }public string IssuerSigningKey { get; set; }public int AccessTokenExpiresMinutes { get; set; } } }
appsettings.json
{"Logging": {"LogLevel": {"Default": "Warning"}},"AllowedHosts": "*","JWT": {"Issuer": "FlyLolo","Audience": "TestAudience","IssuerSigningKey": "FlyLolo1234567890","AccessTokenExpiresMinutes": "30"} }
Startup.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ClientTest.Controllers; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens;namespace ClientTest {public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){#region 读取配置JWTConfig config = new JWTConfig();Configuration.GetSection("JWT").Bind(config);#endregion#region 启用JWT认证services.AddAuthentication(options =>{options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options =>{options.TokenValidationParameters = new TokenValidationParameters{ValidIssuer = config.Issuer,ValidAudience = config.Audience,IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.IssuerSigningKey)),ClockSkew = TimeSpan.FromMinutes(1)};});#endregionservices.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts();}app.UseHttpsRedirection();app.UseAuthentication();app.UseMvc();}} }
转载于:https://www.cnblogs.com/huangzelin/p/11475191.html
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
