[开发工具]-[Token&JWT]

Token&JWT

token

前端请求后端时,后端需要保证这个请求来自受认可的用户,因此需要对用户进行认证。为避免频繁地使用与数据库交互以获取用户信息的手段来认证,在初次登陆后,后端为前端生成一个信息,前端在之后向后端发出请求时只需携带这个信息,后端通过判断该信息的合法性来判断是否允许该请求,以及认证用户,这个信息就是token
所以token并没有固定的实现方式,作为一种认证作用的工具,根据实际需求不同或开发者的习惯可以有不同的实现方式,只要能实现类似的认证作用即可

关于token的刷新机制

机制1:设置一个过期时间expire_time以及刷新时间refresh_time,刷新时间大于过期时间,当当前token存活时间达到过期时间时,可以凭借这个token去获得一个新的token;但如果存活时间大于刷新时间,就只能重新登陆来获取新的token。相当于就是,用户端拿着一个token,如果发出请求的频率较高(两次请求之间相隔不超过expire_time),那就没必要刷新token,一方面会影响到用户体验,一方面服务端这边也需要进行额外的生成token操作;而如果用户长时间没有发出新的请求,超出了refresh_time,那么对用户的信任就应降低,有必要刷新token

JWT

概述

JWT(json web token),是其中一种实现的规范,由三个部分组成:headerpayloadsignature。header包含token的基本的通用信息,如加密所用算法,过期时间等;payload中可以携带如用户信息等其它的信息,例如可以把用户的账号密码作为payload的一部分;signature是对header,payload以及后端设定的盐值进行加密后组成的签证信息

代码示例

依赖
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.18.1</version>
</dependency>
JWT工具类
public class JwtUtil {
	/**
	 * 自定义签名(盐值)
     */
    private static final String SIGNATURE = "!Q@W#E$R";
    /**
     *生成token
     * @param map 要放入payload的键值对数据
     * @return java.lang.String
     */
    public static String generateToken(Map<String,String> map){
        Calendar calendar = Calendar.getInstance();
        //设置15天为token过期时间
        calendar.add(Calendar.DATE,15);
        //创建builder
        JWTCreator.Builder builder = JWT.create();
        //将map中的键值对放入token的payload处
        map.forEach(builder::withClaim);
        //设置过期时间以及加密算法和签名
        return builder.withExpiresAt(calendar.getTime())
        		//使用的加密算法一般都是这一个
                .sign(Algorithm.HMAC256(SIGNATURE));
    }
    /**
     *验证token,只要验证过程中有一步不通过该方法都会抛异常,因此不用过多处理
     * @param token 前端请求携带的token
     * @return com.auth0.jwt.interfaces.DecodedJWT
     */
    public static DecodedJWT verify(String token){
        return JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
    }
}
整合拦截器
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //从请求头获取token
        String token = request.getHeader("token");
        ..............
        try {
            JwtUtil.verify(token);
            return true;
        }catch (SignatureVerificationException e){
            log.error("token所使用的签名无效,[{}]",e.getMessage());
            resultDto.put("msg","token所使用的签名无效");
        }catch (TokenExpiredException e){
            log.error("token已过期,[{}]",e.getMessage());
            resultDto.put("msg","token已过期");
        }catch (AlgorithmMismatchException e){
            log.error("token所使用的算法不一致,[{}]",e.getMessage());
            resultDto.put("msg","token所使用的算法不一致");
        }catch (Exception e){
            log.error("无效token![{}]",e.getMessage());
            resultDto.put("msg","token无效");
        }
        response.getWriter().println(new ObjectMapper().writeValueAsString(....));
        return false;
    }
}
springMVC配置类
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    	//在拦截器注册类中注册自定义的拦截器,以及要拦截的请求路径
        registry.addInterceptor(new JwtInterceptor())
                .addPathPatterns("/**");
    }
}

你可能感兴趣的:(java)