白名单介绍
创建元注解
创建一个元注解,标注此元注解的方法才需要进行判断
1 2 3 4 5 6 7 8 9 10
| @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AuthorityCheck { /** * 接口需要配置公共ip白名单之外的iP时使用 * @return hconfig中的key */ public String key() default ""; }
|
Controller方法标注注解
对需要进行判断的方法加上注解
如果需要为接口单独配置白名单,在注解中加上key,key是hconfig白名单配置中的key
如果不需要单独配置白名单,则@AuthorityCheck,走公共的白名单
1 2 3 4 5 6
| @RequestMapping(value = "/mmpInfos.json") @AuthorityCheck(key = "mmpInfos.ip.white.list") @ResponseBody public DappJsonResult queryMaintenanceModeAndPriceInfos() { return new JsonResult<>(data); }
|
拦截器实现
HandlerInterceptorAdapter是一个适配类,也可以直接继承HandlerInterceptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Component public class AuthorityInterceptor extends HandlerInterceptorAdapter { private static final Logger logger = LoggerFactory.getLogger(AuthorityInterceptor.class); @Resource private IPWhiteListService ipWhiteList; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!(handler instanceof HandlerMethod)) { return true; } HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); if (!method.isAnnotationPresent(AuthorityCheck.class)) { return true; } if (!ipWhiteList.isEnabled()) { logger.debug("白名单禁用"); return true; } AuthorityCheck authorityCheck = method.getAnnotation(AuthorityCheck.class); String realIp = IpUtil.getUserIPString(request); logger.debug("real ip is: {}", realIp); return ipWhiteList.isAllowedIp(realIp,authorityCheck.key()); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| @Component public class IPWhiteListService { private static final Logger logger = LoggerFactory.getLogger(IPWhiteListService.class); private static final String COMMON_IP_WHITE_LIST = "common.ip.white.list"; @HConfig("dapp_ip_white_conf.properties") private Map ipWhiteMap; public boolean isEnabled() { String isEnable = getString("ip.white.switch","true"); return "true".equals(isEnable); } /** * 访问ip只要在特定白名单 or 公共单个白名单 or 公共ip段中 则允许访问 * @param realIp * @param key 接口特定ip白名单hconfig中key * @return */ public boolean isAllowedIp(String realIp,String key) { if(StringUtils.isNotBlank(key)) {//接口有定制的ip白名单 String unusualIpWhiteList = getString(key,""); if(unusualIpWhiteList.contains(realIp)) { return true; } } //所有接口公共的ip白名单 String commonIpWhiteList = getString(COMMON_IP_WHITE_LIST, "127.0.0.1"); return commonIpWhiteList.contains(realIp) || isInIpWhiteRangeList(realIp); } //公共ip段白名单校验 public boolean isInIpWhiteRangeList(String ip) { String rangeIps = getString("common.range.ip.white.list",""); List rangeIpList = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(rangeIps); if(rangeIpList != null && rangeIpList.size() != 0) { for (String s : rangeIpList) { boolean isValid = isInIpWhiteRangeList(s, ip); if(isValid) { return true; } } } return false; } /** * 判断IP是否在指定范围; * @param ipSection 范围 示例 192.168.1.1-192.168.2.10 * @param ip * @return */ public static boolean isInIpWhiteRangeList(String ipSection, String ip) { if (StringUtils.isBlank(ipSection) || StringUtils.isBlank(ip) ) { return false; } ipSection = ipSection.trim(); ip = ip.trim(); final String REGX_IP = "((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)"; final String REGX_IPB = REGX_IP + "\\-" + REGX_IP; if (!ipSection.matches(REGX_IPB) || !ip.matches(REGX_IP)) {//判断参数是否是ip4格式 return false; } int idx = ipSection.indexOf('-'); String[] sips = ipSection.substring(0, idx).split("\\."); String[] sipe = ipSection.substring(idx + 1).split("\\."); String[] sipt = ip.split("\\."); long startIp = 0L, endIp = 0L, realIp = 0L; for (int i = 0; i < 4; ++i) { //把ip转化成long startIp = startIp << 8 | Integer.parseInt(sips[i]); endIp = endIp << 8 | Integer.parseInt(sipe[i]); realIp = realIp << 8 | Integer.parseInt(sipt[i]); } if (startIp > endIp) { long t = startIp; startIp = endIp; endIp = t; } return startIp <= realIp && realIp <= endIp; } private String getString(String key,String def) { String value = ipWhiteMap.get(key); return value == null ? def : value; }
|
配置文件
dispatch-servlet.xml文件进行如下修改
Hconfig白名单配
便于管理hconfig白名单单独拉出来一个文件dapp_ip_white_conf.properties
公共ip段白名单开始结束用 一个横线隔开 “-“
多个ip或者ip段之间用英文逗号 “,”隔开
只要访问ip在 公共ip白名单,公共ip段白名单,接口特定白名单 三者中之一存在则是允许访问的,他们是 or 的关系
1 2 3 4 5 6 7 8 9 10 11
| #白名单开关 ip.white.switch=true #公共的白名单 common.ip.white.list=127.0.0.1 #公共ip段白名单 common.range.ip.white.list=10.89.129.1-10.89.129.255,127.0.0.1-127.0.0.6 #团期接口白名单 mmpInfos.ip.white.list=10.89.129.89
|