如何使用spring-security动态配置ip地址?

问题描述 投票:1回答:1

我是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);
    }
}

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

我如何对(2)线做类似的事情?

spring-security
1个回答
0
投票

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

首先,我们可以定义一个实现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");
            }
        }
//...
    }
//...
}

当然,您必须在User类中存储ip配置。然后,我们定义一个类扩展AbstractSecurityInterceptor实现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
        }
    //...
    }

现在它可以工作,但任何建议都是受欢迎的,并且令人钦佩地改进了解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.