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;
private String salt;
private String name;
private int expiresSecond;
}
3.token配置
@Slf4j
@Component
public class TokenConfiguration extends RuntimeException implements HandlerInterceptor {
private final static TokenInfo tokenInfo = new TokenInfo();
private static final String KEY = "token";
@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);
parseToken(token);
log.info("token解析正确!");
Long tokenOutTime = getWebTokenTime(token);
Long currentTime = System.currentTimeMillis();
if (tokenOutTime < currentTime){
throw new RuntimeException();
}
parseToken(token);
log.info("token正确!");
return true;
}
static {
tokenInfo.setExpiresSecond(15*42*60*60*100L);
tokenInfo.setName("monkey");
tokenInfo.setSalt("ikingTech");
}
public String getToken(Object object) {
try {
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(tokenInfo.getSalt());
Key signingKey = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
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);
long outMillis = tokenInfo.getExpiresSecond();
if (outMillis >= 0) {
long expMillis = nowMillis + outMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp).setNotBefore(now);
}
String token = builder.compact();
log.info("token:" + token);
return token;
}catch (Exception e){
log.info("token加密失败!");
throw new RuntimeException();
}
}
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();
}
}
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;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenConfiguration)
.excludePathPatterns("/login")
.excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
}
@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;
@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";
}
}
@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;
}
}