在后台接口开发中会有一类接口是需要做登录校验的,类似于生成订单,查看自己的订单列表等接口,都需要先判断用户是否登录.虽然可以在接口中进行判断,但是会让代码冗余,所以决定用自定义拦截器+自定义注解来完成这个功能
自定义拦截器可以实现HandlerInterceptor
接口或者继承HandlerInterceptorAdapter
类,HandlerInterceptorAdapter
适配器是对HandlerInterceptor
接口做了默认实现, 这种适配器模式, 是为了方便开发者只去想要复写方法, 其他方法采取默认措施.
public class AuthenticationInterceptor extends HandlerInterceptorAdapter { private Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired TokenTools tokenTools; //在执行目标方法之前执行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler.getClass().isAssignableFrom(HandlerMethod.class)) { Authentication Authentication = ((HandlerMethod) handler) .getMethodAnnotation(Authentication.class); //如果没用Authentication这个注解标注的接口或者validate=false则直接通过 if (Authentication == null || Authentication.validate() == false) { return true; } else { String userToken = request.getParameter("token"); log.debug("current token**************: " + userToken); if (StringUtils.isBlank(userToken)) { returnValue(response); return false; } else { if (!tokenTools.checkLoginInfo(userToken)) { returnValue(response); return false; } log.debug("You have logged in successfully!"); return true; } } }else { return true; } } private void returnValue(HttpServletResponse response) throws IOException { Map<String, Object> resultMap = new HashMap<String, Object>(); resultMap.put("resultcode", "0003"); resultMap.put("message", "登陆失效"); response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); response.getWriter().write(JSON.toJSONString(resultMap)); } }
自定义注解
/** * 需要登录的接口需要使用该注解 * @author cihon * */ @Target(ElementType.METHOD) //指示注释类型所适用的程序元素的种类。 @Retention(RetentionPolicy.RUNTIME) //指示注释类型的注释要保留多久。 public @interface Authentication { boolean validate() default true; }
我们需要定义一个配置文件的类来让自定义拦截器生效
/**
* 自定义拦截器配置文件
* @author cuizheng
*
*/
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthenticationInterceptor()).addPathPatterns("/**");
}
}
像下面这个接口加上@Authentication这个注解后就会做登录校验的判断
@Authentication @RequestMapping({"/saveImage"}) public String saveImage(@RequestHeader("header") String header, @RequestBody String body) { String s = new String(Base64.decode(body)); return leBorrowService.saveImage(header,s); }