拦截器的作用就不多说了,我们今天通过拦截器来实现接口令牌的验证
maven集成需要依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
项目的结构,gateway里面有拦截的配置,这个包命名有问题,轻喷
@Autowired
TokenService tokenService;
@PostMapping("/api/web/admin/token")
public Object getToken(){
return tokenService.creatToken();
}
/************ tokenService 具体实现 *******************/
// 封装的redis操作工具类
@Autowired
RedisTool redisTool;
/**
* 生成令牌,并存入放入缓存
* @return accessToken
*/
@Override
public Map<String,Object> creatToken() {
String accessToken = UUID.randomUUID().toString().replace("-", "");
// 缓存令牌,有效期为30分钟
redisTool.set(accessToken,accessToken,60*60);
Map map = Response.results();
map.put("accessToken",accessToken);
return map;
}
关于token的拦截类实现,请求标头中必须要有缓存的令牌
@Component
public class AccessTokenFilter implements HandlerInterceptor {
@Autowired
TokenService checkService;
/**
* 在请求处理之前进行调用(Controller方法调用之前)
* @return true 继续向下执行 false取消当前请求
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String accessToken = request.getHeader("accessToken");
if (checkService.checkToken(accessToken))
return true;
// 失败的话设置返回状态码
response.setStatus(403);
return false;
}
}
多个拦截器组成一个拦截器链,AccessTokenFileter算作一个拦截器
@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {
@Autowired
private AccessTokenFilter interceptor;
/**
* addPathPatterns 用于添加拦截规则
* excludePathPatterns 排除拦截
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor).addPathPatterns("/**")
.excludePathPatterns("/api/web/admin/token");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
接下来我们通过 Postman 测试
测试获取动态令牌接口,可以发现是没有任何拦截的
测试登录接口
少输入令牌最后一个字符,可以看到HTTP状态码,是我们之前设置的403,因为我们并没有设置相关返回内容,所以body下是空的
导致403状态码有时候可能不是没传令牌的原因,所以我们我们多返回一下信息回去,重新实现拦截器
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String accessToken = request.getHeader("accessToken");
if (checkService.checkToken(accessToken)||"ezblock_studio".equals(accessToken)){
return true;
}
response.setStatus(403);
// 设置 UTF-8 转码 否则返回到前端的都是 ??? 不可识别信息
response.setCharacterEncoding("UTF-8");
response.getWriter().write("请输入有效令牌");
response.getWriter().println("//你好");
return false;
}
现在软件开发流行前后端分离架构,后端接口返回 JSON 数据方便前端工程师处理,那在这里我们该怎么做呢?
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String accessToken = request.getHeader("accessToken");
if (checkService.checkToken(accessToken)||"ezblock_studio".equals(accessToken)){
return true;
}
response.setStatus(403);
response.setCharacterEncoding("utf-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
JSONObject resp = new JSONObject();
resp.put("status","请输入有效令牌");
writer.write(resp.toString());
return false;
}