springboot+jwt+token

1.导入依赖

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.18.2</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.79</version>
</dependency>

2.创建用户和签名实体类

  • 用户信息表
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SysUser {
    private String id;
    private String name;
    private String password;
    private String webToken;
}
  • 签名信息表
@Data
@Component
public class TokenInfo implements Serializable {
    private static final long serialVersionUID = -3574431640051881254L;
    /**
     * base64位签名
     */
    private String salt;
    /**
     * 发行人名称
     */
    private String name;
    /**
     * 保存时间
     */
    private int expiresSecond;
}

3.token配置

/**
 * 定义拦截器
 * @author monkey
 */
@Slf4j
@Component
public class TokenConfiguration extends RuntimeException implements HandlerInterceptor {

    /**
     * 存放token相关信息
     */
    private final static TokenInfo tokenInfo = new TokenInfo();
    /**
     * 设置token名称
     */
    private static final String KEY = "token";

    /**
     * token拦截
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("拦截请求" + request.getRequestURI());
        // 如果不是映射到方法直接通过,可以访问资源.
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        //为空就返回错误
        String token = request.getHeader(KEY);
        if (StringUtils.isEmpty(token)) {
            log.error("token信息不存在{}",token);
            throw new RuntimeException();
        }
        log.info("token:{}",token);
        //判断token信息是否正确
        parseToken(token);
        log.info("token解析正确!");
        //判断是否过期
        Long tokenOutTime = getWebTokenTime(token);
        Long currentTime = System.currentTimeMillis();
        if (tokenOutTime < currentTime){
            throw new RuntimeException();
        }
        //判断token信息是否正确
        parseToken(token);
        log.info("token正确!");
        return true;
    }

    /**
     * 获取配置文件token签名,发行人,时间信息
     */
    static {
        tokenInfo.setExpiresSecond(15*42*60*60*100L);     //token失效时间15天
        tokenInfo.setName("monkey");
        tokenInfo.setSalt("ikingTech");
    }

    /**
     * 加密token.
     */
    public String getToken(Object object) {
        try {
            // 生成签名密钥
            byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(tokenInfo.getSalt());
            Key signingKey = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
            // 添加构成JWT的参数
            JwtBuilder builder = Jwts.builder()
                    .setHeaderParam("typ", "JWT")
                    .claim(KEY, object)
                    .setIssuer(tokenInfo.getName())
                    .signWith(SignatureAlgorithm.HS256, signingKey);
            //当前时间
            long nowMillis = System.currentTimeMillis();
            Date now = new Date(nowMillis);
            // 添加Token过期时间(ms)
            long outMillis = tokenInfo.getExpiresSecond();
            if (outMillis >= 0) {
                long expMillis = nowMillis + outMillis;
                Date exp = new Date(expMillis);
                builder.setExpiration(exp).setNotBefore(now);
            }
            // 生成JWT
            String token = builder.compact();
            log.info("token:" + token);
            return token;
        }catch (Exception e){
            log.info("token加密失败!");
            throw new RuntimeException();
        }
    }

    /**
     * 解析token.
     */
    public static SysUser parseToken(String token)  {
        try {
            Claims claims = Jwts
                    .parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(tokenInfo.getSalt()))
                    .parseClaimsJws(token)
                    .getBody();

            return JSON.parseObject(JSON.toJSONString(claims.get(KEY)), SysUser.class);
        }catch (Exception e){
            log.info("token解析失败!");
            throw new RuntimeException();
        }

    }


    /**
     * 获取webToken的失效时间
     */
    public static Long getWebTokenTime(String token) {
        try{
            Claims claims = Jwts
                    .parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(tokenInfo.getSalt()))
                    .parseClaimsJws(token)
                    .getBody();
            return claims.getExpiration().getTime();
        }catch (Exception e){
            log.info("token获取失效时间失败!");
            throw new RuntimeException();
        }


    }

    /**
     * <获取登录用户信息>
     */
    public static SysUser getLoginUserInfo(){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            log.error("获取ServletRequestAttributes失败。");
            return null;
        }
        HttpServletRequest request = attributes.getRequest();
        String token = request.getHeader(KEY);
        return parseToken(token);
    }
}

4.过滤器过滤登录页面,放行swagger

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

    @Autowired
    private TokenConfiguration tokenConfiguration;

    /**
     * 给除了 /login 的接口都配置拦截器,拦截转向到 defineInterceptor
     */
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenConfiguration)
//                .addPathPatterns("/select") //拦截first开头的url
                .excludePathPatterns("/login")//拦截除了的url
                .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
    }


    // 放行swagger
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");

    }
}

5.自定义异常

@ControllerAdvice
public class MyException {

    @ExceptionHandler(value = RuntimeException.class)
    @ResponseBody
    public String tokenException(){
        return "用户token信息不正确!";
    }
}

6.接口测试

@RestController
public class LoginController {

    @Autowired
    private TokenConfiguration tokenConfiguration;

    /**
     * login
     * @param user
     * @return
     */
    @PostMapping(value = "/login")
    public String login(@RequestBody SysUser user){
        if ("杨过".equals(user.getName()) && "1234".equals(user.getPassword())){
            user.setId("1");
            user.setWebToken(tokenConfiguration.getToken(user));
            return "登录成功!success";
        }else {
            return "用户名或密码错误!failed";
        }
    }

    /**
     * select
     * @return
     */
    @GetMapping(value = "/select")
    public SysUser select(){
        SysUser user = new SysUser();
        user.setName("杨过");
        user.setPassword("1234");
        user.setId("1");
        user.setWebToken(tokenConfiguration.getToken(user));

        return user;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值