前言
这边是自己搭建项目的时候弄的一个token验证,包括无token时的拦截等,在网上查了很多资料大部分都用不了,有的生成了token,但是没有放到请求头里面接口照样能访问,有的拦截器执行了N遍,这里整理了下使用的是jjwt实现的token验证。
代码实现
我这里使用的是springboot
pom.xml
<!-- token -->
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
JwtUtils(生成和验证token)
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtUtils {
// 过期时间10分钟
private static long expire = 600000;
// 秘钥
private static String secret = "HSyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9";
/**
* 创建一个token
*
* @param userId
* @return
*/
public static String generateToken(String userId) {
Date now = new Date();
Date expireDate = new Date(now.getTime() + expire);
return Jwts.builder().setHeaderParam("type", "JWT").setSubject(userId).setIssuedAt(now)
.setExpiration(expireDate).signWith(
SignatureAlgorithm.HS512, secret).compact();
}
/**
* 解析token
*/
public Claims getClaimsByToken(String token) {
try {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (Exception e) {
System.out.println("validate is token error");
return null;
}
}
/**
* 判断 token 是否过期
*/
public boolean isTokenExpired(Date expiration){
return expiration.before(new Date());
}
}
TokenInterceptor(拦截器)
import com.example.common.exception.ATException;
import io.jsonwebtoken.Claims;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
@Component
public class TokenInterceptor extends HandlerInterceptorAdapter {
// 注入jwt工具类
@Autowired
private JwtUtils jwtUtils;
// 重写 前置拦截方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 1、从请求头中获取token
String token = request.getHeader("Authorization");
// 2、判断 token 是否存在
if (token == null ||"".equals(token)) {
System.out.println("未登录");
// 这里可以自定义 抛出 token 异常
throw new ATException("未登录");
}
// 3、解析token
Claims claim = jwtUtils.getClaimsByToken(token);
if (null == claim) {
System.out.println("未登录");
// 这里可以自定义 抛出 token 异常
throw new ATException("未登录");
}
// 4、判断 token 是否过期
// Date expiration = claim.getExpiration();
// boolean tokenExpired = jwtUtils.isTokenExpired(expiration);
// if (tokenExpired || null == claim) {
// System.out.println("token已过期,请重新登录");
// // 这里可以自定义 抛出 token 异常
// throw new ATException("token已过期,请重新登录");
// }
// 5、 从 token 中获取员工信息
String subject = claim.getSubject();
// 6、去数据库中匹配 id 是否存在 (这里直接写死了)
if (null == subject) {
System.out.println("用户不存在");
// 这里可以自定义 抛出 token 异常
throw new ATException("用户不存在");
}
// 7、成功后 设置想设置的属性,比如员工姓名
// request.setAttribute("userId", subject);
// request.setAttribute("userName", "张三");
return true;
}
}
WebMvcConfigs(配置类)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfigs implements WebMvcConfigurer{
// 注入 token 拦截器
@Autowired
private TokenInterceptor interceptor;
/**
* 重写添加拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加自定义拦截器,并拦截对应 url
registry.addInterceptor(interceptor)
.addPathPatterns("/rest/**");
}
}
我这边是拦截了所有 rest 开头的接口都需要token验证
controller
@ApiOperation(value = "/rest/test", notes = "test")
@RequestMapping(value = "test", method = RequestMethod.GET)
public RestResponse test(
) {
try {
return RestResponse.success();
} catch (Exception ex) {
ex.printStackTrace();
}
}
@ApiOperation(value = "createToken", notes = "createToken")
@RequestMapping(value = "createToken", method = RequestMethod.GET)
public RestResponse createToken(
) {
try {
String token= JwtUtils.generateToken("1111111111");
return RestResponse.success(token);
} catch (Exception ex) {
ex.printStackTrace();
}
}
在请求头中加入token 后访问
Authorization 前端传token时参数应为Authorization 否则会没有数据需要保持统一