1.pom.xml引入依赖

<!-- token -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.3.0</version>
</dependency>

2.JWTUtil工具类

package com.zm.common.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

public class JWTUtil {
    
    public static final String TOKEN_HEADER = "token";
    /**
     *过期时间
     */
    private static final Integer EXPIRE_TIME = 5;
    /**
     *用于加密的密钥
     */
    private static final String SECRET = "132#3dsh#gah2@#$%SDS*$SDA&SD";
    /**
     * 生成token
     **/
    public static String createToken(Map<String, String> map) throws UnsupportedEncodingException {
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.MINUTE, EXPIRE_TIME);
        JWTCreator.Builder builder = JWT.create();
        map.forEach((k, v) -> {
            builder.withClaim(k, v);
        });
        String token = builder.withIssuedAt(new Date())//设置签发时间
                .withExpiresAt(nowTime.getTime())//设置过期时间 过期时间大于签发时间
                .sign(Algorithm.HMAC256(SECRET));//用公共密钥加密
        System.out.println("token失效时间:" + nowTime.getTime());
        return token;
    }

    /**
     * 校验token是否正确
     */
    public static boolean verify(String token) {
        try {
            JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
            return false;
        } catch (Exception exception) {
            return true;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     */
    public static DecodedJWT decodedJwt(String token) {
        return JWT.decode(token);
    }
}

3.添加JWT认证拦截器(结合实际情况,也可以使用aop方式来实现认证)

package com.zm.web.interceptor;


import com.zm.common.exception.BusinessRuntimeException;
import com.zm.common.exception.ErrorResultCode;
import com.zm.common.util.JWTUtil;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class JwtInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        String tokenHeader = request.getHeader(JWTUtil.TOKEN_HEADER);
        if (tokenHeader == null || "".equals(tokenHeader)) {
            throw new BusinessRuntimeException(ErrorResultCode.Login_failure);
        }
        if (JWTUtil.verify(tokenHeader)) {
            throw new BusinessRuntimeException(ErrorResultCode.Login_failure);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    }


}
package com.zm.web.Config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.zm.web.interceptor.JwtInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class HttpConverterConfig implements WebMvcConfigurer {

    /**
     * 添加jwt认证拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //拦截路径可自行配置多个 可用 ,分隔开
        registry.addInterceptor(new JwtInterceptor()).addPathPatterns("/**").
                excludePathPatterns("/login");
    }

	/**
     * 配置Swagger静态资源访问
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    //使用阿里 FastJson 作为JSON MessageConverter
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        List<MediaType> supportedMediaTypes = new ArrayList<>();
        supportedMediaTypes.add(MediaType.APPLICATION_JSON);
        supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
        supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        supportedMediaTypes.add(MediaType.APPLICATION_PDF);
        supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XML);
        supportedMediaTypes.add(MediaType.IMAGE_GIF);
        supportedMediaTypes.add(MediaType.IMAGE_JPEG);
        supportedMediaTypes.add(MediaType.IMAGE_PNG);
        supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
        supportedMediaTypes.add(MediaType.TEXT_HTML);
        supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
        supportedMediaTypes.add(MediaType.TEXT_PLAIN);
        supportedMediaTypes.add(MediaType.TEXT_XML);
        converter.setSupportedMediaTypes(supportedMediaTypes);
        converter.setDefaultCharset(Charset.forName("UTF-8"));
        FastJsonConfig config = new FastJsonConfig();
        JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
        config.setSerializerFeatures(SerializerFeature.WriteDateUseDateFormat);//格式化时间
        converter.setFastJsonConfig(config);
        converters.add(converter);
    }

}

4. 从请求对象中获取token中保存的信息

package com.zm.web.util;


import com.auth0.jwt.interfaces.DecodedJWT;
import com.zm.common.util.JWTUtil;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

public class HttpUtil {

    /**
     * 从请求对象中获取token中保存的用户信息
     */
    public static String getUserSessionInfo() {
        // 获取请求对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 获取请求头Token值
        String token = Optional.ofNullable(request.getHeader(JWTUtil.TOKEN_HEADER)).orElse(null);
        DecodedJWT decodedJWT = JWTUtil.decodedJwt(token);
        String username = decodedJWT.getClaims().get("username").asString();
        return username;
    }

}

5. 测试一下成果

package com.zm.web.controller;

import com.zm.common.util.JWTUtil;
import com.zm.entity.User;
import com.zm.service.UserService;
import com.zm.vo.LoginVo;
import com.zm.vo.TokenVo;
import com.zm.web.util.HttpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;

@RestController
@Validated
public class JwtController {

    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public TokenVo login(@Valid @RequestBody LoginVo loginVo) throws UnsupportedEncodingException {
        // 登陆验证
        User user = userService.selectUserInfoByName(loginVo.getUsername());
        // 验证通过存入用户信息
        HashMap<String, String> map = new HashMap<>();
        map.put("username", user.getName());
        // 返回生成的token
        return new TokenVo(JWTUtil.createToken(map));
    }

    @GetMapping("/user")
    public User hello() {
        System.out.println("token中的信息:" + HttpUtil.getUserSessionInfo());
        return userService.selectUserInfoByName(HttpUtil.getUserSessionInfo());
    }

}

先访问一下获取用户信息接口,提示登陆失效

springboot3整合redssion_java

登陆获取token

springboot3整合redssion_ide_02

将获取到的token放入请求头中,再次访问获取用户信息接口

springboot3整合redssion_ide_03

以下参考:


6. JWT的使用

服务端生成了JWT作为Token,返回给客户端,客户端可以将其保存在localStorage中,请求的时候,都要带上这个 Token。可以在http的Headers中传给服务端,通常用Authorization这个字段存放Token。

7. JWT的几个特点

(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。

(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

8. JWT的使用场景和优劣