tycg_carviolation_BE/Traffic.Service/Helpers/JwtHelpers.cs

90 lines
4.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using Traffic.Data.ViewModels;
using Microsoft.Extensions.Configuration;
using Traffic.Data.Enums;
namespace Traffic.Service.Helpers
{
public class JwtHelpers
{
private readonly IConfiguration _configuration;
public JwtHelpers(IConfiguration configuration)
{
_configuration = configuration;
}
public string GenerateToken(AccountUserViewModel admin, int expireDays = 30)
{
var issuer = _configuration.GetValue<string>("JwtSettings:Issuer");
var signKey = _configuration.GetValue<string>("JwtSettings:SignKey");
// 設定要加入到 JWT Token 中的聲明資訊(Claims)
var claims = new List<Claim>();
// 在 RFC 7519 規格中(Section#4),總共定義了 7 個預設的 Claims我們應該只用的到兩種
//claims.Add(new Claim(JwtRegisteredClaimNames.Iss, issuer));
claims.Add(new Claim(JwtRegisteredClaimNames.NameId, admin.Id.ToString())); // member.Identity.Name
claims.Add(new Claim(JwtRegisteredClaimNames.Name, admin.Account.ToString())); // member.Identity.Name
claims.Add(new Claim(JwtRegisteredClaimNames.GivenName, admin.Name.ToString())); // member.Identity.Name
//claims.Add(new Claim(JwtRegisteredClaimNames.Aud, "The Audience"));
//claims.Add(new Claim(JwtRegisteredClaimNames.Exp, DateTimeOffset.UtcNow.AddMinutes(30).ToUnixTimeSeconds().ToString()));
//claims.Add(new Claim(JwtRegisteredClaimNames.Nbf, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString())); // 必須為數字
//claims.Add(new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString())); // 必須為數字
claims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())); // JWT ID
// 網路上常看到的這個 NameId 設定是多餘的
//claims.Add(new Claim(JwtRegisteredClaimNames.NameId, memberName));
// 這個 Claim 也以直接被 JwtRegisteredClaimNames.Sub 取代,所以也是多餘的
//claims.Add(new Claim(ClaimTypes.Name, memberName));
// 你可以自行擴充 "roles" 加入登入者該有的角色
switch (admin.Role)
{
case (int)Auth.Admin:
claims.Add(new Claim("roles", "Admin"));
break;
case (int)Auth.User:
claims.Add(new Claim("roles", "User"));
break;
default:
break;
}
var memberClaimsIdentity = new ClaimsIdentity(claims);
// 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signKey));
// HmacSha256 有要求必須要大於 128 bits所以 key 不能太短,至少要 16 字元以上
// https://stackoverflow.com/questions/47279947/idx10603-the-algorithm-hs256-requires-the-securitykey-keysize-to-be-greater
var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
// 建立 SecurityTokenDescriptor
var tokenDescriptor = new SecurityTokenDescriptor
{
Issuer = issuer,
//Audience = issuer, // 由於你的 API 受眾通常沒有區分特別對象,因此通常不太需要設定,也不太需要驗證
//NotBefore = DateTime.Now, // 預設值就是 DateTime.Now
//IssuedAt = DateTime.Now, // 預設值就是 DateTime.Now
Subject = memberClaimsIdentity,
Expires = DateTime.Now.AddDays(expireDays),
SigningCredentials = signingCredentials
};
// 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
var serializeToken = tokenHandler.WriteToken(securityToken);
return serializeToken;
}
}
}