【问题标题】:How to config ip address dynamically with spring-security?如何使用 spring-security 动态配置 IP 地址?
【发布时间】:2018-05-20 07:41:54
【问题描述】:

我是 spring-security 的新手,我需要设置一个授权系统来保护 REST 服务。

就我而言,我的“用户”是不同部门和公司的一些服务器。所以我尝试将服务器配置为 MyUser,它是 UserDetails 的子类。

但是当我被要求授权服务器的 IP 地址时,我遇到了一个问题。我看到 WebSecurityConfigurerAdapter.configure(HttpSecurity http) 中有 IP 地址授权,我可以使用 configure(AuthenticationManagerBuilder auth){auth.userDetailsS​​ervice(myUserDetailsS​​ervice);} 检索配置。但是似乎configure(HttpSecurity http)方法只在系统启动时运行一次。

那么,我该怎么办?有什么方法可以添加自定义检查器或其他东西来验证 ip 地址吗?

这些是我的代码:

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.httpBasic().and()
            .authorizeRequests()
            .antMatchers("/order/**").hasAuthority("read_order") //(1)
            .antMatchers("/order/**").hasIpAddress("192.168.1.45") //(2)
            .anyRequest().denyAll();
        // @formatter:on
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }
}

使用实现UserDetailsService 的自定义userService,我可以将(1)行替换为数据库中的配置。这意味着当我更改配置时,Spring Security 将从数据库中加载它。我不需要重新启动系统。

我该如何做与 (2) 行类似的事情?

【问题讨论】:

    标签: spring-security


    【解决方案1】:

    我找到了解决方案。我不确定这是不是最好的方法,但它可以工作。这就是解决方案。

    首先,我们可以定义一个实现 AccessDecisionManager 的类:

    @Service
    public class ResourceAccessDecisionManager implements AccessDecisionManager {
      @Override
        public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
                throws
                AccessDeniedException, InsufficientAuthenticationException {
    //...
            HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
            String ip = request.getRemoteHost();
            Object principal = authentication.getPrincipal();
            User user;
            if (principal instanceof User){
                user=(User)principal;
                if (!ip.equals(user.getIpConfig())){
                    throw new AccessDeniedException("wrong ip");
                }
            }
    //...
        }
    //...
    }
    

    当然,您必须将 ip 配置存储在 User 类中。 然后,我们定义一个类 extends AbstractSecurityInterceptor implements Filter:

    @Service
    public class ResourceFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
    //...
        @Autowired
        public void setMyAccessDecisionManager(ResourceAccessDecisionManager resourceAccessDecisionManager) {
            super.setAccessDecisionManager(resourceAccessDecisionManager);
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
                throws IOException, ServletException {
            FilterInvocation fi = new FilterInvocation(servletRequest, servletResponse, filterChain);
            invoke(fi);
        }
    
        private void invoke(FilterInvocation fi) throws IOException, ServletException {
            InterceptorStatusToken token = super.beforeInvocation(fi);
            try {
                fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
            } finally {
                super.afterInvocation(token, null);
            }
        }
    //...
    }
    

    并将过滤器添加到安全配置类中:

        @Configuration
        @EnableWebSecurity
        public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
            private final ResourceService resourceService;
            private final UserService userService;
            private final HttpServletRequest request;
            private final ResourceFilterSecurityInterceptor resourceFilterSecurityInterceptor;
            private final EnvironmentConfig environmentConfig;
    
            @Autowired
            public SecurityConfiguration(ResourceService resourceService, UserService userService,
                    HttpServletRequest request,
                    ResourceFilterSecurityInterceptor resourceFilterSecurityInterceptor,
                    EnvironmentConfig environmentConfig) {
                this.resourceService = resourceService;
                this.userService = userService;
                this.request = request;
                this.resourceFilterSecurityInterceptor = resourceFilterSecurityInterceptor;
                this.environmentConfig = environmentConfig;
            }
    
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                // @formatter:off
                http
                        .httpBasic().and()
                        .authorizeRequests()
                        .antMatchers("/order/**").authenticated()
                        .anyRequest().authenticated()
                        .and().csrf().disable()
     .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                ;
    
                http.addFilterBefore(resourceFilterSecurityInterceptor,FilterSecurityInterceptor.class);
                // @formatter:on
            }
        //...
        }
    

    现在它可以工作了,但欢迎提出任何改进解决方案的建议。

    【讨论】:

      猜你喜欢
      • 2017-11-02
      • 2017-07-09
      • 2010-09-12
      • 2018-08-21
      • 2017-01-16
      • 2012-11-28
      • 2019-07-03
      相关资源
      最近更新 更多