基于springmvc开发注解式ip拦截器
一、注解类
1 @Documented 2 @Target({ElementType.TYPE,ElementType.METHOD}) 3 @Retention(RetentionPolicy.RUNTIME) 4 public @interface IPFilter { 5 6 /** 7 * 访问ip白名单 8 * @return 9 */ 10 String[] allow() default {}; 11 12 /** 13 * 访问ip黑名单 14 * @return 15 */ 16 String[] deny() default {}; 17 }
1. @Documented —— 指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。
2. @Target——指明该类型的注解可以注解的程序元素的范围。该元注解的取值可以为TYPE,METHOD,CONSTRUCTOR,FIELD等。如果Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。
3. @Inherited——指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。
4.@Retention——指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,CLASS,RUNTIME。
二、注解实现
1 public class AuthorityIPInterceptor extends HandlerInterceptorAdapter { 2 private final static Logger logger = LoggerFactory.getLogger(AuthorityIPInterceptor.class); 3 4 @Override 5 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 6 throws Exception { 7 if (handler instanceof HandlerMethod) { 8 IPFilter ipFilter = ((HandlerMethod) handler).getMethodAnnotation(IPFilter.class); 9 if (ipFilter == null) { 10 return true; 11 } 12 String ipAddress = getIpAddress(request); 13 ArrayList<String> deny = Lists.newArrayList(ipFilter.deny()); 14 ArrayList<String> allow = Lists.newArrayList(ipFilter.allow()); 15 16 //设置了黑名单, 黑名单内ip不给通过 17 if (CollectionUtils.isNotEmpty(deny)) { 18 if (deny.contains(ipAddress)) { 19 logger.info("IP: "+ipAddress+" 被拦截"); 20 response.setStatus(500); 21 return false; 22 } 23 } 24 //设置了白名单, 只有白名单内的ip给通过 25 if (CollectionUtils.isNotEmpty(allow)) { 26 if (allow.contains(ipAddress)) { 27 logger.info("IP: "+ipAddress+" 被放行"); 28 return true; 29 }else { 30 logger.info("IP: "+ipAddress+" 没有放行权利"); 31 response.setStatus(500); 32 return false; 33 } 34 } 35 } 36 return true; 37 } 38 39 /** 40 * 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址; 41 * 42 * @param request 43 * @return 44 * @throws IOException 45 */ 46 public final static String getIpAddress(HttpServletRequest request) throws IOException { 47 // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 48 49 String ip = request.getHeader("X-Forwarded-For"); 50 if (logger.isInfoEnabled()) { 51 logger.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip=" + ip); 52 } 53 54 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 55 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 56 ip = request.getHeader("Proxy-Client-IP"); 57 if (logger.isInfoEnabled()) { 58 logger.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip=" + ip); 59 } 60 } 61 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 62 ip = request.getHeader("WL-Proxy-Client-IP"); 63 if (logger.isInfoEnabled()) { 64 logger.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip=" + ip); 65 } 66 } 67 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 68 ip = request.getHeader("HTTP_CLIENT_IP"); 69 if (logger.isInfoEnabled()) { 70 logger.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip=" + ip); 71 } 72 } 73 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 74 ip = request.getHeader("HTTP_X_FORWARDED_FOR"); 75 if (logger.isInfoEnabled()) { 76 logger.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip=" + ip); 77 } 78 } 79 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 80 ip = request.getRemoteAddr(); 81 if (logger.isInfoEnabled()) { 82 logger.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip=" + ip); 83 } 84 } 85 } else if (ip.length() > 15) { 86 String[] ips = ip.split(","); 87 for (int index = 0; index < ips.length; index++) { 88 String strIp = (String) ips[index]; 89 if (!("unknown".equalsIgnoreCase(strIp))) { 90 ip = strIp; 91 break; 92 } 93 } 94 } 95 return ip; 96 } 97 }
通过继承springmvc的拦截器,对所有访问当前加了注解的controller接口和方法进行拦截
三、路径拦截
1 <mvc:interceptor> 2 <mvc:mapping path="/**/xxx/**"/> 3 <bean class="com.xxx..AuthorityIPInterceptor"/> 4 </mvc:interceptor>
通过在mvc的配置文件配置请求的拦截路径,防止所有的请求都被拦截,做到精准控制