2017-12-06 11 views
1

저는 스프링 보안에 익숙하지 않아 REST 서비스를 보호하기 위해 인증 시스템을 설정해야합니다.스프링 보안을 사용하여 동적으로 IP 주소를 구성하는 방법은 무엇입니까?

내 경우에는 "사용자"가 다른 부서와 회사의 일부 서버입니다. 그래서 UserDetails의 하위 클래스 인 MyUser로 서버를 설정하려고했습니다.

하지만 서버의 IP 주소를 승인하도록 요청 받았을 때 문제가 발생했습니다. WebSecurityConfigurerAdapter.configure (HttpSecurity http)에 IP 주소 권한이 있다는 것을 알았고 configure (AuthenticationManagerBuilder auth) {auth.userDetailsService (myUserDetailsService);}를 사용하여 구성을 검색 할 수 있습니다. 그러나 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) 라인을 교체 할 수 있습니다. 즉, 구성을 변경하면 스프링 보안이 데이터베이스에서로드합니다. 시스템을 다시 시작할 필요가 없습니다.

어떻게하면 (2) 줄과 비슷한 작업을 수행 할 수 있습니까?

답변

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"); 
      } 
     } 
//... 
    } 
//... 
} 

은 확실히 당신이 사용자 클래스 내에서 IP 구성을 저장했다.

@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); 
     } 
    } 
//... 
} 

그리고 보안 설정 클래스에 필터를 추가 : 다음 , 우리는 클래스가 AbstractSecurityInterceptor에 필터를 구현 확장 정의 이제

@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 
     } 
    //... 
    } 

가 작동 할 수 있지만, 어떤 제안은 환영하고 향상에 감탄 해결책.