1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- using IdentityModel;
- using Microsoft.AspNetCore.Authentication.JwtBearer;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.IdentityModel.Tokens;
- using System;
- using System.Threading.Tasks;
- using System.Security.Claims;
- using System.IdentityModel.Tokens.Jwt;
- using System.Collections.Generic;
- using System.Text;
- namespace TEAMModelOS.SDK.Extension
- {
- public static class JwtAuthExtension
- {
- public static string CreateAuthToken(string issuer, string id,string name,string picture, string salt, string schoolID = "", string[] roles = null, string[] permissions = null, int expire = 1)
- {
- // 設定要加入到 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.Sub, id)); // 用戶ID
- claims.Add(new Claim("name", name)); // 用戶的顯示名稱
- claims.Add(new Claim("picture", picture)); // 用戶頭像
- claims.Add(new Claim(JwtRegisteredClaimNames.Azp, schoolID)); // 學校簡碼,如果有的話
- claims.Add(new Claim(JwtRegisteredClaimNames.Exp, DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString())); // 到期的時間,必須為數字
- // 擴充 "roles" 加入登入者的角色,角色類型 (USER、HABOOK)
- if (roles != null)
- {
- foreach (var role in roles)
- {
- claims.Add(new Claim("roles", role));
- }
- }
- // 擴充 "permissions" 加入登入者的權限請求
- if (permissions != null)
- {
- foreach (var role in permissions)
- {
- claims.Add(new Claim("permissions", role));
- }
- }
- // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用
- var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
- // HmacSha256 有要求必須要大於 128 bits,所以 salt 不能太短,至少要 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,
- Subject = new ClaimsIdentity(claims),
- Expires = DateTime.Now.AddHours(expire),
- SigningCredentials = signingCredentials
- };
- // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
- var tokenHandler = new JwtSecurityTokenHandler();
- var securityToken = tokenHandler.CreateToken(tokenDescriptor);
- var serializeToken = tokenHandler.WriteToken(securityToken);
- return serializeToken;
- }
- public static bool ValidateAuthToken(string token, string salt)
- {
- try
- {
- var handler = new JwtSecurityTokenHandler();
- var validationParameters = new TokenValidationParameters
- {
- RequireExpirationTime = true,
- ValidateIssuer = false,
- ValidateAudience = false,
- IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
- ValidateLifetime = false,
- //LifetimeValidator = LifetimeValidator,
- ClockSkew = TimeSpan.Zero
- };
- ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
- return true;
- }
- catch (Exception ex)
- {
- //Trace.WriteLine(ex.Message);
- return false;
- }
- }
- }
- }
|