背景
每个网站都会和其它的公司或者平台有对接,有的公司内部的也会有接口的相互调用。但是接口的直接开放并不安全,必须有对应的令牌才能保证安全。令牌在什么时候去校验?自然是请求过来时,后端接收前。
Javaweb开发有专门处理这种请求的模块—拦截器。拦截器会在校验请求是否符合规则,符合才能真正被接收。那么只要在拦截器中校验令牌是否正确就能过滤掉非法的请求。甚至通过控制令牌的权限控制访问权限。
原理
interceptor提供了preHandle和postHandle以及afterCompletion三个方法。preHandle调用controller具体方法之前调用,postHandle完成具体方法之后调用,afterCompletion完成对页面的render以后调用,至此整个页面渲染完成。也就是说我们在preHandle记录开始的时间,在afterCompletion记录结束的时间,就可或者整个页面生成的时间。
很显然,我们这次需要拦截的是接口权限。有权限的才能做后续的操作,那就是使用preHandle方法。
步骤和流程
步骤:
第一步:自定义一个实现了Interceptor接口的类,或者继承抽象类AbstractInterceptor。这里继承了HandlerInterceptor接口
第二步:在配置文件中注册定义的拦截器。
第三步:在需要使用Controller中编写业务逻辑
流程:
具体实现
1 自定义拦截器类,实现HandlerInterceptor接口
2 实现preHandle方法,此处校验的是app_id和app_secret是否合法
3 在configuration类中注册拦截器,定义生效的规则
4 编写Controller代码
核心代码
拦截器OpenIntercept:
@Component //表示这是一个组件,可以实现依赖注入
public class OpenIntercept implements HandlerInterceptor{
// 校验的数据存在数据库中,需要查询数据库
@Autowired
AppSourceMapper appSourceMapper;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 获取指定的参数数据,用于校验使用
String app_id = request.getParameter("app_id");
String app_secret = request.getParameter("app_secret");
System.out.println(request.getRemoteAddr());
// 校验是否合法
if(StringUtils.isNotBlank(app_id)&& StringUtils.isNotBlank(app_secret)&& checkAppSourceIsExsist(app_id,app_secret)){
return true; //合法通过
} else{
//非法给出提示
response.setCharacterEncoding("UTF-8");
response.getOutputStream().write(ResultUtils.error(-1, "您无操作此接口的权限!").getBytes());
return false;
}
}
@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 {
}
// 校验数据库是否存在令牌对
private boolean checkAppSourceIsExsist(String app_id,String app_secret){
return appSourceMapper.countByAppIdAndSecret(app_id, app_secret)>0?true:false;
}
}
配置类CoreConfiguration
public class CoreConfiguration extends WebMvcConfigurerAdapter{
@Autowired
OpenIntercept openIntercept;
// 注册拦截器
public void addInterceptors(InterceptorRegistry registry) {
// 注册包括拦截器和拦截的路径,可以使用统配表达式
registry.addInterceptor(openIntercept).addPathPatterns("/open/**");
}
@Bean
public HttpMessageConverter<String> responseBodyConverter() {
StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
return converter;
}
@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
converters.add(responseBodyConverter());
}
@Override
public void configureContentNegotiation(
ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}
觉得本文好的可以点个赞,觉得不好的可以提提建议或意见,一起进步,一起成长!!!
欢迎邮件来信讨论 490514142@qq.com