引入JWT相关依赖
<!--引入jwt依赖-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
编写JWT工具类
package com.democxy.common.utils;
import io.jsonwebtoken.*;
import java.util.Date;
/**
* @author SHILING_DENG
* @version 2020-05-05
*
*/public class JwtUtil {
//设置过期时间为15分钟
public static final long EXPIRE_TIME = 15*60*1000;
/**
* token私钥
*/ private static final String TOKEN_SECRET = "6CvvNscuUDAq*JxE";
/**
* 签发JWT
* @param id 可以设置为登录账户的ID
* @param subject 可以是JSON数据,如登录用户的JSON字符串 尽可能少
* @param ttlMillis token有效时间
* @return
*/ public static String signToken(String id, String subject, long ttlMillis) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder builder = Jwts.builder()
.setId(id)
.setSubject(subject) // 主题
.setIssuer("admin") // 签发者
.setIssuedAt(now) // 签发时间
.signWith(SignatureAlgorithm.HS256, TOKEN_SECRET); // 签名算法以及密匙
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
builder.setExpiration(expDate); // 过期时间
}
return builder.compact();
}
/**
* 验证JWT
* @param token
* @return
*/ public static boolean validateToken(String token) {
try {
Claims claims = parseToken(token);
if (claims!=null){
return true;
}else{
return false;
}
} catch (ExpiredJwt Exception e) {
return false;
} catch (SignatureException e) {
return false;
} catch (Exception e) {
return false;
}
}
/**
* 解析JWT字符串
* @param token
* @return
* @throws Exception
*/ public static Claims parseToken(String token){
Claims body = null;
try {
body = Jwts.parser()
.setSigningKey(TOKEN_SECRET)
.parseClaimsJws(token)
.getBody();
} catch (ExpiredJwtException e) {
e.printStackTrace();
} catch (UnsupportedJwtException e) {
e.printStackTrace();
} catch (MalformedJwtException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
return body;
}
public static void main(String[] args){
// String token = signToken("1", "admin", EXPIRE_TIME);
// System.out.println(token);
// System.out.println(validateToken(token));
}
}
编写全局异常处理相关类
package com.democxy.common.exception;
/**
* 自定义异常类
* @author shiling
* @version 2020-04-28
*/public class CustomException extends RuntimeException {
private int code;
private String msg ;
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public CustomException() {
this(1001, "接口错误");
}
public CustomException(String msg) {
this(1001, msg);
}
public CustomException(int code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
}
package com.democxy.common.global;
/**
* 响应数据
*/public class ResponeData<T> {
private int code;
private String msg;
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public ResponeData(T data) {
this(ResultCode.SUCCESS,data);
}
public ResponeData(ResultCode resultCode, T data) {
this.code = resultCode.getCode();
this.msg = resultCode.getMsg();
this.data = data;
}
}
package com.democxy.common.global;
/**
* 响应枚举类
* @author shiling
* @version 2020-04-28
*/public enum ResultCode {
VALIDATE_ FAILED (1002, "参数校验失败"),
SUCCESS(200, "操作成功"),
FAILED(500, "响应失败"),
NOT_FOUND(404, "未知请求"),
LOGIN_FAILED(4040, "登录失败!");
private int code;
private String msg;
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
ResultCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
package com.democxy.common.exception;
import com.democxy.common.global.ResponeData;
import com.democxy.common.global.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理类 加上@ControllerAdvice注解或者@RestControllerAdvice,
* 加@RestControllerAdvice只能全局处理RestFul接口异常
* @author shiling
* @version 2020-04-28
*/@RestControllerAdvice
public class ExceptionControllerAdvice {
Logger logger = LoggerFactory.getLogger(ExceptionControllerAdvice.class);
/**
* 表单验证异常处理
* @param e
* @return
*/ @ExceptionHandler(BindException.class)
public ResponeData<String> BindExceptionHandler(BindException e) {
ObjectError objectError = e.getAllErrors().get(0);
// 注意哦,这里传递的响应码枚举
logger.error("表单数据校验异常",e);
return new ResponeData<>(ResultCode.VALIDATE_FAILED, objectError.getDefaultMessage());
}
/**
* 自定义异常处理
* @param e
* @return
*/ @ExceptionHandler(CustomException.class)
public ResponeData<String> CustomExceptionHandler(CustomException e) {
logger.error("自定义异常",e);
// 注意哦,这里传递的响应码枚举
if (4040 == e.getCode()){
return new ResponeData<>(ResultCode.LOGIN_FAILED, e.getMsg());
}else {
return new ResponeData<>(ResultCode.FAILED, e.getMsg());
}
}
/**
* Exception异常处理
* @param e
* @return
*/ @ExceptionHandler(Exception.class)
public ResponeData<String> ExceptionHandler(Exception e) {
//记录日志信息
logger.error("服务异常",e);
// 注意哦,这里传递的响应码枚举
return new ResponeData<>(ResultCode.FAILED, "服务异常!");
}
}
编写登录拦截器
package com.democxy.common.interceptor;
import com.democxy.common.exception.CustomException;
import com.democxy.common.utils.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 AuthenticationInterceptor implements HandlerInterceptor {
@ Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从 http 请求头中取出 token
String token = request.getHeader("token");
System.out.println(token);
boolean verity = JwtUtil.validateToken(token);
if (!verity){
throw new CustomException(4040,"token过期,请重新登录");
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
注册拦截器
package com.democxy.common. config ;
import com.democxy.common.interceptor.AuthenticationInterceptor;
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 WebConfig implements WebMvcConfigurer {
// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthenticationInterceptor())
.addPathPatterns("/","/admin/**")
.excludePathPatterns("/admin/account/login","/admin/account/logout");
}
}