SpringCloud等微服务下登录校验解决方案JWT

一、JWT之前我们是怎么做的

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中校验是否有此用户即可,这种方式目前也有很多公司都在使用。但是这种方式不是最优的方案,这种方式需要每次都去redis里拿数据检验一下,在访问量大的时候,每次访问redis也是一种资源(比如网络资源和IO)的消耗,所以现在很多应用已经开始使用我们今天要讲的JWT

二、什么是JWT

1、JWT是一个开放标准,它定义了一种用于简洁,自包含的,用于通信双方之间以 JSON 对象的形式安全传递信息的方法。

JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名

简单来说,就是通过一定规范来生成token,然后可以通过解密算法逆向解密token,这样就可以获取用户信息

优点:

     1)生产的token可以包含基本信息,比如id、用户昵称、头像等信息,避免再次查库

     2)存储在客户端,不占用服务端的内存资源

缺点:token是经过base64编码,所以可以解码,因此token加密前的对象不应该包含敏感信息,如用户权限,密码等

2、JWT格式组成 头部、负载、签名

header+payload+signature

头部:主要是描述签名算法

负载:主要描述是加密对象的信息,如用户的id等,也可以加些规范里面的东西,如iss签发者,exp 过期时间,sub 面向的用户

签名:主要是把前面两部分进行加密,防止别人拿到token进行base解密后篡改token

3、关于jwt客户端存储

可以存储在cookie,localstorage和sessionStorage里面

三、JWT使用实战

1、加入相关依赖



	io.jsonwebtoken
	jjwt
	0.7.0


2、开发加密生成JWT的token方法和解密检验token方法

package com.cj.wx_pay.utils;

import com.cj.wx_pay.domain.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;

/**
 * jwt工具类
 */
public class JwtUtils {

    public static final String SUBJECT = "wx_pay";

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

    //秘钥
    public static final  String APPSECRET = "wx_pay666";

    /**
     * 生成jwt
     * @param user
     * @return
     */
    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,APPSECRET).compact();//对应签名,主要是把前面两部分进行加密
        return token;
    }

    /**
     * 解密校验token
     * @param token
     * @return
     */
    public static Claims checkJWT(String token ){
        try{
            final Claims claims =  Jwts.parser().setSigningKey(APPSECRET).parseClaimsJws(token).getBody();
            return  claims;
        }catch (Exception e){ }
        return null;
    }

}

3、测试验证

    @GetMapping("testGeneJwt")
	public JsonData testGeneJwt(){
		User user = new User();
		user.setId(666);
		user.setHeadImg("www.baidu.com/1.jpg");
		user.setName("zhangsan");
		String token = JwtUtils.geneJsonWebToken(user);
		return JsonData.buildSuccess(token);
	}

	@GetMapping("testCheck")
	public JsonData testCheck(@RequestParam("token") String token){
		Claims claims = JwtUtils.checkJWT(token);
		if(claims != null){
			String name = (String)claims.get("name");
			String img = (String)claims.get("img");
			int id =(Integer) claims.get("id");
			User user = new User();
			user.setId(id);
			user.setHeadImg(img);
			user.setName(name);
			return JsonData.buildSuccess(user);
		}else{
			return JsonData.buildError("非法token");
		}
	}

看下加密返回的结果

SpringCloud等微服务下登录校验解决方案JWT_第1张图片

把加密的token作为参数传进去,看下解密的结果

SpringCloud等微服务下登录校验解决方案JWT_第2张图片

可以看到已经解密成功了,我们再随便拿一个不是我们JWT生成的token串儿试一下,看是否能解密成功

SpringCloud等微服务下登录校验解决方案JWT_第3张图片

可以看到随便伪造的token提示非法token

以上就是对JWT的一些基本使用方法,有需要或者感兴趣的小伙伴可以试一下

你可能感兴趣的:(Java开发总结)