1.继承
HandlerInterceptor重写
preHandle:拦截处理程序的执行。在 HandlerMapping 确定合适的处理程序对象之后,但在 HandlerAdapter 调用处理程序之前调用。 postHandle:拦截处理程序的执行。在 HandlerAdapter 实际调用处理程序之后调用,但在 DispatcherServlet 呈现视图之前调用。可以通过给定的 ModelAndView 向视图公开其他模型对象。 afterCompletion:请求处理完成后的回调,即渲染视图后。将在处理程序执行的任何结果上调用,从而允许适当的资源清理。注意:只有在此拦截器的{@code preHandle} 方法成功完成并返回{@code true} 时才会调用! 与 {@code postHandle} 方法一样,该方法将在链中的每个拦截器上以相反的顺序调用,因此第一个拦截器将是最后一个被调用的。PS:通过response可以将返回信息writer到前端
@Component
public class WeChatProgramInterceptor implements HandlerInterceptor {
@Autowired
private RedisUtil redisUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
String openid = request.getHeader("openId");
if (Objects.equals(token,null) || Objects.equals(openid,null)){
// 参数不全 非法操作
response.setCharacterEncoding("utf-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
JSONObject jsonObject = new JSONObject();
jsonObject.put("success", false);
jsonObject.put("code", 50000);
jsonObject.put("msg", "非法操作!");
writer.write(jsonObject.toJSONString());
writer.flush();
writer.close();
return false;
}else {
//登录失效 重新调用一下生成token的接口
if (!redisUtil.hasKey(token)){
response.setCharacterEncoding("utf-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
JSONObject jsonObject = new JSONObject();
jsonObject.put("success", false);
jsonObject.put("code", 50001);
jsonObject.put("msg", "登录失效!");
writer.write(jsonObject.toJSONString());
writer.flush();
writer.close();
return false;
}
//当前openId 和 token保存的openId 不一致
String value = (String) redisUtil.getValue(token);
String[] split = value.split("-");
if (!openid.equals(split[1])){
response.setCharacterEncoding("utf-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
JSONObject jsonObject = new JSONObject();
jsonObject.put("success", false);
jsonObject.put("code", 50000);
jsonObject.put("msg", "非法操作!");
writer.write(jsonObject.toJSONString());
writer.flush();
writer.close();
return false;
}
}
return true;
}
}
2.新建一个
WebConfig 实现 WebMvcConfigurer 接口
@Resource
private HandlerInterceptor weChatProgramInterceptor;
/**
* 微信小程序 进行安全拦截
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//拦截小程序的
//addPathPatterns 表示要拦截的请求
//excludePathPatterns 不需要拦截的
registry.addInterceptor(weChatProgramInterceptor).addPathPatterns("/xx/**").excludePathPatterns("/xx/xx/xx","/xxx/xx/x","/xx/xx/xx","/xx/xx/xx");
}
小程序接口安全性保证
1.通过微信5分钟临时凭证code 获取openid 和 session_key , 将openid 返回给前端
2.通过 openid 和 session_key 生成一个 token,当作key 存储redis,value存储openid 和 session_key (redis存储时间 可以设置 也可以不设置 最好设置)
3.将token返回给前端 ,要求前端请求必须携带openid 和 token
验证: (1)拦截器 如果token和openid 都没有携带 设置请求失败
(2)redis 时间过期 让前端重新调用 生成token的接口 新的token替代老的token
(3)防止 openid 和 token 中的openid 不一致