当前位置:首页 > 芯闻号 > 充电吧
[导读]上一篇文章讲解了JWT的基本简介,这一篇文章我就来实战一下。介绍一下在分布式单点登录中的使用方法:首先来看一下Token实体类,public class Token implements Serial


上一篇文章讲解了JWT的基本简介,这一篇文章我就来实战一下。介绍一下在分布式单点登录中的使用方法:


首先来看一下Token实体类,


public class Token implements Serializable{
	private static final long serialVersionUID = -5391652691006115018L;
	
	/** 认证头 **/
	private Head head;
	/** 认证信息有效载荷 **/
	private Playload playload;
	
	/** 第一部分:base64head头 **/
	private String base64Head;
	/** 第二部分:base64playload荷载 **/
	private String base64PlayLoad;
	/** 第三部分:签证信息 **/
	private String signature;
	/** 最终token字符串 **/
	private String tokenStr;
	
	/**
	 * Token头
	 *
	 *
	 */
	public static class Head implements Serializable{
		private static final long serialVersionUID = -6516084948347601103L;
		
		/** token类型 **/
		private String typ = "JWT";
		/** token算法 默认:HMAC SHA256**/
		private String alg = "HS256";
		
		public String getTyp() {
			return typ;
		}
		public void setTyp(String typ) {
			this.typ = typ;
		}
		public String getAlg() {
			return alg;
		}
		public void setAlg(String alg) {
			this.alg = alg;
		}
	}
	
	/**
	 * Token有效载荷
	 * 
	 *
	 */
	public static class Playload implements Serializable {
		private static final long serialVersionUID = 3981890375700111920L;
		
		/** 该token签发者 **/
		private String iss;
		/** 该token的所有人,可以存放用户名 **/
		private String sub;
		/** 接收token的一方 **/
		private String aud;
		/** token的过期时间(时间戳),必须要大于签发时间;大于等于该时间需要刷新token **/
		private long exp;
		/** token生效的开始时间(时间戳),意味着在这个时间之前验证token是会失败的,默认生成token后立即生效 **/
		private long nbf;
		/** token的签发时间 时间戳**/
		private long iat;
		/** token的唯一身份标识,主要用来作为一次性token,从而回避重放攻击 **/
		private String jti;
		/** token验证宽限时间(时间戳) 超过宽限时间需要重新登录,  
		 * 即该token的真正存活时间,宽限时间的加入是为了解决并发token刷新后新token失效问题
		 * **/
		private long gra;
		/** token类型:  后台登录用户,互联网用户,第三方机构 **/
		private String typ;
		
		public String getIss() {
			return iss;
		}
		public void setIss(String iss) {
			this.iss = iss;
		}
		public String getSub() {
			return sub;
		}
		public void setSub(String sub) {
			this.sub = sub;
		}
		public String getAud() {
			return aud;
		}
		public void setAud(String aud) {
			this.aud = aud;
		}
		public long getExp() {
			return exp;
		}
		public void setExp(long exp) {
			this.exp = exp;
		}
		public long getNbf() {
			return nbf;
		}
		public void setNbf(long nbf) {
			this.nbf = nbf;
		}
		public long getIat() {
			return iat;
		}
		public void setIat(long iat) {
			this.iat = iat;
		}
		public String getJti() {
			return jti;
		}
		public void setJti(String jti) {
			this.jti = jti;
		}
		public long getGra() {
			return gra;
		}
		public void setGra(long gra) {
			this.gra = gra;
		}
		public String getTyp() {
			return typ;
		}
		public void setTyp(String typ) {
			this.typ = typ;
		}

		
	}

	public Head getHead() {
		return head;
	}
	public void setHead(Head head) {
		this.head = head;
	}
	public Playload getPlayload() {
		return playload;
	}
	public void setPlayload(Playload playload) {
		this.playload = playload;
	}
	public String getSignature() {
		return signature;
	}
	public void setSignature(String signature) {
		this.signature = signature;
	}
	public String getBase64Head() {
		return base64Head;
	}
	public void setBase64Head(String base64Head) {
		this.base64Head = base64Head;
	}
	public String getBase64PlayLoad() {
		return base64PlayLoad;
	}
	public void setBase64PlayLoad(String base64PlayLoad) {
		this.base64PlayLoad = base64PlayLoad;
	}
	public String getTokenStr() {
		return tokenStr;
	}
	public void setTokenStr(String tokenStr) {
		this.tokenStr = tokenStr;
	}
	
}



可以看到实体类里面包含了head payload signature这三部分。

然后用户登录成功之后创建token的代码如下:


public static Token createToken(String secret,String tokenId,TokenType tokenType,String userName) {
		try {
			Token token = new Token();
			//创建头
			Token.Head head = new Token.Head();
			head.setAlg("HS256");
			head.setTyp("JWT");
			
			//创建载荷
			//签发时间
			long iat = System.currentTimeMillis();
			//过期时间 20 分钟后过期
			long exp = iat + AuthConstants.TOKEN_EXP_TIME ;
			//最后存活时间
			long gra = iat + AuthConstants.TOKEN_GRA_TIME ;
			Token.Playload playload = new Token.Playload();
			playload.setAud("CLIENT"); //接收token的一方
			playload.setIat(iat); //签发时间
			playload.setExp(exp);
			playload.setGra(gra);
			playload.setIss("AUTH_CENTER");//签发者
			playload.setJti(tokenId); //token唯一身份标识
			playload.setNbf(iat);//生效时间,立即生效
			playload.setSub(userName); //token的所属者,可以存放用户名
			playload.setTyp(tokenType.toString().toUpperCase());
			
			//创建token
			String base64Head = Base64Util.encodeStr(JSONUtil.toJson(head) );
			String base64Playload = Base64Util.encodeStr(JSONUtil.toJson(playload) );
			String signature = HmacUtil.encryptHMACSHA256(base64Head+"."+base64Playload, secret); //token签名
			String tokenStr = base64Head+"."+base64Playload+"."+signature; //token字符串
			
			//组装token对象
			token.setHead(head);
			token.setPlayload(playload);
			token.setBase64Head(base64Head);
			token.setBase64PlayLoad(base64Playload);
			token.setSignature(signature);
			token.setTokenStr(tokenStr);
			return token;
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("生成token失败:{}",e.getMessage());
		}
		return null;
	}



创建成功之后,要把token放到响应头中,setHeader方法name参数要用Authorization,value值要使用

"Bearer "+token。

然后用户访问需要权限的接口都需要在请求头加上token,因为使用了Spring Cloud微服务架构,因此请求

会统一通过API网关访问,所以需要在网关处验证token的合法性,使用下面这个parseToken的方法:


/**
	 * 验证并解析token
	 * @param token token字符串
	 * @param secret token签名的盐(密钥)
	 * @return 成功返回token ,失败返回ull
	 */
	public static Token parseToken(String token,String secret) {
		try {
			//判断token是否是合法格式的token串
			if(StringUtils.isEmpty(token)) {
				throw new AuthException("token串为空!");
			}
			if(StringUtils.isEmpty(secret)) {
				throw new AuthException("解析token时,token密钥为空!");
			}
			String[] tokens = token.split("\.");
			if(tokens==null || tokens.length!=3) {
				throw new AuthException("非法格式的token串:"+token);
			}
			
			//token分解
			String base64Head = tokens[0].trim(); //token头
			String base64Playload = tokens[1].trim(); //token载荷
			String signature = tokens[2].trim(); //token签名
			//验证签名是否为合法的
			String signData = base64Head+"."+base64Playload;
			String signaturedStr = HmacUtil.encryptHMACSHA256(signData, secret.trim()); //token签名
			if(!signature.equals(signaturedStr)) {
				throw new AuthException("非法的token:解析token时,token验签失败!");
			}
			
			Token.Head head = JSONUtil.toBean(Base64Util.decodeStr(base64Head), Token.Head.class);
			Token.Playload playLoad = JSONUtil.toBean(Base64Util.decodeStr(base64Playload), Token.Playload.class);
			Token rs = new Token();
			rs.setHead(head);
			rs.setPlayload(playLoad);
			rs.setSignature(signature);
			return rs;
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("解析token失败:{}",e.getMessage());
			return null;
		}
	}



使用JWT进行身份验证的基本方法的实例就到这里,没有接触过JWT的同学可以先看一下JWT


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭