文章描述了校验请求IP是否符合白名单设置的三种实现方法,各位看官按需取用。这里只记录代码,不讲原理。
一、拦截器
代码如下。
基本的思路是,定义一个表示需要校验的注解,然后在拦截器中抓取。
值得注意的是:
假如验证不通过,并不是简单地抛出异常,而是向 response 中写入返回以Json 字符串表征的结果。
1) 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Authority {
}
2) 定义拦截器
@Slf4j
public class IpPermissionInterceptor extends HandlerInterceptorAdapter {
@Autowired
private AuthenticService authenticService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("提示:请求进入了拦截器");
if (!(handler instanceof HandlerMethod)) {
return true;
}
final HandlerMethod handlerMethod = (HandlerMethod) handler;
Authority authority = handlerMethod.getMethodAnnotation(Authority.class);
if (Objects.isNull(authority)) {
return true;
}
log.info("提示:打印访问ip,x-real-ip:{},x-forwarded-ford:{}",request.getHeader("x-real-ip"),request.getHeader("x-forwarded-for") );
String ip = getIp(request);
log.warn("提示:请求方的IP {}", ip);
if (StringUtils.isNotBlank(ip)) {
ResultDTO<Void> resultDTO = authenticService.authenticate(ip);
if (resultDTO.isSuccess()) {
log.info("提示:验证IP通过");
return true;
}
}
ResultDTO failResultDTO = ResultDTO.fail(null, "提示::IP不受信,请联系管理员");
try {
// 向 reponse 中写入结果
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.getWriter().append(JSON.toJSONString(failResultDTO));
} catch (IOException e) {
log.warn("提示::验证IP失败", e);
response.sendError(HttpStatus.BAD_REQUEST.value());
}
return false;
}
// 获取IP
private String getIp(HttpServletRequest request) {
String realIp = request.getHeader("x-real-ip");
if (StringUtils.isNotBlank(realIp)) {
return realIp;
}
String forwardedIPs = request.getHeader("x-forwarded-for");
if (StringUtils.isNotBlank(forwardedIPs)) {
String[] split = StringUtils.split(forwardedIPs, ",");
return split[0];
}
return request.getRemoteAddr();
}
}
3) 向 Spring 容器注册本拦截器
<mvc:interceptors>
<bean class="com.IpPermissionInterceptor"/>
</mvc:interceptors>