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

浅析JWT| JWT是啥子,Java构建JWT 小声bbb 说到系统的安全识别,记得自己第一个项目,用的就是session,用户登录进来以后,给他session标记登录,记录id进去,轻轻松松,设计的操作也很简单,类似操作HashMap。 这大概也有1年多快两年了,现在回头看真的是可怕,几乎在裸奔 众所周知,平常使用的Session是存储在服务器的一种技术,可以理解为一个会话id,每次使用HTTP请求,都会携带一个sessionId,服务器根据这个SessionId去找对应的session しかし,我预判了你的预判 第三方完全可以随便输入一个sess 阅读详情

JWT是啥

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

为什么要用这个东西

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

它能干点啥

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

正题开始—怎么玩

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

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

}

除了上面那个大哥 下面基本就没啥问题了、
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;
    }

}

然后是最重要的部分 生成解密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);
    }

}

下面是一些会用到的其他类 一起提供了 使用时请注意。。。
/**
 * @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 + '\'' +
                '}';
    }
}

到此为止 所谓的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;

}


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

Java中JWT技术解析与实践:安全高效的身份认证 身份认证与授权是现代Web应用中至关重要的安全机制。JSON Web Token(JWT)作为一种轻量级的身份验证方案,已经成为Java开发中广泛使用的解决方案。本篇博客将深入解析JWT技术,探讨其在Java应用中的实践与应用。我们将了解JWT的基本原理,以及它如何实现安全高效的身份认证和授权。通过使用JWT,我们可以在无状态的分布式系统中实现简单且可扩展的用户身份验证,不再依赖传统的Session和Cookie。我们还将探讨如何在Java中集成JWT,以及如何将其应用于实际项目中。让我们一起深入探索JWT 阅读详情

相关推荐

Java实现JWT认证的完整指南:如何从零开始构建安全认证系统

JWT是一种基于JSON的开放标准,用于在各方之间作为JSON对象安全地传输信息。它特别适合于在无状态环境中(如RESTful API)进行身份验证和信息交换。通过以上步骤,我们成功地在Java中实现了基于JWT的身份认证系统。这个系统具有高度的安全性和扩展性,适用于各种需要身份认证的应用场景。希望这篇文章对大家有所帮助,如果你觉得这篇文章对你有所帮助,欢迎关注我的博客。未来,我会继续分享更多关于Java开发的干货。让我们一起在技术的道路上不断探索,勇往直前!

weixin_46372265的博客 1702

Java - JWT的简单介绍和使用

目前自己在做一个云直播个人项目,后端架构是微服务,目前准备用JWT来做Token的校验。借此机会来复习和学习一遍JWT的相关知识。

Zong_0915的博客 1万+

Java使用JWT实现Token认证机制

JWT(JSON Web Token)是一种用于在网络上安全地传输信息的简洁的、URL 安全的表示方法,它定义了一个紧凑且自包含的方式,用于不同实体之间安全地传输信息(JSON格式)。JWT 通常由三部分组成,分别是 Header(头部)、Payload(有效载荷)和 Signature(签名)。JWT是一种简单、安全、便捷的身份验证和授权机制,在现代Web应用程序中得到广泛应用。然而,在使用JWT时也需要注意其安全性问题,并采取相应的措施来确保JWT的安全性和完整性。

pan_junbiao的博客 2724

Java使用JWT

JWT 一、简介 1、JWT JWT为 Json Web Token,是一种令牌生成算法。使用JWT能够保证Token的安全性,且能够进行Token时效性的检验。 2、JWT结构 JWT共由三部分组成,分别是数据头(Header)、Payload(数据体)、验证签名(Verify Signature)组成。其中,Header中的内容为加密信息以及Token的类别,Payload为用户数据、Verify Signature为校验数据。 二、依赖 JWT需要两个依赖java-jwt、jjwt <depe

cxmengxin的博客 1万+

整合SpringSecurity和JWT实现登录认证和授权

文章目录前言一、SpringSecurity是什么?二、JWT是什么?1. JWT的组成2. JWT实现认证和授权的原理三、整合步骤1. 引入相关依赖2. yml配置中加入jwt配置信息3. 添加JWT token的工具类4. 添加SpringSecurity的配置类5. 添加自定义结果处理类5.1 添加CustomAccessDeniedHandler5.2 添加CustomAuthenticationEntryPoint6. 添加JwtUser类7. 添加过滤器JwtAuthenticationTok

Java升级之路的博客 5178

[JWT][JAVA]JSON Web Tokens的简单使用(java-jwt)

概括来说,JWT是一种符合RFC 7519工业体系设计的、基于JSON对象的、利用RSA等算法签发的Token框架/标准。

身披白袍的博客 3686

Java实现JWT的Token认证机制

基于JWT的Token认证机制实现 1.什么是JWT JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。 2.JWT组成 一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签证 头部(Header) 头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以 被表示成一个JSON对象。 {"t...

Dreamer. 1万+

JWT(json web token)认证实现【Playload 存储自定义对象】

会将空转为字符串“null”生成jwt:sign(

专注于计算机研发知识和资讯分享 1798

java jwt登录_JWT实现登录认证实例

JWT全称JSON Web Token,是一个紧凑的,自包含的,安全的信息交换协议。JWT有很多方面的应用,例如权限认证,信息交换等。本文将简单介绍JWT登录权限认证的一个实例操作。JWT组成JWT由头部(Header),负载(Payload)和签名(Signature)三部分组成。其中头部包含了JWT的声明信息,例如签名所用的算法等。{"alg": "HS256","typ": "JWT"}负载...

weixin_36413546的博客 2168

Java JWT实现与应用详解

本文还有配套的精品资源,点击获取 简介:JWT是一种安全的、紧凑的、自包含的信息传输标准,适用于Java和Android的身份验证和授权。本文深入解析了JWT的组成部分,包括头部、负载和签名,并通过 jjwt 开源库展示如何在Java中创建、解析和验证JWT。重点介绍了JWT在Java和Android中的具体实现,以及开发者应如何利用这些技术构建安全的应用程序...

weixin_42593549的博客 2924

ZYNQ出现问题及解决办法汇总(一直更新)

问题目录使用软件及开发板版本一,vitis在build project时卡住。二,Could not find FPGA device on the board for connection 'Local'三,FPGA configuration failed:DONE PIN is not high四,Could not find ARM device on the board for connection 'Local' 使用软件及开发板版本 开发板:MZ7XA-7020 软件:vitis2020.2(

qq_45057368的博客 1万+

jwt原理及Java中实现

JWT(JSON Web Token)是一种用于无状态认证的开放标准,通过签名机制将认证信息打包成自包含的字符串。它由Header、Payload和Signature三部分组成,支持自定义字段,适用于分布式系统。JWT解决了传统会话管理的状态维护问题,但需注意安全风险,如设置过期时间、避免密钥泄露等。常见陷阱包括不校验关键声明、存储不当等。Java中可使用JJWT库实现JWT的创建与验证,Spring Boot则通过OAuth2资源服务器简化校验流程。JWT适用于无状态场景,但敏感信息需加密处理。

qq_74049173的博客 1437

U8采购入库单CO接口开发实战:加载、新增与删除操作详解

本文详细解析了用友U8采购入库单CO接口的开发实战,重点介绍了加载、新增与删除三大核心操作的实现方法。通过C#代码示例和实际项目经验,帮助开发者高效处理采购入库单,提升企业供应链管理效率。文章还涵盖了环境配置、异常处理、性能优化等关键技巧,适合U8二次开发人员参考。

weixin_33462927的博客 372

JAVA实现JWT

JWT介绍 详情访问官网https://jwt.io/ JWT是什么 JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。此信息可以验证和信任,因为它是经过数字签名的。JWT可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。 虽然 JWT 可以被加密以在各方之间提供保密性,但我们将重点关注签名令牌。签名令牌可以验证其中包含的声明的完整性,而加密令牌会对其他方隐藏这些声

l_learning的博客 2070

ISP——坏点矫正(Defective Pixel Correction,DPC)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录一、出现原因二、坏点分类三、矫正方法动态矫正1.PINTO算法2.梯度法3.DPC和demosaic结合法4.行检测法 一、出现原因 1.感光元件芯片自身工艺技术瑕疵造成以及长期使用造成的瑕疵; 2.光线采集存在缺陷; 二、坏点分类 1.hot pixel: 固定保持较高的像素值,一般呈现为画面高亮的点; 2.dead pixel: 固定保持较低的像素值,一般在画面中呈现为暗点; 3.noise pixel:信号强度随光照呈现的.

qq_41939460的博客 9421

Cadence SpectreRF仿真避坑指南:PSS和Pnoise设置详解(附实战案例)

本文详细解析了Cadence SpectreRF中PSS(周期稳态分析)和Pnoise(周期噪声分析)的关键设置技巧,帮助模拟IC设计工程师避开常见仿真陷阱。通过实战案例分享,涵盖引擎选择、Beat Frequency计算、噪声类型配置等核心参数优化策略,提升仿真精度与效率。特别针对开关电容电路和振荡器等复杂场景提供专业解决方案。

weixin_42613501的博客 601

Java手动生成JWT

头部 首先我们需要一个Json { "alg":"HS256" } 接着我们需要将其在Java中展示出来 String header = "{\n" + "\t\"alg\":\"HS256\"\n" + "}"; 之后要去除所有空格 String header = "{"alg":"HS256"}"; 报错了,很明显是有问题的,接着用转义字符将“正常展示出来 String header

孤星的博客 1160

PYTHON 打印三角形大全

用PYTHON语言打印各种三角形

世上无难事,只要肯攀登 1万+

JAVA 实现 JWT

引入JWT依赖,由于是基于Java,所以需要的是java-jwt <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency> 自定义注解用于判断是否需要验证 用来跳过验证的PassToken @.

weixin_43966635的博客 2537

利用Arcgis发布wmts服务

使用发布 GIS 服务连接连接到 ArcGIS Server 站点后,可以将各种 GIS 资源(如地图文档、数据库以及服务定义)发布到服务器上。此外,还可以添加、删除、启动和停止服务。使用管理 GIS 服务器连接到 ArcGIS Server 站点后,可以编辑各种服务器属性,例如配置存储位置、集群配置、参与到该站点中的计算机列表以及管理站点的数据存储。通过使用 GIS 服务连接建立连接后,可以查看并使用发布到该站点的服务。但不能编辑服务器或服务属性、发布服务,也不能添加、删除、启动、停止或暂停服务。

ghgfsasxda的博客 2392

kaggle学习笔记-餐厅数据挖掘

分析Zomato数据集的基本思想是为了公平地了解影响在班加罗尔不同地方建立不同类型餐厅的因素,每个餐厅的总评级,班加罗尔是这样一个城市,拥有超过12,000家餐厅,餐厅供应来自世界各地的菜肴。每天都有新的餐馆开业,这个行业还没有饱和,需求也在与日俱增。然而,尽管需求不断增加,新餐馆却很难与老牌餐馆竞争。大多数餐厅都供应同样的食物。班加罗尔是印度的IT之都。这里的大多数人主要依靠餐馆的食物,因为他们没有时间自己做饭。由于对餐馆的需求如此巨大,因此研究一个地方的人口统计学就变得很重要。

优快云XXCQ的博客 1861

java实现基于JWT的token认证

java实现基于JWT的token认证1.引入依赖2.创建JWT工具类3.创建JWT注解类4.创建用于JWT验证的拦截器5.在SpringMVC.xml中配置拦截器7. 1.引入依赖 <!--引入JWT依赖,由于是基于Java,所以需要的是java-jwt--> <dependency> <groupId>io.jsonwebtoken&lt...

淮右布衣的博客 2150

【AI应用实战-Codex】Mac intel芯片下安装Codex(二)

摘要:本文介绍了在Intel芯片Mac上安装OpenAI Codex桌面应用时遇到的问题及解决方法。由于官方仅提供ARM64版本,导致Intel Mac无法直接运行。解决方案包括:1)使用社区脚本将ARM版DMG与x64 Electron重新打包成兼容版本;2)使用VSCode插件配合CLI作为替代方案。文章详细记录了重新打包过程中遇到的"electron_common_owl_features"绑定缺失错误,通过注入stub代码、重算ASAR完整性哈希等步骤成功解决问题。最终生成的Co

3510

SpringSecurity和JWT实现认证和授权

整合SpringSecurity和JWT实现认证和授权

OlderSheep编程达人 2347

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

JWT Token的Java实现

官网地址:https://jwt.io/ jwt github:https://github.com/jwtk/jjwt Demo源码地址: https://github.com/wangcantian/SecurityCommDemo JWT Jar 包下载:http://pan.baidu.com/s/1pLqJYUv 下面按照这几个方面来介绍它: Java 基本实现 开源库 jjwt 的使用 源码解析 jjwt 废话不多说,撸起袖子就是干,上代码 Java 实现 private

lzf的博客 1539

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: 20201122---整理面试问题
下一篇: Java实现登录与注销--JWT(2)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值