jwt生成和url解析
1、公共方法

using System.Security.Claims; using System.Security.Cryptography; using System.Security.Principal; namespace HRS.Web.Helper { public class TokenHelper { private static string _Secret = ConfigurationManager.AppSettings["TokenSercert"]; private static string _Issuer = ConfigurationManager.AppSettings["Issuer"]; public static string GenerateToken(string username, int expireMinutes = 120) { var symmetricKey = Convert.FromBase64String(_Secret); // 生成二进制字节数组 var tokenHandler = new JwtSecurityTokenHandler(); // 创建一个JwtSecurityTokenHandler类用来生成Token var now = DateTime.UtcNow; // 获取当前时间 var tokenDescriptor = new SecurityTokenDescriptor // 创建一个 Token 的原始对象 { Subject = new ClaimsIdentity(new[] // Token的身份证,类似一个人可以有身份证,户口本 { new Claim("username", username) // 可以创建多个 }), Expires = now.AddMinutes(Convert.ToInt32(expireMinutes)), // Token 有效期 NotBefore = now, IssuedAt = now, Issuer = _Issuer, SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(symmetricKey), SecurityAlgorithms.HmacSha256) }; var stoken = tokenHandler.CreateToken(tokenDescriptor); // 生成一个编码后的token对象实例 var token = tokenHandler.WriteToken(stoken); // 生成token字符串,给前端使用 return token; } /// <summary> /// 验证token /// </summary> /// <param name="token"></param> /// <returns></returns> public static IPrincipal AuthenticateJwtToken(string token) { string userName; if (ValidateToken(token, out userName)) { // 这里就是验证成功后要做的逻辑,也就是处理WWW-Authenticate验证 var info = new List<Claim>() { new Claim(ClaimTypes.Name, userName) };// 根据验证token后获取的用户名重新建一个声明,你可以在这里创建多个声明 // Claims就像你身份证上面的信息,一个Claim就是一条信息,将这些信息放在ClaimsIdentity就构成身份证 var infos = new ClaimsIdentity(info, "Jwt"); // 将上面的身份证放在ClaimsPrincipal里面,相当于把身份证给持有人 IPrincipal user = new ClaimsPrincipal(infos); return user; } return null; } private static bool ValidateToken(string token, out string userName) { userName = null; var simplePrincipal = GetPrincipal(token); // 调用自定义的GetPrincipal获取Token的信息对象 var identity = simplePrincipal.Identity as ClaimsIdentity; // 获取主声明标识 if (identity == null) return false; if (!identity.IsAuthenticated) return false; var userNameClaim = identity.FindFirst("username"); // 获取声明类型是ClaimTypes.Name的第一个声明 userName = userNameClaim.Value; // 获取声明的名字,也就是用户名 if (string.IsNullOrEmpty(userName)) return false; return true; } /// <summary> /// 此方法用解码字符串token,并返回秘钥的信息对象 /// </summary> /// <param name="token"></param> /// <returns></returns> private static ClaimsPrincipal GetPrincipal(string token) { try { var tokenHandler = new JwtSecurityTokenHandler(); // 创建一个JwtSecurityTokenHandler类,用来后续操作 var jwtToken = tokenHandler.ReadToken(token) as JwtSecurityToken; // 将字符串token解码成token对象 if (jwtToken == null) throw new ShowInfoException("token错误"); var symmetricKey = Convert.FromBase64String(_Secret); // 生成编码对应的字节数组 var validationParameters = new TokenValidationParameters() // 生成验证token的参数 { RequireExpirationTime = true, // token是否包含有效期 ValidateIssuer = false, // 验证秘钥发行人,如果要验证在这里指定发行人字符串即可 ValidIssuer = _Issuer, ValidateAudience = false, // 验证秘钥的接受人,如果要验证在这里提供接收人字符串即可 IssuerSigningKey = new SymmetricSecurityKey(symmetricKey), // 生成token时的安全秘钥 ValidateLifetime = false, //是否验证失效时间 LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken scToken, TokenValidationParameters vParameters) => expires > DateTime.UtcNow, }; SecurityToken securityToken; // 接受解码后的token对象 var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken); return principal; // 返回秘钥的主体对象,包含秘钥的所有相关信息 } catch (SecurityTokenInvalidLifetimeException ex) { throw new ShowInfoException("token超时,请重新获取token"); } catch (SecurityTokenInvalidIssuerException ex) { throw new ShowInfoException("token发行人错误,应该是【{0}】", _Issuer); } catch (Exception ex) { throw new ShowInfoException("token错误"); } } } }
2、生成
respone.access_token = TokenHelper.GenerateToken(model.businesslicenseNo, 5);
3、解析和重定向

using HRS.Lib.Comm.Exceptions; using HRS.Service.Contract.ContractParam.Base; using HRS.Service.Contract.Security; using HRS.Web.Helper; using HRS.Web.JsonCommunication; using HRS.Web.Rule; using HRS.Web.WcfClient; using System; using System.Net; using System.Text; using System.Web.Mvc; namespace HRS.Web.Controllers { public class LoginController : BaseController { public const string USER_NAME_VERIFYCODE_KEY_NAME = "==VERIFYCODE=="; // // GET: /Login/ [AllowAnonymous] public ActionResult Index() { try { var authorization = Request.QueryString["jwt"]; // 获取请求的token对象 if (authorization == null) throw new ShowInfoException("缺省jwt参数"); var principal = TokenHelper.AuthenticateJwtToken(authorization); // 调用此方法,根据token生成对应的"身份证持有人" if (principal == null) { throw new ShowInfoException("jwt参数格式不正确"); } Login(principal.Identity.Name); return Redirect("~/dashboard.html"); } catch(Exception e) { BusinessEngine.Logger.Error(e); return Content(e.Message); } } /// <summary> /// 登录 /// </summary> private void Login(string username) { BaseRequstJson requestJson = new BaseRequstJson() { MethodFullName = "PotentialCustomer.Login", ParamTypeName = "LoginReqParam", ParamJsonData = "{\"Username\":\"" + username + "\",\"IsTempPwdLogin\":true,\"ExtraData\":{\"VerifyCode\":\"\"}}" }; var param = GetParam(requestJson.ParamTypeName, requestJson.ParamJsonData); var paramUser = param as LoginReqParam; if (paramUser == null) { throw new ArgumentNullException("param type is not ParamUser"); } // 登录信息 ValidateIP(paramUser); //与wcf服务通讯 var resp = ServiceCommunicator.Login<BaseResponse>(requestJson.MethodFullName, paramUser, paramUser.UserName); paramUser.UserID = resp.ExtraData.GetStr("UserID"); SessionAdapter[BaseControllerEngine.CUR_USER_SESSION_NAME] = paramUser; SessionAdapter[BaseControllerEngine.CUR_USER_RES_NAME] = new UserRes(); Session["UserID"] = paramUser.UserID; Session["UserType"] = paramUser.UserType; Session["LoginTime"] = DateTime.Now.ToString("yyyyMMddHHmmssffff"); Session["UserCName"] = resp.ExtraData.GetStr("UserCName"); Session["InstitutionName"] = resp.ExtraData.GetStr("InstitutionName"); } /// <summary> /// 验证IP /// </summary> /// <param name="paramUser"></param> private void ValidateIP(LoginReqParam paramUser) { var sb = new StringBuilder(); sb.Append("【UserAgent:】" + Request.UserAgent); sb.Append("【UserHostAddress:】" + Request.UserHostAddress); sb.Append("【UserHostName:】" + Request.UserHostName); string userHostAddress = string.Empty; if (null != Request.ServerVariables["HTTP_X_FORWARDED_FOR"]) { userHostAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString().Split(',')[0].Trim(); } //否则直接读取REMOTE_ADDR获取客户端IP地址 if (string.IsNullOrEmpty(userHostAddress)) { userHostAddress = Request.ServerVariables["REMOTE_ADDR"]; } //前两者均失败,则利用Request.UserHostAddress属性获取IP地址,但此时无法确定该IP是客户端IP还是代理IP if (string.IsNullOrEmpty(userHostAddress)) { userHostAddress = Request.UserHostAddress; } //最后判断获取是否成功,并检查IP地址的格式(检查其格式非常重要) if (string.IsNullOrEmpty(userHostAddress) || !HRS.Lib.Comm.IO.WebUtil.IsIP(userHostAddress)) { userHostAddress = "172.0.0.1"; } sb.Append("【ClientIP:】" + userHostAddress); for (var i = 0; i < Request.ServerVariables.AllKeys.Length; i++) { var key = Request.ServerVariables.AllKeys[i]; sb.Append(string.Format("【ServerVariables-{0}:】{1}", key, Request.ServerVariables[key])); } paramUser.ClientIP = userHostAddress; paramUser.LoginInfo = sb.ToString(); #region 当前服务器信息 var serverhost = Dns.GetHostEntry(Dns.GetHostName()); var serverIP = string.Empty; foreach (IPAddress ip in serverhost.AddressList) { if (ip.AddressFamily.ToString() == "InterNetwork") { serverIP = ip.ToString(); break; } } paramUser.ServerInfo = string.Format("{0}:{1}", serverhost.HostName, serverIP); #endregion } } }
4、调用
http://localhost:8888/Login?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Inh4eHh4LXh4eDEiLCJuYmYiOjE2NDc4MzE2NDksImV4cCI6MTY0NzgzMTk0OSwiaWF0IjoxNjQ3ODMxNjQ5LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjUwMDAifQ.8OnP1WF5EVI3O_TOnsVCkS_PC0tvtJQj268haOpuOY4