在开发中遇到一个场景,当需要提供接口给其他系统,并需要鉴权时,我当时的处理方案是用过滤器拦截进行个性化鉴权,如果鉴权通过则还是需要经过安全测试、转码等filter,但是不走后面的鉴权过滤器,不通过则跳转到错误页面。
这里就需要去掉过滤器链中的某一个过滤器,下面介绍下我的方案:通过反射修改过滤器链:
/** * * 通过反射修改过滤器链 * @param chain */ private void skipFilter(FilterChain chain) { try { //排除的过滤器数组 Object[] filterArr=new Object[]{InterfaceConstants.UN_AUTH_FILTER}; Field field = chain.getClass().getDeclaredField("filters"); field.setAccessible(true); FilterConfig[] filters = (FilterConfig[]) field.get(chain); int k = 0; for (int i = 0; i < filters.length; i++) { if (filters[i] != null) { Field field2 = filters[i].getClass().getDeclaredField("filterDef"); field2.setAccessible(true); Field field3 = field2.get(filters[i]).getClass().getDeclaredField("filterClass"); field3.setAccessible(true); String filterClass = (String) field3.get(field2.get(filters[i])); int loc = Arrays.binarySearch(filterArr, filterClass); if (loc >= 0) { //将过滤器重置为null filters[i] = null; k++; } field3.setAccessible(false); field2.setAccessible(false); } } int index = 0; for (int i = 0; i < filters.length; i++) { if (index == 0 && filters[i] == null) { index = i; } else if (index != 0 && filters[i] != null) { filters[index] = filters[i]; filters[i] = null; i = index; index = 0; } } field.setAccessible(false); Field n=null; try { n = chain.getClass().getDeclaredField("n"); logger.info("tomcat容器中filter的n属性"); } catch (Exception e) { n = chain.getClass().getDeclaredField("filterCount"); logger.info("jboss容器中filterCount属性"); } if(n!=null){ n.setAccessible(true); n.set(chain, n.getInt(chain) - k); n.setAccessible(false); } } catch (Exception e) { logger.error("通过反射修改过滤器链出错",e); } }