jwt java案例_JSON WEB TOKEN(JWT)详解以及JAVA项目实战

本文深入解析JWT(JSON Web Tokens)的工作原理,对比Cookie与Session的优缺点,阐述基于Token的身份验证方式。详细介绍JWT的结构、特点,并提供Java环境下使用JJWT库生成、验证和管理JWT的示例代码,帮助开发者理解和实现在Java项目中应用JWT。
摘要由CSDN通过智能技术生成

1.我们为什么要是用token

Token, 令牌,代表执行某些操作的权利,也就是我们进行某些操作的通行证。

1.1 在很久很久以前,我们使用什么做身份认证?

我们都知道 HTTP 是无状态(stateless)的协议:HTTP 对于事务处理没有记忆能力,不对请求和响应之间的通信状态进行保存。

使用 HTTP 协议,每当有新的请求发送时,就会有对应的新响应产生。协议本身并不保留之前一切的请求或响应报文的信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把 HTTP 协议设计成如此简单的。

可是,随着 Web 的发展,早期这种无状态的特性却带来了很多不方便性,比如说用户登录新浪微博,在登录页输入用户名、密码之后进入首页,但是由于 HTTP 是无状态的,HTTP 并不知道上一次的 HTTP 请求是否通过了验证,更无法得知当前用户的具体信息。

最简单的解决方案就是在所有的请求里面都带上用户名和密码,这样虽然可行,但是大大加重了服务器的负担(对于每个 request 都需要到数据库验证),而且用户也要每进入一个页面输入一次密码,毫无用户体验可言。

为此,引入了各种身份认证机制

1.1.1 Cookie & session

Cookie 是由 HTTP 服务器设置的,保存在浏览器中的小型文本文件,其内容为一系列的键值对

相对于保存在浏览器中的 Cookie,Session 是存储在服务器端的

Cookie 传递过程:浏览器向某个 URL 发送请求

对应的服务器收到该 HTTP 请求,生成要发给浏览器的 HTTP 响应

在响应头中加入 Set-Cookie 字段,值为要设置的的Cookie

浏览器收到来自服务器的 HTTP 响应

浏览器在响应头中发现了 Set-Cookie 字段,就会将该字段的值保存在内存或者是硬盘中。

当下一次向该服务器发送 HTTP 请求时,会将服务器设置的 Cookie 附加在 HTTP 请求的字段 Cookie 中。

服务器收到这个 HTTP 请求之后,发现请求头中有 Cookie 字段,就知道了已经处理过这个用户的请求了。

过期的 Cookie 会被删除

基于Cookie-session的认证过程用户输入登录信息

服务端验证登录信息是否正确,如果正确就在服务器端为这个用户创建一个 Session,并把 Session 存入数据库

服务器端会向客户端返回带有 sessionID 的 Cookie

客户端接收到服务器端发来的请求之后,看见响应头中的 Set-Cookie 字段,将 Cookie 保存起来

接下来的请求中都会带上这个 Cookie,服务器将 sessionID 和 数据库中的相匹配,如果有效则处理该请求

如果用户登出,Session 会在客户端和服务器端都被销毁

1.1.2 Cookie & session 的弊端由于Cookie 以及 session 需要存储在浏览器内存以及服务器内存中,请求增大时,资源消耗会很大

基于cookie做身份认证,若浏览器屏蔽cookie,则造成很麻烦,需要另辟蹊径,使用url重写等方式

对于分布式系统支持不好

cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

1.2 基于token的鉴权方式

token在服务器时可以不用存储用户信息的,token传递的方式也不限于cookie传递。

当用户第一次访问服务器时,服务端通过算法,加密钥,生成一个token。通过BASE64编码后将token发送给客户端。

客户端将token保存起来,下次请求带着token,服务器收到请求会用相同的算法取验证toekn,如果通过就继续执行。

此时服务器变成无状态了,从而比较容易实现扩展

session为会话,token为令牌。

token解决了session扩展性差的问题

2. JWT

2.1 JWT结构

一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名依顺序用点号(".")链接而成:1.header,2.payload,3.signature。Header(头部)

Payload(负载)

Signature(签名)

如下为一个 JWT字符串:eyJhbGciOiJIUzI1NiJ9.eyJleHBpcmVUaW1lIjoxNTg5MDE0MzA2OTU0LCJkZXB0Ijoi5Yas6KW_55Oc5ZywIiwidXNlcm5hbWUiOiLlpKfopb_nk5wifQ.QSv0FcvNheiA3FW6OEah7jJKG4SG0ver3q67F0980rY

2.1.1 Header(头部)eyJhbGciOiJIUzI1NiJ9

使用base64解密后得到:{"alg":"HS256"}

2.1.2 Payload(负载)

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用:、iss (issuer):签发人

exp (expiration time):过期时间

sub (subject):主题

aud (audience):受众

nbf (Not Before):生效时间

iat (Issued At):签发时间

jti (JWT ID):编号

也可以自定义 :username:大西瓜

JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。

2.1.3 Signature(签名)

Signature 部分是对前两部分的签名,防止数据篡改。

使用指定加密算法以及仅服务器可知的 密钥(secret)对前两部分进行加密。

2.1.4 拼接

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以生成完整的JWT token了

2.2 JWT 的几个特点JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

3. java中使用 JWT

本文使用 JJWT 来实现java环境 JWT 生成,解密操作

3.1 引入 JJWT maven依赖

目前最新版本 0.9.1

io.jsonwebtoken

jjwt

0.9.1

3.2 配置 keyprivate static final String SALT = "0142add7c2664198863943f24bf4b8b9";

private static Key getKeyInstance() {

SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

String apiKey = DatatypeConverter.printBase64Binary(SALT.getBytes());

byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(apiKey);

Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

return signingKey;

}

3.3 生成tokenpublic static String createJavaWebToken4JwtAuth(Map claims) {

logger.info("生成的token为开始");

String toekn = Jwts.builder().setClaims(claims).setExpiration(DateUtil.addSeconds(new Date(), 50))

.signWith(SignatureAlgorithm.HS256, getKeyInstance()).compact();

logger.info("生成的token为:" + toekn);

return toekn;

}

其中 官方Payload 中的属性都有对应api来配置,🌰中配置了 .setExpiration(DateUtil.addSeconds(new Date(), 50))

3.4 获取body部分public static Map verifyJavaWebToken(String jwt) {

try {

Map jwtClaims =

Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(jwt).getBody();

return jwtClaims;

} catch (Exception e) {

logger.info(e.getMessage());

return null;

}

}

当当前时间超过配置的过期时间时,会后抛出异常

3.5 校验有效性方法public static boolean isTokenEffect(String jwt) {

if (StringUtils.isEmpty(jwt)) {

return false;

}

Map claims = verifyJavaWebToken(jwt);

if (null == claims) {

logger.info("转换jwt失败!");

return false;

}

return true;

}

3.6 使用public static void main(String[] args) {

Map paramMap = new HashMap<>();

paramMap.put("username", "大西瓜");

paramMap.put("dept", "冬西瓜地");

String tokens = JwtUtil.createJavaWebToken4JwtAuth(paramMap);

System.out.println(tokens);

System.out.println(isTokenEffect(tokens));

}

本文JwtUtil 已提交github到我的工具集 ytooo-util

我的工具集包含 常用字符串处理、日期处理、http请求封装、文件处理、请求体封装等常用工具

欢迎使用

ml.ytooo

ytooo-util

3.6.5

更多好玩好看的内容,欢迎到我的博客交流,共同进步        WaterMin

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值