实现步骤:
一、自定义一个拦截器配置类,里面可以配置不同的拦截器,比如校验token的、校验权限的等,在里面可以设置拦截的路径和放行的路径等。
二、自定义注解(以校验token为例子,我自定义了@NotCheckToken
这个注解,当控制层使用这个注解,表示放行,该接口不进行token的校验)
三、实现具体的拦截器,比如token校验的,你校验token的逻辑要写在这个类里面,具体的处理,preHandler方法表示进行拦截,然后判断是否使用@NotCheckToken
注解, 没有使用这个注解则需要进行token校验。
具体实现
1、InterceptorConfig(拦截器配置类)
package com.lancoo.primaryedu.Interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @description: 自定义拦截器
* @author: daiziru
* @date: 2023/7/14 15:39
* @param:
* @return:
**/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
/**
* 配置拦截路径
*
* @param registry 拦截器参考
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// token 拦截所有请求,通过判断是否有 @NotCheckToken 注解 决定是否需要校验
registry
.addInterceptor(tokenInterceptor()) //添加需要的自定义拦截器
.addPathPatterns("/**"); //对所有路径进行拦截
}
/**
* token 拦截器注入
*
* @return Token 拦截器
*/
@Bean
public TokenInterceptor tokenInterceptor() {
return new TokenInterceptor();
}
}
2、自定义注解NotCheckToken
package com.lancoo.primaryedu.Interceptor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义 Token 校验注解
* @author pky
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotCheckToken {
boolean required() default true;
}
3、token具体的拦截器
package com.lancoo.primaryedu.Interceptor;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.lancoo.common.exception.MyException;
import com.lancoo.common.respone.StatusCode;
import com.lancoo.common.utils.JsonUtil;
import com.lancoo.primaryedu.entity.net.BasePlatOutBean;
import com.lancoo.primaryedu.entity.net.NetUtil;
import com.lancoo.primaryedu.entity.net.OutCome;
import com.lancoo.primaryedu.entity.net.RequestResponse;
import com.lancoo.primaryedu.util.CommonUtil;
import com.lancoo.primaryedu.util.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
/**
* Token 拦截器
* @author pky
*/
@Slf4j
public class TokenInterceptor implements HandlerInterceptor {
@Autowired
private TokenUtil tokenUtil;
@Autowired
private Environment environment;
/**
* @description: 通过检查是否有@NotCheckToken注解,决定是否进行token校验
* @author: daiziru
* @date: 2023/7/14 15:31
* @param: [request, response, object]
* @return: boolean
**/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
// 从 http 请求头中取出 token
String token = CommonUtil.handleHeader(request).getToken();
if(null == token || "".equals(token)) {
throw new MyException(StatusCode.REMIND, "请求头中不存在token或token不正确!");
}
// 如果不是映射到方法直接通过
if (!(object instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) object;
Method method = handlerMethod.getMethod();
// 检查用户权限的注解
if (method.isAnnotationPresent(NotCheckToken.class)) {
NotCheckToken notCheckToken = method.getAnnotation(NotCheckToken.class);
if (notCheckToken.required()) {
return true;
}
}
return checkToken(request, token);
}
/**
* 校验 token
*
* @param request 请求
* @param token 令牌
* @return 校验结果,true/通过;false/不通过
* @throws Exception 可能出现的异常
*/
private boolean checkToken(HttpServletRequest request, String token) throws Exception {
if (null == token) {
token = "";
}
String ADDR = "/UserMgr/Login/Api/Login.ashx";
String yunAddr = environment.getProperty("base.addr");
String SysID = environment.getProperty("sys.id");
Map<String, String> form = new HashMap<>();
form.put("method", "TokenCheck");
form.put("token", token);
form.put("params", SysID + "|");
String result = "";
RequestResponse response = NetUtil.postForm(checkBaseUr(yunAddr) + ADDR, form);
OutCome<BasePlatOutBean<BasePlatOutBean.BasePlatLoginOutDataBean>> outCome = new OutCome<>();
if (response.isSuccessful) {
if (!StringUtil.isEmpty(response.Data)) {
result = response.Data;
}
}
if (!result.equals("")) {
//解析下json字符串
Map<String, String> keyValue = new JsonUtil().getKeyValue(result);
String re = keyValue.get("result");
if (re == null) {
return false;
}
if (re.equals("true")) {
return true;
}
}
return false;
}
public String checkBaseUr(String url) {
if (url.endsWith("/")) {
return url;
}
return url + "/";
}
}