安裝Microsoft.AspNetCore.Authentication.JwtBearer
Nuget包
appsettings.json中,添加JWT的配置,注意SecretKey
不能設置成太短的純數字,不然要報錯
"JWT": {
"Issuer": "AudienceUpgrade", //發行人
"Audience": "UpgradeService", //擁有者
"SecretKey": "900BA04D853C4DDF9CBF8B2B406EB4B6", //16位以上
"Expires": 7 //過期時間 單位:天
}
添加Jwt服務
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true, //是否驗證Issuer
ValidIssuer = builder.Configuration["Jwt:Issuer"], //發行人Issuer
ValidateAudience = true, //是否驗證Audience
ValidAudience = builder.Configuration["Jwt:Audience"], //訂閱人Audience
ValidateIssuerSigningKey = true, //是否驗證SecurityKey
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecretKey"])), //SecurityKey
ValidateLifetime = true, //是否驗證失效時間
ClockSkew = TimeSpan.FromSeconds(30), //過期時間容錯值,解決服務器端時間不同步問題(秒)
RequireExpirationTime = true,
};
//自定義認證不過的返回值
options.Events = new JwtBearerEvents
{
OnChallenge = async context =>
{
context.HandleResponse();
context.Response.ContentType = "application/json;charset=utf-8";
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("{\"message\":\"Unauthorized\",\"success\":false}");
}
};
});
啓用認證
app.UseAuthentication();
app.UseAuthorization();
添加一個JWT幫助類
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Security.Claims;
using System.Text;
namespace WebApplication2
{
public class TokenHelper
{
private readonly IConfiguration _configuration;
public TokenHelper(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// 創建加密JwtToken
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public string CreateJwtToken<T>(T t)
{
// 定義用戶信息
//var claims = new Claim[]
//{
// new Claim(ClaimTypes.Name, "123456"),
// new Claim(JwtRegisteredClaimNames.Email, "[email protected]"),
//};
var claimList = new List<Claim>();
foreach (var item in typeof(T).GetProperties()) claimList.Add(new Claim(item.Name, item.GetValue(t)!.ToString()!));
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:SecretKey"]));
var expires = Convert.ToDouble(_configuration["JWT:Expires"]);
var algorithm = SecurityAlgorithms.HmacSha256;//選擇加密算法
var signingCredentials = new SigningCredentials(secretKey, algorithm);
JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
_configuration["JWT:Issuer"], //Issuer
_configuration["JWT:Audience"], //Audience
claims: claimList,
DateTime.Now, //notBefore
DateTime.Now.AddDays(expires), //expires
signingCredentials //Credentials
);
string jwtToken = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
return jwtToken;
}
/// <summary>
/// 通過Token獲取對象信息,實體類字段必須全部是string類型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="Token"></param>
/// <returns></returns>
public T GetTokenObj<T>(string Token)
{
var jwt = Token.Replace("Bearer ", string.Empty).TrimStart();
Type t = typeof(T);
object obj = Activator.CreateInstance(t)!;
var jwtInfo = new JwtSecurityTokenHandler().ReadJwtToken(jwt);
foreach (var item in jwtInfo.Claims)
{
PropertyInfo _Property = t.GetProperty(item.Type);
if (_Property != null && _Property.CanRead)
_Property.SetValue(obj, item.Value, null);
}
return (T)obj;
}
/// <summary>
/// Token是否是符合要求的標準 Json Web 令牌
/// </summary>
/// <param name="tokenStr"></param>
/// <returns></returns>
public bool IsCanReadToken(ref string tokenStr)
{
if (string.IsNullOrWhiteSpace(tokenStr) || tokenStr.Length < 7)
return false;
if (!tokenStr.Substring(0, 6).Equals(Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme))
return false;
tokenStr = tokenStr.Substring(7);
bool isCan = new JwtSecurityTokenHandler().CanReadToken(tokenStr);
return isCan;
}
}
}
注入生命週期
builder.Services.AddSingleton<TokenHelper>();
使用JWT
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;
namespace WebApplication2.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly TokenHelper _tokenHelper;
public WeatherForecastController(TokenHelper tokenHelper)
{
_tokenHelper = tokenHelper;
}
[Authorize]
[HttpGet("GetWeatherForecast")]
public string Get()
{
string tokenStr = Request.Headers["Authorization"].ToString();
//獲取相關信息,實體類字段必須全部是string類型
var obj = _tokenHelper.GetTokenObj<Login>(tokenStr);
return JsonSerializer.Serialize(obj);
}
/// <summary>
/// 登錄
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpGet("Login")]
public string Login()
{
var t = new Login { Id=Guid.NewGuid().ToString() };
return _tokenHelper.CreateJwtToken(t);
}
}
public class Login
{
public string Id { get; set; }
}
}
控制器加上特性
//添加Jwt認證
[Authorize]
//取消認證
[AllowAnonymous]