JWT的详细入门(都能看懂)

电商常见等用户信息校验等方法:

方案2:用户量大时,带宽等占用严重

1、单机tomcat应用登录检验
            sesssion保存在浏览器和应用服务器会话之间
            用户登录成功,服务端会保证一个session,当然会给客户端一个sessionId,
            客户端会把sessionId保存在cookie中,每次请求都会携带这个sessionId
​
2、分布式应用中session共享
            真实的应用不可能单节点部署,所以就有个多节点登录session共享的问题需要解决
            1)tomcat支持session共享,但是有广播风暴;用户量大的时候,占用资源就严重,不推荐
            2)使用redis存储token:
                    服务端使用UUID生成随机64位或者128位token,放入redis中,然后返回给客户端并存储在cookie中
                    用户每次访问都携带此token,服务端去redis中校验是否有此用户即可
​

Jwt技术解决上面等问题:

1、JWT 是一个开放标准,它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。
            JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名
​
            简单来说,就是通过一定规范来生成token,然后可以通过解密算法逆向解密token,这样就可以获取用户信息
            {
                id:888,
                name:'小D',
                expire:10000
            }
            
            funtion 加密(object, appsecret){
                xxxx
                return base64( token);
            }
​
            function 解密(token ,appsecret){
​
                xxxx
                //成功返回true,失败返回false
            }
​
            优点:
                1)生产的token可以包含基本信息,比如id、用户昵称、头像等信息,避免再次查库
​
                2)存储在客户端,不占用服务端的内存资源
​
            缺点:
                token是经过base64编码,所以可以解码,因此token加密前的对象不应该包含敏感信息
                如用户权限,密码等
​
2、JWT格式组成 头部、负载、签名
           header+payload+signature
​
           头部:主要是描述签名算法
           负载:主要描述是加密对象的信息,如用户的id等,也可以加些规范里面的东西,如iss签发者,exp 过期时间,sub 面向的用户
           签名:主要是把前面两部分进行加密,防止别人拿到token进行base解密后篡改token
​
3、关于jwt客户端存储
            可以存储在cookie,localstorage和sessionStorage里面
 
  1. 加入相关依赖
  2. 编写生成token
  3. 编写检验token

相关依赖

<!--jwt的依赖 -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.8.0</version>
</dependency>

public class JwtUtils {
    private static final String JWTSECRET = "myScrect";

    /*
    生成token的方法
     */
    public static String create(User user) {
        if (user == null || user.getId() == null || user.getUserName() == null) {
            return null;
        }
        String token = Jwts.builder()
                .setSubject(JWTSECRET)    //设置签名
                .claim("id", user.getId())        //设置传入的参数
                .claim("name", user.getUserName())
                .setIssuedAt(new Date())    //发行时间
                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 7)) //过期时间
                .signWith(SignatureAlgorithm.HS256, JWTSECRET)   //签名算法  ,密钥   ES256报错见下面
                .compact(); //压缩
        return token;


    }

    /**
     * 校验token
     *
     * @param token 传入的令牌
     * @return
     */
    public static Claims checkJWT(String token) {
        //通常如果伪造或token过期都会抛出异常所有包裹一下

        try {
            final Claims claims = Jwts.parser()
                    .setSigningKey(JWTSECRET)   //
                    .parseClaimsJws(token)
                    .getBody();           //可以得到签名getSignature getHeader头部
//        if (claims.get("id")==null)
            return claims;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

RS256 (采用SHA-256 的 RSA 签名) 是一种非对称算法, 它使用公共/私钥对: 标识提供方采用私钥生成签名, JWT 的使用方获取公钥以验证签名。由于公钥 (与私钥相比) 不需要保护, 因此大多数标识提供方使其易于使用方获取和使用 (通常通过一个元数据URL)。
另一方面, HS256 (带有 SHA-256 的 HMAC 是一种对称算法, 双方之间仅共享一个 密钥。由于使用相同的密钥生成签名和验证签名, 因此必须注意确保密钥不被泄密。

在开发应用的时候启用JWT,使用RS256更加安全,你可以控制谁能使用什么类型的密钥。另外,如果你无法控制客户端,无法做到密钥的完全保密,RS256会是个更佳的选择,JWT的使用方只需要知道公钥。

测试

@Test
public void TestJWT(){
    User user = new User();
    user.setId(1);
    user.setUserName("xijie");
    String token = JwtUtils.create(user);
    System.out.println(token);

}

开始报错 

java.lang.IllegalArgumentException: Base64-encoded key bytes may only be specified for HMAC signatures.  If using RSA or Elliptic Curve, use the signWith(SignatureAlgorithm, Key) method instead.

将ES256改为HS256 加密算法

 拿到token生成token成功

@Test
public void TestCheck(){
    String token="eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJteVNjcmVjdCIsImlkIjoxLCJuYW1lIjoieGlqaWUiLCJpYXQiOjE1NTA3MjAxMTcsImV4cCI6MTU1MTMyNDkxN30.ovDf7015iSwMHlBVk0D8FQXhVTNVuZOSrs4dKXZMKSw";

    Claims claims = JwtUtils.checkJWT(token);
    System.out.println(""+claims);
    if (claims!=null){
        Integer id = (Integer) claims.get("id");
        String name = (String) claims.get("name");
        System.out.println(id+name);
    }

}

测试Ok

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智达教育‍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值