美文网首页
ch12:自定义Filter实现IP限制

ch12:自定义Filter实现IP限制

作者: 伊娃瓦力 | 来源:发表于2017-07-31 14:35 被阅读0次

    对于Web应用的安全来说,最常使用的方式就是Servlet Filter,Filter能够用来增加应用特定的安全层,在最终调用具体业务逻辑前,Filter可以移除潜在的恶意行为,并增强用户体验。Spring Security提供就是基于Filter提供了各项安全卡控。但是有些时候,我们还是需要开发自定义Filter以满足应用的特殊要求,例如IP限制等。
    在ch04我们已经使用Spring Security基于特定的URL设定可访问的IP地址。但是这是一种静态配置,而生产过程中往往需要动态可访问IP,这时就可以实现自定义Filter,并将其注入到Spring Security Filter Chain中,作为Filter Chain的一环。
    这里我们假设系统管理员限制为某些IP地址,只有同时具备管理员身份和IP地址列表时才允许使用管理员权限。

    自定义Filter

    任何实现了Filter接口的类都可以注入到Spring Security Filter Chain中。这里我们使用Spring Security提供的OncePerRequestFilter作为父类。该类可以保证每个请求只调用一次改Filter。子类需要实现doFilterInternal方法。

    public class IpFilter extends OncePerRequestFilter {
        private String targetRole;//目标角色
        private List<String> authorizedIpAddresses;//IP地址列表
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                        FilterChain filterChain) throws ServletException, IOException {
            final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && targetRole != null) {
                boolean shouldCheck = false;
                for (GrantedAuthority authority : authentication.getAuthorities()) {
                    if (authority.getAuthority().equals(targetRole)) {
                        shouldCheck = true;
                        break;
                    }
                }
                if (shouldCheck && !authorizedIpAddresses.isEmpty()) {
                    boolean authorized = false;
                    for (String ipAddress : authorizedIpAddresses) {
                        if (request.getRemoteAddr().equals(ipAddress)) {
                            authorized = true;
                            break;
                        }
                    }
    
                    if (!authorized) {
                        throw new AccessDeniedException(
                                "Access has been denied for you IP address:" + request.getRemoteAddr());
                    }
                }
            } else {
                System.out.println(
                        "The IPFilter should be placed after the user has been authenticated in the filter chain.");
            }
            filterChain.doFilter(request, response);
        }
    
        public String getTargetRole() {
            return targetRole;
        }
    
        public void setTargetRole(String targetRole) {
            this.targetRole = targetRole;
        }
    
        public List<String> getAuthorizedIpAddresses() {
            return authorizedIpAddresses;
        }
    
        public void setAuthorizedIpAddresses(List<String> authorizedIpAddresses) {
            this.authorizedIpAddresses = authorizedIpAddresses;
        }
    }
    

    这里我们简单的检查了用户身份、以及访问者的IP是否为Localhost(实际生产中IP地址检查要复杂的多)。不符合要求的访问将抛出AccessDeniedException。

    配置IpFilter

    创建好Filter后,需要将其注入到Filter Chain中,这时就需要考虑Filter依赖关系,已决定Filter在Filter Chain中的位置。IpFilter需要获得用户认证信息,所以应该在UsernamePasswordAuthenticationFilter之后。通常自定义Filter都在Chain最后几位上,经过Spring Security层层通用过滤后,再进行个性化和具体的过滤。此外,Spring Security将FilterSecurityInterceptor作为最后一个Filter,主要是验证访问者是否有权限,包括方法级验证等。IpFilter较FilterSecurityInterceptor更具体,所以IpFilter应在后者之前。具体配置如下:

        @Override
        protected void configure(HttpSecurity http) throws Exception {
         http
                    ......
                    .and().addFilterBefore(ipFilter(), FilterSecurityInterceptor.class)
                    ......
        }
    
        private Filter ipFilter() {
            List<String> ipAddresses = new ArrayList<>();
            ipAddresses.add("0:0:0:0:0:0:0:1");//localhost
            IpFilter ipFilter = new IpFilter();
            ipFilter.setTargetRole("ROLE_ADMIN");
            ipFilter.setAuthorizedIpAddresses(ipAddresses);
            return ipFilter;
        }
    

    这里配置了要求具备ROLE_ADMIN的用户IP地址为Localhost。
    通过本机和其他机器使用Admin用户登录,就可以测试不在IP地址列表的机器都被限制访问了。

    代码示例:https://github.com/wexgundam/spring.security/tree/master/ch12

    相关文章

      网友评论

          本文标题:ch12:自定义Filter实现IP限制

          本文链接:https://www.haomeiwen.com/subject/asfrlxtx.html