SpringBoot 2.x 使用 JWT(JSON Web T

2019-09-28  本文已影响0人  RookieMZL
一、跨域认证遇到的问题

由于多终端的出现,很多的站点通过 web api restful 的形式对外提供服务,采用了前后端分离模式进行开发,因而在身份验证的方式上可能与传统的基于 cookieSession Id 的做法有所不同,除了面临跨域提交 cookie 的问题外,更重要的是,有些终端可能根本不支持 cookie

JWT(JSON Web Token) 是一种身份验证及授权方案,简单的说就是调用端调用 api 时,附带上一个由 api 端颁发的 token,以此来验证调用者的授权信息。

一般流程是下面这样:

  1. 用户向服务器发送用户名和密码。
  2. 服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。
  3. 服务器向用户返回一个 session_id,写入用户的 Cookie。
  4. 用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。
  5. 服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

这种模式的问题在于扩展性不好。单机没有问题,如果是服务器集群、跨域的服务导向架构或者用户禁用了 cookie ,就不行了。

二、解决方案

1. 单机和分布式应用下登录校验,session 共享

2. 最终解决方案:使用 JWT 实现 Token 认证

3. 案例图设计

2.png

三、代码演示案例

<!-- 依赖可以减少实体类 getter/setter等方法书写 -->
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <optional>true</optional>
</dependency>
<!-- JWT相关 -->
<dependency>
   <groupId>io.jsonwebtoken</groupId>
   <artifactId>jjwt</artifactId>
   <version>0.7.0</version>
</dependency>

=========================================================

@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {

    private Integer id;
    private String openid;
    private String name;
    private String headImg;
    private String phone;
    private String sign;
    private Integer sex;
    private String city;
    private Date createTime;

}
public class JwtUtil {

    // 主题
    public static final String SUBJECT = "RookieLi";

    // 秘钥
    public static final String SECRETKEY = "Rookie666";

    // 过期时间
    public static final long EXPIRE = 1000 * 60 * 60 * 24 * 7;  //过期时间,毫秒,一周

    // 生成 JWT
    public static String geneJsonWebToken(User user) {

        if (user == null ||
                user.getId() == null ||
                user.getName() == null ||
                user.getHeadImg() == null) {

            return null;
        }
        String token = Jwts.builder()
                .setSubject(SUBJECT)
                .claim("id", user.getId())
                .claim("name", user.getName())
                .claim("img", user.getHeadImg())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                .signWith(SignatureAlgorithm.HS256, SECRETKEY).compact();

        return token;
    }


    // 校验 JWT
    public static Claims checkJWT(String token) {

        try {
            final Claims claims = Jwts.parser().setSigningKey(SECRETKEY).
                    parseClaimsJws(token).getBody();
            return claims;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
public class JwtUtilTest {

    @Test
    public void testGeneJwt(){
    
        User user = new User();
        user.setId(999);
        user.setHeadImg("I'm busy");
        user.setName("Rookie");
        String token = JwtUtil.geneJsonWebToken(user);
        System.out.println(token);

    }


    @Test
    public void testCheck(){

        // 下面此 token 字符串是上面的结果生成的,每次不一样,不是写死的
        String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJSb29raWVMaSIsImlkIjo5OTksIm5hbWUiOiJSb29raWUiLCJpbWciOiJJJ20gYnVzeSIsImlhdCI6MTU2NzMxNjk4NywiZXhwIjoxNTY3OTIxNzg3fQ.FJh41VwVh2gh5-_cOG0SOgoO3dR_ZcK9VWNNskWqKl0";
        Claims claims = JwtUtil.checkJWT(token);
        if(claims != null){
            String name = (String)claims.get("name");
            String img = (String)claims.get("img");
            int id =(Integer) claims.get("id");
            System.out.println(name);
            System.out.println(img);
            System.out.println(id);
        }else{
            System.out.println("非法token");
        }
    }
}

参考博客:
http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
https://www.cnblogs.com/jpfss/p/10929458.html

上一篇 下一篇

猜你喜欢

热点阅读