ibms-dome/FrontendWebApi/Jwt/JwtHelpers.cs

101 lines
4.8 KiB
C#
Raw Permalink 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.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace FrontendWebApi.Jwt
{
public interface IJwtHelpers
{
TnToken GenerateToken(JwtLogin login);
}
public class JwtHelpers: IJwtHelpers
{
private readonly IConfiguration _configuration;
public JwtHelpers(IConfiguration configuration)
{
_configuration = configuration;
}
public TnToken GenerateToken(JwtLogin login)
{
var issuer = _configuration.GetValue<string>("JwtSettings:Issuer");
var signKey = _configuration.GetValue<string>("JwtSettings:SignKey");
var lifeseconds = _configuration.GetValue<int>("JwtSettings:JwtLifeSeconds");
// 設定要加入到 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, login.CustomerNo.ToString()));
//claims.Add(new Claim(JwtRegisteredClaimNames.Sub, login.Username)); // User.Identity.Name
//claims.Add(new Claim(JwtRegisteredClaimNames.Aud, "The Audience"));
claims.Add(new Claim(JwtRegisteredClaimNames.Exp, DateTimeOffset.UtcNow.AddSeconds(lifeseconds).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, userName));
// 這個 Claim 也以直接被 JwtRegisteredClaimNames.Sub 取代,所以也是多餘的
//claims.Add(new Claim(ClaimTypes.Name, userName));
// 你可以自行擴充 "roles" 加入登入者該有的角色
//claims.Add(new Claim("roles", "Users"));
//claims.Add(new Claim("groupid", login.AreaCode));
claims.Add(new Claim("userinfo_guid", login.userinfo_guid));
claims.Add(new Claim("account", login.account));
claims.Add(new Claim("full_name", login.full_name));
claims.Add(new Claim("email", login.email));
var userClaimsIdentity = 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);
var now = DateTime.UtcNow;
var expires = DateTime.UtcNow.AddSeconds(lifeseconds);
// 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
var tokenHandler = new JwtSecurityTokenHandler();
var jst = new JwtSecurityToken(
issuer: issuer,//Token釋出者
//audience: _options.Value.Audience,//Token接受者
claims: claims,//攜帶的負載
notBefore: now,//當前時間token生成時間
expires: expires,//過期時間
signingCredentials: signingCredentials
);
//var jst = new SecurityTokenDescriptor
//{
// Issuer = issuer,//Token釋出者
// //Claims = claims,//攜帶的負載
// //audience: _options.Value.Audience,//Token接受者
// NotBefore = now,//當前時間token生成時間
// Expires = expires,//過期時間
// SigningCredentials = signingCredentials,
// Subject = userClaimsIdentity
//};
var serializeToken = tokenHandler.WriteToken(jst);
var data = new TnToken();
data.token = serializeToken;
data.type = "bearer";
data.expires= lifeseconds;
return data;
}
}
}