当前位置:   article > 正文

java手动实现JWT(我和别人的不一样)_java jwt实现

java jwt实现

JWT是啥

我不会官方语言,我只会最简单的解释 json web token
  • 1

为什么要用这个东西

简单点说 现在都流行前后端分离开发,如果需要一个前后端的通讯验证,最简单的cookie+session可以完成这个任务。但是会有问题昂,万一给你浏览cookie器禁了咋整,现在的用户才是老大哥不是,所以呢 就出现这个东西了
  • 1

它能干点啥

网上一搜一大片最多的就是。单点登录 + jwt。但是这两个东西不是一定要混为一谈的。jwt是jwt 简单点 他就是提供了一点token验证的方式,而不是一定要去作单点登录。(一开始我也混为一谈了,俺们领导天天跟我强调他俩不是一回事)
  • 1

正题开始—怎么玩

序篇:
最烦唠叨一大片没有实际应用的烦不烦,最开始还要强调一个问题,本文不是用的第三方 java-jwt 或者 jjwt 我们是完全自己实现的。和大众定义的jwt格式没啥太大关系。我们只是借鉴一下思想(因为领导说自己写加密方式比较安全)
正文开始:
我们查一下文档他说 jwt分为三段用 “.” 连接
  • 1
  • 2
  • 3
  • 4
第一段:
    第一段是个json。很简单很简单,就是告诉大家,我们在用jwt,也可以告诉他你用什么方式加密的 但是我并不想告诉他 哈哈哈 
  • 1
第二段 payload
 第二段是我们传输的实际业务内容,比如用户名呐,id呐。 所以可以定一个javaBean
  • 1
第三段
这一段是作为安全性验证最关键的一步,将前两段内容拼接后拿过来,进行加密。
  • 1
代码开始
 我们先准备一点工具类,准备啥呢,我们准备用Aes进行第三种的加密,
 当然还要准备base64工具类,不可能用字节数组来回的传输。这里用到的东西以jdk1.8为准。都是自带的 不需要导入任何第三方依赖

 首先是AesUtil  这里有个坑要注意哦
 网上搜的大多数aes加密工具类 会有问题,
 第一个问题:详情请搜索Aes自动补全机制,如果你不改 在windows环境没问题,
 linux环境加解密的补全机制不一样,解密时就会报错。报错是啥我没记 记住有这个问题就好 具体改动下面注释有
 第二个问题:aes 处理前后是有byte数组存在的,正常情况下我们是直接
 new  String(byte[] b).  String s.getBytes()这样的。但是这样会有问题,由于这个串长度 巴拉巴拉 的问题,前后会不一样,所以用base64进行处理。或者用 16--2 进制处理,我下面都提供了 自己看着来
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;

/**
 * @author chunying
 * @Date 2020.12.02
 * @Description 用于Aes加解密的工具类
 */

public class AesUtil {

    private static final Logger LOG = LoggerFactory.getLogger(AesUtil.class);

    /**
     * AES加密
     * @param value
     * @param key
     * @return
     */
    public static byte[] encrypt(String value, String key) {
        try {
         //等等等 就是这里了 这里要告诉key生成器 我们用的是sun提供的加密。解密同理 如果不服气 你不用一个试试 
            Security.addProvider(new sun.security.provider.Sun());
            KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者

            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG",new sun.security.provider.Sun());
            secureRandom.setSeed(key.getBytes());
            kgen.init(128, secureRandom);

            //加密没关系,SecureRandom是生成安全随机数序列,key.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行
            SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥
            byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回
            SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            byte[] byteContent = value.getBytes("utf-8");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);// 初始化为加密模式的密码器
            byte[] result = cipher.doFinal(byteContent);// 加密
            return result;
        } catch (NoSuchPaddingException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (BadPaddingException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES解密 参数是二进制数组 + key
     * @param value
     * @param key
     * @return
     */
    public static byte[] desCrypt(byte[] value, String key) {
        try {
            Security.addProvider(new sun.security.provider.Sun());
            KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
//            kgen.init(128, new SecureRandom(key.getBytes()));

            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", new sun.security.provider.Sun());
            secureRandom.setSeed(key.getBytes());
            kgen.init(128, secureRandom);

            SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥
            byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
            SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);// 初始化为解密模式的密码器
            byte[] result = cipher.doFinal(value);
            return result; // 明文
        } catch (NoSuchAlgorithmException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (BadPaddingException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 将二进制密文转再次换成可识别字符串 返回的是16进制
     * @param value
     * @return
     */
    public static String parseEncrypt(String value, String key) {
        byte[] encrypt = encrypt(value, key);
//        String s = ParseSystemUtil.parseByte2HexStr(encrypt);
        String s = Base64Util.byte2Base64StringFun(encrypt);
        return s;
    }

    /**
     * 返回解密后的内容
     * @param value
     * @param key
     * @return
     */
    public static String parseDesEncrypt(String value, String key) {
//        byte[] bytes = ParseSystemUtil.parseHexStr2Byte(value);
        byte[] bytes = Base64Util.base64String2ByteFun(value);
        try {
            return new String(desCrypt(bytes, key), "utf-8");
        } catch (UnsupportedEncodingException e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        }
        return null;
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
除了上面那个大哥 下面基本就没啥问题了、
import java.io.UnsupportedEncodingException;
import java.util.Base64;

/**
 * @author wangchunying
 * @Date 2020.12.06
 * @Description base工具类
 */

public class Base64Util {

    //转码 参数:值,编码格式
    public static String getEncodeStr(String value, String format) throws UnsupportedEncodingException{
        return Base64.getEncoder().encodeToString(value.getBytes(format));
    }

    //解码 参数:值,编码格式
    public static String getDecodeStr(String value, String format) throws UnsupportedEncodingException {
        return new String(Base64.getDecoder().decode(value), format);
    }

    //base64字符串转byte[]
    public static byte[] base64String2ByteFun(String base64Str){
        return Base64.getDecoder().decode(base64Str);
    }
    //byte[]转base64
    public static String byte2Base64StringFun(byte[] b){
        return Base64.getEncoder().encodeToString(b);
    }

}



/**
 * @author wangchunying
 * @Date 2020.12.02
 * @Description 目前有进制转换
 */

public class ParseSystemUtil {

    /**将二进制转换成16进制
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**将16进制转换为二进制
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
然后是最重要的部分 生成解密token部分
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpSession;

/**
 * @author wangchunying
 * @Date 2020.12.06
 * @Description 关于jwt的操作
 */

public class JwtTokenUtil {

    private static final Logger LOG = LoggerFactory.getLogger(JwtTokenUtil.class);

    //token header
    public static final String AUTH_HEADER_KEY = "Authorization";
    //一周过期时间
    private static final Long expireTime = 1000L*60*60*24*7;
    private static final String TYPE_KEY = "typ";
    private static final String TYPE_VALUE = "jwt";
    private static final String SPOT = ".";
    private static final String FORMAT = "utf-8";
    private static final String SESSION_KEY = "token";
    //加密key
    private static final String KEY = "q3t6w9z$C&F)J@NcQfTjWnZr4u7x";
    //token前缀
    private static final String TOKEN_PREFIX = "ssoToken";

    /**
     * 生成token 以用户基本信息为payload基础生成token 这样解析出来知道是哪个用户
     */
    public static String createToken(UserToken userToken)throws Exception {
        StringBuffer sbResult = new StringBuffer();
        JSONObject jwtFirstJson = new JSONObject();
        String jwtSecondStr = Base64Util.getEncodeStr(JSON.toJSONString(userToken), FORMAT);
        //拼接jwt格式
        jwtFirstJson.put(TYPE_KEY, TYPE_VALUE);
        String jwtFirstStr = Base64Util.getEncodeStr(JSON.toJSONString(jwtFirstJson), FORMAT);
        sbResult.append(jwtFirstStr).append(SPOT).append(jwtSecondStr);
        String hexString = AesUtil.parseEncrypt(sbResult.toString(), KEY);
        //设置过期时间
        refreshExpireTime(userToken);
//        String jwtString = TOKEN_PREFIX + JWT.create()
//                .withSubject(jsonString)
//                .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
//                .sign(AesUtil.parseEncrypt(jsonString, KEY));

        return sbResult.append(SPOT).append(hexString).toString();
    }

    //解析返回的token
    public static UserToken verifyToken(String value) {
        if (StringUtils.isBlank(value)) {
            throw new JwtException(JwtException.JwtErrorCodeEnum.FORMAT, "token is null");
        }
        String[] valueArray = value.split("\\.");
        if (valueArray.length < 3) {
            throw new JwtException(JwtException.JwtErrorCodeEnum.FORMAT, "token des format is error", valueArray);
        }
        String thirdStr = AesUtil.parseDesEncrypt(valueArray[2], KEY);
        //校验是否是真实用户?暂定先返回传过来的信息
        if (StringUtils.isBlank(thirdStr)) {
            throw new JwtException(JwtException.JwtErrorCodeEnum.FORMAT, "token des is error");
        }
        String[] thirdDesStr = thirdStr.split("\\.");
        if (thirdDesStr == null || thirdDesStr.length < 2) {
            throw new JwtException(JwtException.JwtErrorCodeEnum.CONTENT, "token des format is error", thirdDesStr);
        }
        //校验是否符合格式
        try {
            //检验payload 与 header 是否被动过
            if (!valueArray[0].equals(thirdDesStr[0]) || !valueArray[1].equals(thirdDesStr[1])) {
                throw new JwtException(JwtException.JwtErrorCodeEnum.MODIFIED, "token data is modified by smo");
            }
            //first str
            String firstStr = Base64Util.getDecodeStr(thirdDesStr[0], FORMAT);
            JSONObject jsonObject = JSON.parseObject(firstStr);
            String typeValue = jsonObject.getString(TYPE_KEY);
            if (!StringUtils.isNotBlank(typeValue) || !typeValue.equals(TYPE_VALUE)) {
                throw new JwtException(JwtException.JwtErrorCodeEnum.CONTENT, "token first format is error", typeValue);
            }
            //second str
            String secondStr = Base64Util.getDecodeStr(thirdDesStr[1], FORMAT);
            UserToken userToken = JSON.parseObject(secondStr, UserToken.class);
            if (isExpire(userToken)) {
                throw new JwtException(JwtException.JwtErrorCodeEnum.EXPIRE, "token is expire");
            }
            return userToken;
        }catch(Exception e) {
            LOG.error(e.getMessage(), e);
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 判断用户token是否过期
     * @param userToken
     * @return
     */
    public static Boolean isExpire(UserToken userToken) {
        Long currentTime = System.currentTimeMillis();
        return userToken.getExpireTime() <= currentTime;
    }

    /**
     * 刷新token生效时间
     * @param usertoken
     */
    public static void refreshExpireTime(UserToken usertoken) {
        Long time = System.currentTimeMillis() + expireTime;
        usertoken.setExpireTime(time);
    }

    /**
     * 将token放入session 可以知道当前会话用户信息
     * @param userToken
     */
    public static void setLocalUser(HttpSession session, UserToken userToken) {
        session.setAttribute(SESSION_KEY, userToken);
    }

    /**
     * 获取当前会话的用户token信息
     * @return
     */
    public static UserToken getUserToken(HttpSession session) {
        return (UserToken)session.getAttribute(SESSION_KEY);
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
下面是一些会用到的其他类 一起提供了 使用时请注意。。。
/**
 * @author wangchunying
 * @Date 2020.12.06
 */
public class JwtException extends RuntimeException{

    private JwtErrorCodeEnum code;
    private String message;
    private Object data;

    public JwtException(){
        super();
    }

    public JwtException(JwtErrorCodeEnum code, String messgae) {
        this.code = code;
        this.message = messgae;
    }

    public JwtException(JwtErrorCodeEnum code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public JwtErrorCodeEnum getCode() {
        return code;
    }

    public void setCode(JwtErrorCodeEnum code) {
        this.code = code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return "JwtException{" +
                "code=" + code +
                ", message='" + message + '\'' +
                ", data=" + data +
                '}';
    }

    /**
     * sso code enum
     */
    public enum JwtErrorCodeEnum {
        //解析格式错误
        FORMAT(30001),
        //内容错误
        CONTENT(30002),
        //内容前后不一致 确认被修改过
        MODIFIED(30003),
        //过期
        EXPIRE(30004),
        //其他错误
        OTHER(-10);

        Integer code;
        JwtErrorCodeEnum(Integer code){
            this.code = code;
        }

        public Integer getCode() {
            return code;
        }

        @Override
        public String toString() {
            return "JwtErrorCodeEnum{" +
                    "code=" + code +
                    '}';
        }
    }
}


public class SsoException extends RuntimeException{

    private Integer code;
    private String message;

    public SsoException(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return "SsoException{" +
                "code=" + code +
                ", message='" + message + '\'' +
                '}';
    }
}



import java.io.Serializable;

/**
 * @author wangchunying
 * @Date 2020.12.02
 * @Description
 */
public class UserToken implements Serializable {

    private static final long serialVersionUID = 1619189980427628544L;
    private Integer userID;
    private String userName;
    //过期时间
    private Long expireTime;

    public Long getExpireTime() {
        return expireTime;
    }

    public void setExpireTime(Long expireTime) {
        this.expireTime = expireTime;
    }

    public Integer getUserID() {
        return userID;
    }

    public void setUserID(Integer userID) {
        this.userID = userID;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Override
    public String toString() {
        return "UserToken{" +
                "userID=" + userID +
                ", userName='" + userName + '\'' +
                ", expireTime='" + expireTime + '\'' +
                '}';
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
到此为止 所谓的jwt部分已经结束了,下面是如果你想用jwt作为共有接口拦截应该怎么做。是基于springboot来说的
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * @author wangchunying
 * @Date 2020.12.07
 * @Descrip 全局方法拦截 若方法不想使用此拦截器 请看JwtIgnore
 */
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //从http请求头中取出token
        //如果本地测试嫌麻烦可以把下面三行注释打开 切记别提交
//        if (1==1) {
//            return true;
//        }
        final String token = request.getHeader(JwtTokenUtil.AUTH_HEADER_KEY);
        //如果不是映射到方法,直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        //如果是方法探测,直接通过
        if (HttpMethod.OPTIONS.equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        //如果方法有JwtIgnore注解,直接通过
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(JwtIgnore.class)) {
            JwtIgnore jwtIgnore = method.getAnnotation(JwtIgnore.class);
            if (jwtIgnore.value()) {
                return true;
            }
        }
        //若测试接口 可以注释 打开token
//        if (StringUtils.isBlank(token)) {
//            throw new SsoException(901, "token is null, please check again");
//        }

        //验证,并获取token内部信息
        UserToken userToken = JwtTokenUtil.verifyToken(token);
        //将token放入本地缓存
        JwtTokenUtil.setLocalUser(request.getSession(), userToken);
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //方法结束后,移除缓存的token
//        JwtTokenUtil.removeUserToken();
    }
}



import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author wangchunying
 * @Date 2020.12.07
 * @Descrip 跨域配置
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

//    /**
//     * 重写父类提供的跨域请求处理的接口
//     */
//    @Override
//    public void addCorsMappings(CorsRegistry registry) {
//        // 添加映射路径
//        registry.addMapping("/**")
//                // 放行哪些原始域
//                .allowedOrigins("*")
//                // 是否发送Cookie信息
//                .allowCredentials(true)
//                // 放行哪些原始域(请求方式)
//                .allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS", "HEAD")
//                // 放行哪些原始域(头部信息)
//                .allowedHeaders("*")
//                // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
//                .exposedHeaders("Server","Content-Length", "Authorization", "Access-Token", "Access-Control-Allow-Origin","Access-Control-Allow-Credentials");
//    }


    /**
     * 添加拦截器。如果你想在拦截器里面注入其他类。请交给spring管理 如不会 可问我 或自行查询
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加权限拦截器
        registry.addInterceptor(new AuthenticationInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**");
    }

}
这里我不想启动跨域 所以注销掉了

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author wangchunying
 * @Date 2020.12.07
 * @Description: 如果你不想token 介入方法 请添加此注解
 */

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface JwtIgnore {

    boolean value() default true;

}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131

到此为止 jwt已经写完了,后面我会陆续更新息息相关的登录~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/544466
推荐阅读
相关标签
  

闽ICP备14008679号