123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- 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;
- using System.ComponentModel;
- namespace TEAMModelOS.SDK.Extension
- {
- public static class JwtAuthExtension
- {
- public static string CreateAuthToken(string issuer, string id, string name, string picture, string salt, string scope, string Website,int timezone, string areaId = "", string schoolID = "", string standard = "", string[] roles = null, string[] permissions = null, int expire = 1,int year=-1)
- {
- // 設定要加入到 JWT Token 中的聲明資訊(Claims)
- var payload = new JwtPayload {
- { JwtRegisteredClaimNames.Iss, issuer }, //發行者
- { JwtRegisteredClaimNames.Sub, id }, // 用戶ID
- { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話
- { JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds()}, // 到期的時間,必須為數字
- { "name",name}, // 用戶的顯示名稱
- { "picture",picture}, // 用戶頭像
- { "roles",roles}, // 登入者的角色,角色類型 (Admin、Teacher、Student)
- { "permissions",permissions}, //登入者的權限請求
- { "standard",standard} ,//登入者的能力点标准
- { "scope",scope}, //登入者的入口类型。 (teacher 教师端登录的醍摩豆ID、tmduser学生端登录的醍摩豆ID、student学生端登录校内账号的学生ID)
- { "area",areaId==null?"":areaId},
- { "timezone",timezone},
- { JwtRegisteredClaimNames.Website,Website},
- };
- //学生入学年
- if (year!=-1) {
- payload.Add("year", year);
- }
- // 建立一組對稱式加密的金鑰,主要用於 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);
- var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
- var header = new JwtHeader(signingCredentials);
- var secToken = new JwtSecurityToken(header, payload);
- // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
- var tokenHandler = new JwtSecurityTokenHandler();
- //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
- var serializeToken = tokenHandler.WriteToken(secToken);
- return serializeToken;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="issuer">颁发者</param>
- /// <param name="id">第三方合作uuid</param>
- /// <param name="salt"></param>
- /// <param name="expire"></param>
- /// <returns></returns>
- public static (string jwt , string jti) CreateBusinessApiToken(string location, string id, string salt,int customize = 0 )
- {
- string scope = "business";
- if (customize != 0)
- scope = "customize";
- var keys = OpenApiJtwIssuer.OpenApiJtw签发者.GetDescriptionText().Split(',');
- string issuer = "";
- if (location.Equals("China-Dep"))
- {
- issuer = keys[0];
- }
- else if (location.Equals("China-Test"))
- {
- issuer = keys[0];
- }
- else if (location.Equals("China"))
- {
- issuer = keys[1];
- }
- else if (location.Equals("Global-Dep"))
- {
- issuer = keys[2];
- }
- else if (location.Equals("Global-Test"))
- {
- issuer = keys[2];
- }
- else if (location.Equals("Global"))
- {
- issuer = keys[3];
- }
- string jti = Guid.NewGuid().ToString();
- // 設定要加入到 JWT Token 中的聲明資訊(Claims)
- var payload = new JwtPayload {
- { JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者
- { JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户
- {JwtRegisteredClaimNames.Jti, jti},
- { "scope",scope}
- };
- // 建立一組對稱式加密的金鑰,主要用於 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);
- var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
- var header = new JwtHeader(signingCredentials);
- var secToken = new JwtSecurityToken(header, payload);
- // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
- var tokenHandler = new JwtSecurityTokenHandler();
- //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
- var serializeToken = tokenHandler.WriteToken(secToken);
- return (serializeToken,jti);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="issuer">颁发者</param>
- /// <param name="id">第三方合作uuid</param>
- /// <param name="salt"></param>
- /// <param name="expire"></param>
- /// <returns></returns>
- public static (string jwt, string jti) CreateSchoolApiToken(string location, string id, string salt,List<int> auth, string schoolID = "")
- {
- string scope = "school";
- var keys = OpenApiJtwIssuer.OpenApiJtw签发者.GetDescriptionText().Split(',');
- string issuer = "";
- if (location.Equals("China-Dep"))
- {
- issuer = keys[0];
- }
- else if (location.Equals("China-Test"))
- {
- issuer = keys[0];
- }
- else if (location.Equals("China"))
- {
- issuer = keys[1];
- }
- else if (location.Equals("Global-Dep"))
- {
- issuer = keys[2];
- }
- else if (location.Equals("Global-Test"))
- {
- issuer = keys[2];
- }
- else if (location.Equals("Global"))
- {
- issuer = keys[3];
- }
- string jti = Guid.NewGuid().ToString();
- // 設定要加入到 JWT Token 中的聲明資訊(Claims)
- var payload = new JwtPayload {
- { JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者
- { JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户
- {JwtRegisteredClaimNames.Jti, jti},
- { "scope",scope},
- { "auth",auth},
- { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話
- };
- // 建立一組對稱式加密的金鑰,主要用於 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);
- var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
- var header = new JwtHeader(signingCredentials);
- var secToken = new JwtSecurityToken(header, payload);
- // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
- var tokenHandler = new JwtSecurityTokenHandler();
- //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
- var serializeToken = tokenHandler.WriteToken(secToken);
- return (serializeToken, jti);
- }
- public static string CreateApiToken(string issuer, string id, string salt, string name, List<int> auth, string schoolID = "", int expire = 1)
- {
- // 設定要加入到 JWT Token 中的聲明資訊(Claims)
- var payload = new JwtPayload {
- { JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者
- { JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户
- { JwtRegisteredClaimNames.Aud, "" }, // aud: 接收jwt的一方
- { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話
- {JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString() },
- { "name",name}, // 用戶的顯示名稱
- //{ JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds()}, // 到期的時間,必須為數字
- //{ "name",name}, // 用戶的顯示名稱
- //{ "picture",picture}, // 用戶頭像
- { "auth",auth}, // 登入者的角色,角色類型 (Admin、Teacher、Student)
- // { "permissions",permissions} //登入者的權限請求
- };
- // 建立一組對稱式加密的金鑰,主要用於 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);
- var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
- var header = new JwtHeader(signingCredentials);
- var secToken = new JwtSecurityToken(header, payload);
- // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
- var tokenHandler = new JwtSecurityTokenHandler();
- //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
- var serializeToken = tokenHandler.WriteToken(secToken);
- return serializeToken;
- }
- public static bool ValidateApiToken(string token, string salt)
- {
- try
- {
- var handler = new JwtSecurityTokenHandler();
- var validationParameters = new TokenValidationParameters
- {
- RequireExpirationTime = false,
- 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)
- {
- //Trace.WriteLine(ex.Message);
- return false;
- }
- }
- 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)
- {
- //Trace.WriteLine(ex.Message);
- return false;
- }
- }
- /// <summary>
- /// 刷新token,不验证过期时间
- /// </summary>
- /// <param name="token"></param>
- /// <param name="salt"></param>
- /// <returns></returns>
- public static bool ValidateAuthTokenRefresh(string token, string salt)
- {
- try
- {
- var handler = new JwtSecurityTokenHandler();
- var validationParameters = new TokenValidationParameters
- {
- RequireExpirationTime = false,
- ValidateIssuer = false,
- ValidateAudience = false,
- IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
- ValidateLifetime = true,
- ClockSkew = TimeSpan.Zero
- };
- ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
- return true;
- }
- catch (Exception)
- {
- //Trace.WriteLine(ex.Message);
- return false;
- }
- }
- /// <summary>
- /// 第三方登录后的id_token
- /// </summary>
- /// <param name="issuser"></param>
- /// <param name="id"></param>
- /// <param name="name"></param>
- /// <param name="picture"></param>
- /// <param name="webSite"></param>
- /// <param name="salt"></param>
- /// <param name="roles"></param>
- /// <param name="permissions"></param>
- /// <param name="expire"></param>
- /// <returns></returns>
- public static string CreateBizLoginAuthToken(string issuser, string id, string name, string picture, string webSite, string salt, string[] roles = null, string[] permissions = null, int expire = 1)
- {
- var payload = new JwtPayload
- {
- { JwtRegisteredClaimNames.Iss,issuser}, //发行者
- { JwtRegisteredClaimNames.Sub,id}, //用户ID
- { JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds()},//到期时间
- { "name",name},//用户显示名称
- { "picture",picture}, // 用户头像
- { "roles",roles}, //登陆者的角色, (admin、dea)
- { "permissions",permissions}, //登陆者的权限
- { JwtRegisteredClaimNames.Website,webSite}, // 平台站点
- };
- // 建立加密的秘钥
- 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);
- var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
- var header = new JwtHeader(signingCredentials);
- var secToken = new JwtSecurityToken(header, payload);
- // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
- var tokenHandler = new JwtSecurityTokenHandler();
- //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
- var serializeToken = tokenHandler.WriteToken(secToken);
- return serializeToken;
- }
- }
- public enum OpenApiJtwIssuer
- {
- [Description("open-test.teammodel.cn,open.teammodel.cn,open-test.teammodel.net,open.teammodel.net")]
- OpenApiJtw签发者,
- }
- }
|