복붙노트

[SPRING] 스프링 보안을 구성하는 방법을 제공합니까?

SPRING

스프링 보안을 구성하는 방법을 제공합니까?

외부 파일에서 구성 세부 사항을 읽고 이에 따라 구성하는 방식으로 스프링 보안을 구성 할 수 있습니까?

(나는 런타임에 설정을 변경하는 것을 고려하지 않고있다. 시작시 파일을 읽는 것에 대해 이야기하고있다)

내 Sporing 보안 설정의 예는 다음과 같습니다.

@EnableWebSecurity
@Configuration
public class SecurityConfig {

    @Bean                                                             
    public UserDetailsService userDetailsService() throws Exception {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("user").password("userPass").roles("USER").build());
        manager.createUser(User.withUsername("admin").password("adminPass").roles("ADMIN").build());
        return manager;
    }


    @Configuration
    @Order(1)                                                        
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

        @Override       
        public void configure(AuthenticationManagerBuilder auth) 
          throws Exception {            
            auth.inMemoryAuthentication().withUser("user").password("user").roles("USER");
            auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
        }

        protected void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/api/v1/**")                               
                .authorizeRequests()
                .antMatchers("/api/v1/**").authenticated()
                    .and()
                .httpBasic();
        }
    }

    @Configuration
    @Order(2)
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override       
        public void configure(AuthenticationManagerBuilder auth) 
          throws Exception {

            auth.inMemoryAuthentication().withUser("user1").password("user").roles("USER");
            auth.inMemoryAuthentication().withUser("admin1").password("admin").roles("ADMIN");
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/api/test/**")
                .authorizeRequests()
                .antMatchers("/api/test/**").authenticated()
                    .and()
                .formLogin();
        }
    }
}

보시다시피 여러 구성 (Order () 주석을 살펴보십시오)을 사용하고 있습니다. 내가 할 수 있기를 원하는 것은 시작 번호 및 구성 유형을 결정할 때입니다. 첫 번째 클라이언트의 예는 LdapConfig 및 SamlConfig와 같은 2 개의 구성을 원할 수 있습니다. 기타는 LdapConfig 및 SqlConfig를 원하고 세 번째는 4-5 구성을 원할 수 있습니다. 그렇게 할 수 있습니까?

참고 : 저는 Spring Boot를 사용하지 않습니다.

편집하다

내가 왜 이런 식으로 원하는지 요약 :

고객이란 내 제품을 구매할 회사를 의미합니다. 그리고 사용자는 내 제품을 구입 한 회사의 실제 최종 사용자를 의미합니다. 그래서 저는이 제품을 3 개 회사에 선적했습니다. 먼저 LDAP 인증 흐름과 google-oauth2 인증 흐름을 갖도록 구성합니다. 이 첫 번째 회사의 사용자는이 두 가지 옵션으로 로그인 페이지를 보게됩니다. 이제 회사 2는 LDAP 인증 흐름과 SAM 인증 흐름을 가질 수 있으며 해당 회사의 사용자는이 두 가지 옵션을 보게됩니다. 그리고 회사는 시작하기 전에 사용 가능한 옵션을 선택합니다.

해결법

  1. ==============================

    1.속성을로드 할 수 있습니다 (예 : WebApplicationContext를 작성하기 전에 DB 신임을 작성하십시오. 다음 예제를보십시오.

    속성을로드 할 수 있습니다 (예 : WebApplicationContext를 작성하기 전에 DB 신임을 작성하십시오. 다음 예제를보십시오.

    public class WebAppInitializer implements WebApplicationInitializer {
    
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // Tell the EnvironmentManager to load the properties. The path to the config 
        // file is set by Tomcat's home variable. If you change the container you might 
        // need to change this, too.
        EnvironmentParamManager.initialize(System.getProperty("catalina.home"));
    
        // now create the Spring Context
        AnnotationConfigWebApplicationContext rootContext = 
            new AnnotationConfigWebApplicationContext();
        rootContext.register(RootConfig.class);
        rootContext.setServletContext(servletContext);
        SpringApplicationContextProvider.configure(rootContext);
        // ... other config
    }
    

    EnvironmentParamManager는 다음과 같을 수 있습니다. 응용 프로그램의 비 스프링 부분에서도 모든 곳에서 속성에 액세스 할 수 있도록 정적으로 만들려고했습니다.

    public class EnvironmentParamManager {
    
      private static Properties properties = new Properties();
    
      public static void initialize(String pathToConfigFile) {
        BufferedInputStream stream;
        try {
            stream = new BufferedInputStream(new FileInputStream(
               pathToConfigFile + "myconfig.props"));
            properties.load(stream);            
            stream.close();
        } catch (Throwable e) {
            throw new Error("Cannot read environment settings from file " + pathToConfigFile);
        }
      }
    
      public static String getMongoDBHostname() {
        return properties.getProperty("mongodb.username");
      }
    
    }
    

    JavaConfig를 사용할 때 Bean 생성 단계에서 다음과 같이 쉽게 구성 등록 정보에 액세스 할 수 있습니다.

    @Configuration
    public class CoreConfig {
    
    @Bean
    public MongoDbFactory mongoDbFactory() throws Exception {
      ...
      ServerAddress address = new 
         ServerAddress(EnvironmentParamManager.getMongoDBHost(), 
                       EnvironmentParamManager.getMongoDBPort());
      ...
    }
    

    물론 Spring 컨텍스트가 부트 스트랩되기 전에 로컬 속성 파일을로드하는 것과 같은 방법으로 LDAP 등의 다른 서비스에 자유롭게 연결할 수 있습니다. 희망이 도움이됩니다.

  2. ==============================

    2.스프링 @Conditional 주석을 사용하여 구성 요소를 선택적으로로드 할 수 있습니다.

    스프링 @Conditional 주석을 사용하여 구성 요소를 선택적으로로드 할 수 있습니다.

    configs는 다음과 같습니다.

    @Configuration(value = "some.security.config")
    @Conditional(value = LoadSecurityConfigCondition.class)
    public class SomeSecurityConfig {
      // some code
    }
    
    @Configuration(value = "other.security.config")
    @Conditional(value = LoadSecurityConfigCondition.class)
    public class OtherSecurityConfig {
      // other code
    }
    

    그런 다음 LoadSecurityConfigCondition.class는 구성 요소가로드되는지 여부를 결정합니다.

    @Component
    public class LoadSecurityConfigCondition implements Condition {
    
      @Override
      public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
        boolean enabled = false;
    
        if (metadata.isAnnotated(Configuration.class.getName())) {
          final String name = (String) metadata.getAnnotationAttributes(Configuration.class.getName()).get("value");
          if (StringUtils.isNotBlank(name)) {
            /* Here you may load your config file and 
             * retrieve the information on wether to load 
             * the config identified by its name.
             */
            enabled = ...;
          }
        }
        return enabled;
      }
    }
    

    이 예제에서 config 항목은 @Configuration 이름으로 생성 될 수 있으며 목적을 명확히하기 위해 .enabled가 뒤에 붙습니다.

    some.security.config.enabled=true
    other.security.config.enabled=false
    
  3. ==============================

    3.이것을 시도해 봤니?

    이것을 시도해 봤니?

    @EnableWebSecurity
    @Configuration
    public class SecurityConfig {
    
        @Bean
        public UserDetailsService userDetailsService() throws Exception {
            InMemoryUserDetailsManager manager = new MemoryUserDetailsManager();
           manager.createUser(User.withUsername("user").password("userPass").roles("USER").build());
        manager.createUser(User.withUsername("admin").password("adminPass").roles("ADMIN").build());
        return manager;
    }
    
    
    @Configuration
    @Profile({"profile1", "profile2"})
    @Order(1)
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
    
        @Override
        public void configure(AuthenticationManagerBuilder auth)
                throws Exception {
            auth.inMemoryAuthentication().withUser("user").password("user").roles("USER");
            auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
        }
    
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .antMatcher("/api/v1/**")
                    .authorizeRequests()
                    .antMatchers("/api/v1/**").authenticated()
                    .and()
                    .httpBasic();
        }
    }
    
    @Configuration
    @Profile("profile1")
    @Order(2)
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
    
        @Override
        public void configure(AuthenticationManagerBuilder auth)
                throws Exception {
    
            auth.inMemoryAuthentication().withUser("user1").password("user").roles("USER");
            auth.inMemoryAuthentication().withUser("admin1").password("admin").roles("ADMIN");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .antMatcher("/api/test/**")
                    .authorizeRequests()
                    .antMatchers("/api/test/**").authenticated()
                    .and()
                    .formLogin();
            }
        }
    }
    

    따라서 spring.profiles.active = profile1을 사용하면 두 구성 모두 spring.profiles.active = profile2로로드되고 첫 번째 구성 만로드됩니다. 물론 두 개 이상의 프로필을 사용할 수 있으며 시작할 때 둘 이상의 프로필을 활성화 할 수도 있습니다 (쉼표로 구분). 요구 사항에 맞는 방식으로 구성과 프로파일을 분리하면됩니다.

  4. from https://stackoverflow.com/questions/48806067/providing-way-to-configure-spring-security by cc-by-sa and MIT license