JwtAuthExtension.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. using Microsoft.AspNetCore.Authentication.JwtBearer;
  2. using Microsoft.AspNetCore.Authorization;
  3. using Microsoft.Extensions.Configuration;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using Microsoft.IdentityModel.Tokens;
  6. using System;
  7. using System.Threading.Tasks;
  8. using System.Security.Claims;
  9. using System.IdentityModel.Tokens.Jwt;
  10. using System.Collections.Generic;
  11. using System.Text;
  12. using System.ComponentModel;
  13. namespace TEAMModelOS.SDK.Extension
  14. {
  15. public static class JwtAuthExtension
  16. {
  17. public static string CreateAuthToken(string issuer, string id, string name, string picture, string salt, string scope, string Website, string areaId = "", string schoolID = "", string standard = "", string[] roles = null, string[] permissions = null, int expire = 1)
  18. {
  19. // 設定要加入到 JWT Token 中的聲明資訊(Claims)
  20. var payload = new JwtPayload {
  21. { JwtRegisteredClaimNames.Iss, issuer }, //發行者
  22. { JwtRegisteredClaimNames.Sub, id }, // 用戶ID
  23. { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話
  24. { JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString()}, // 到期的時間,必須為數字
  25. { "name",name}, // 用戶的顯示名稱
  26. { "picture",picture}, // 用戶頭像
  27. { "roles",roles}, // 登入者的角色,角色類型 (Admin、Teacher、Student)
  28. { "permissions",permissions}, //登入者的權限請求
  29. { "standard",standard} ,//登入者的能力点标准
  30. { "scope",scope}, //登入者的入口类型。 (teacher 教师端登录的醍摩豆ID、tmduser学生端登录的醍摩豆ID、student学生端登录校内账号的学生ID)
  31. { "area",areaId==null?"":areaId},
  32. { JwtRegisteredClaimNames.Website,Website},
  33. };
  34. // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用
  35. var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
  36. // HmacSha256 有要求必須要大於 128 bits,所以 salt 不能太短,至少要 16 字元以上
  37. // https://stackoverflow.com/questions/47279947/idx10603-the-algorithm-hs256-requires-the-securitykey-keysize-to-be-greater
  38. var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
  39. var header = new JwtHeader(signingCredentials);
  40. var secToken = new JwtSecurityToken(header, payload);
  41. // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
  42. var tokenHandler = new JwtSecurityTokenHandler();
  43. //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
  44. var serializeToken = tokenHandler.WriteToken(secToken);
  45. return serializeToken;
  46. }
  47. /// <summary>
  48. ///
  49. /// </summary>
  50. /// <param name="issuer">颁发者</param>
  51. /// <param name="id">第三方合作uuid</param>
  52. /// <param name="salt"></param>
  53. /// <param name="expire"></param>
  54. /// <returns></returns>
  55. public static (string jwt , string jti) CreateBusinessApiToken(string location, string id, string salt ,string scope)
  56. {
  57. var keys = OpenApiJtwIssuer.OpenApiJtw签发者.GetDescriptionText().Split(',');
  58. string issuer = "";
  59. if (location.Equals("China-Dep"))
  60. {
  61. issuer = keys[0];
  62. }
  63. else if (location.Equals("China-Test"))
  64. {
  65. issuer = keys[0];
  66. }
  67. else if (location.Equals("China"))
  68. {
  69. issuer = keys[1];
  70. }
  71. else if (location.Equals("Global-Dep"))
  72. {
  73. issuer = keys[2];
  74. }
  75. else if (location.Equals("Global-Test"))
  76. {
  77. issuer = keys[2];
  78. }
  79. else if (location.Equals("Global"))
  80. {
  81. issuer = keys[3];
  82. }
  83. string jti = Guid.NewGuid().ToString();
  84. // 設定要加入到 JWT Token 中的聲明資訊(Claims)
  85. var payload = new JwtPayload {
  86. { JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者
  87. { JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户
  88. {JwtRegisteredClaimNames.Jti, jti},
  89. { "scope",scope}
  90. };
  91. // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用
  92. var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
  93. // HmacSha256 有要求必須要大於 128 bits,所以 salt 不能太短,至少要 16 字元以上
  94. // https://stackoverflow.com/questions/47279947/idx10603-the-algorithm-hs256-requires-the-securitykey-keysize-to-be-greater
  95. var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
  96. var header = new JwtHeader(signingCredentials);
  97. var secToken = new JwtSecurityToken(header, payload);
  98. // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
  99. var tokenHandler = new JwtSecurityTokenHandler();
  100. //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
  101. var serializeToken = tokenHandler.WriteToken(secToken);
  102. return (serializeToken,jti);
  103. }
  104. public static string CreateApiToken(string issuer, string id, string salt, string name, List<int> auth, string schoolID = "", int expire = 1)
  105. {
  106. // 設定要加入到 JWT Token 中的聲明資訊(Claims)
  107. var payload = new JwtPayload {
  108. { JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者
  109. { JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户
  110. { JwtRegisteredClaimNames.Aud, "" }, // aud: 接收jwt的一方
  111. { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話
  112. {JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString() },
  113. { "name",name}, // 用戶的顯示名稱
  114. //{ JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString()}, // 到期的時間,必須為數字
  115. //{ "name",name}, // 用戶的顯示名稱
  116. //{ "picture",picture}, // 用戶頭像
  117. { "auth",auth}, // 登入者的角色,角色類型 (Admin、Teacher、Student)
  118. // { "permissions",permissions} //登入者的權限請求
  119. };
  120. // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用
  121. var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
  122. // HmacSha256 有要求必須要大於 128 bits,所以 salt 不能太短,至少要 16 字元以上
  123. // https://stackoverflow.com/questions/47279947/idx10603-the-algorithm-hs256-requires-the-securitykey-keysize-to-be-greater
  124. var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
  125. var header = new JwtHeader(signingCredentials);
  126. var secToken = new JwtSecurityToken(header, payload);
  127. // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
  128. var tokenHandler = new JwtSecurityTokenHandler();
  129. //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
  130. var serializeToken = tokenHandler.WriteToken(secToken);
  131. return serializeToken;
  132. }
  133. public static bool ValidateApiToken(string token, string salt)
  134. {
  135. try
  136. {
  137. var handler = new JwtSecurityTokenHandler();
  138. var validationParameters = new TokenValidationParameters
  139. {
  140. RequireExpirationTime = false,
  141. ValidateIssuer = false,
  142. ValidateAudience = false,
  143. IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
  144. ValidateLifetime = false,
  145. //LifetimeValidator = LifetimeValidator,
  146. ClockSkew = TimeSpan.Zero
  147. };
  148. ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
  149. return true;
  150. }
  151. catch (Exception)
  152. {
  153. //Trace.WriteLine(ex.Message);
  154. return false;
  155. }
  156. }
  157. public static bool ValidateAuthToken(string token, string salt)
  158. {
  159. try
  160. {
  161. var handler = new JwtSecurityTokenHandler();
  162. var validationParameters = new TokenValidationParameters
  163. {
  164. RequireExpirationTime = true,
  165. ValidateIssuer = false,
  166. ValidateAudience = false,
  167. IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
  168. ValidateLifetime = false,
  169. //LifetimeValidator = LifetimeValidator,
  170. ClockSkew = TimeSpan.Zero
  171. };
  172. ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
  173. return true;
  174. }
  175. catch (Exception)
  176. {
  177. //Trace.WriteLine(ex.Message);
  178. return false;
  179. }
  180. }
  181. }
  182. public enum OpenApiJtwIssuer
  183. {
  184. [Description("open-test.teammodel.cn,open.teammodel.cn,open-test.teammodel.net,open.teammodel.net")]
  185. OpenApiJtw签发者,
  186. }
  187. }