복붙노트

[SPRING] 사용자 지정 인증 공급자가 호출되지 않음

SPRING

사용자 지정 인증 공급자가 호출되지 않음

나는 Spring Security로 고객 AuthenticationProvider를 설정하려고 노력하고 있지만 작동하는 데 많은 행운이 없다. XML 구성을 기반으로하는 학습 자료가 많기 때문에 Java 구성을 사용하고 있습니다.

이것은 Spring v4.0.1.RELEASE를 사용하지만 Spring Security v3.2.2.RELEASE를 사용합니다. 아마 버전 번호 충돌?

내가 말할 수있는 한, 내 공급자를 만드는 것 뿐이야.

public class KBServicesAuthProvider implements AuthenticationProvider {
  @Autowired
  private ApplicationConfig applicationConfig;

  @Autowired
  private SessionServiceClient sessionServiceClient;

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String email = (String) authentication.getPrincipal();
    String password = (String) authentication.getCredentials();

    try {
      KBSessionInfo sessionInfo = sessionServiceClient.login(applicationConfig.getKbServicesPresenceId(), email,
          password);

      List<GrantedAuthority> grantedRoles = new ArrayList<>();
      for (KBRoleMembership role : sessionInfo.getAuthenticatedUser().getRoleMemberships()) {
        grantedRoles.add(new SimpleGrantedAuthority(role.getRoleId()));
      }

      return new UsernamePasswordAuthenticationToken(email, password, grantedRoles);
    } catch (InvalidSessionException e) {
      throw new AuthenticationCredentialsNotFoundException("Username or password was not accepted", e);
    }
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
  }
}

그런 다음 내 보안 설정을 설명하는 클래스를 설정하십시오. 이 클래스는 내 제공자와 연결됩니다.

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired(required = true)
  SessionServiceClient sessionServiceClient;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/").permitAll().anyRequest().authenticated();
    http.formLogin().loginPage("/login").permitAll().and().logout().permitAll();
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(getKBServicesAuthenticationProvider());
  }

  @Bean
  protected AuthenticationProvider getKBServicesAuthenticationProvider() {
    return new KBServicesAuthProvider();
  }
}

하지만 로그에서 아무 것도 볼 수없고 내 디버그 지점 중 하나도 공격을 받고 있지 않습니다. 응용 프로그램은 안전하지 않은 역할을합니다 (그래서 다양한 URL에 도달 할 수 있습니다).

내가 무엇을 확인해야하는지에 대한 아이디어가 있습니까?

해결법

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

    1.이것은 내가 완전히 이걸 고민하고 있기 때문에 완전한 대답이 아닐 수도 있습니다. 사용자 지정 인증 공급자와 사용자 지정 사용자 세부 정보 서비스를 사용하고 있습니다. 내 사용자 세부 정보 서비스에서 중단 점에 도달하지만 내 인증 공급자에서는 중단되지 않습니다. 다음은 내 전체 config 클래스의 모습입니다.

    이것은 내가 완전히 이걸 고민하고 있기 때문에 완전한 대답이 아닐 수도 있습니다. 사용자 지정 인증 공급자와 사용자 지정 사용자 세부 정보 서비스를 사용하고 있습니다. 내 사용자 세부 정보 서비스에서 중단 점에 도달하지만 내 인증 공급자에서는 중단되지 않습니다. 다음은 내 전체 config 클래스의 모습입니다.

    @Configuration
    @EnableWebMvcSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private CustomUserDetailsService userDetailsService;
        @Autowired
        private CustomAuthenticationProvider customAuthenticationProvider;
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService);
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            AuthenticationProvider rememberMeAuthenticationProvider = rememberMeAuthenticationProvider();
            TokenBasedRememberMeServices tokenBasedRememberMeServices = tokenBasedRememberMeServices();
    
            List<AuthenticationProvider> authenticationProviders = new ArrayList<AuthenticationProvider>(2);
            authenticationProviders.add(rememberMeAuthenticationProvider);
            authenticationProviders.add(customAuthenticationProvider);
            AuthenticationManager authenticationManager = authenticationManager(authenticationProviders);
    
            http
                    .csrf().disable()
                    .headers().disable()
                    .addFilter(new RememberMeAuthenticationFilter(authenticationManager, tokenBasedRememberMeServices))
                    .rememberMe().rememberMeServices(tokenBasedRememberMeServices)
                    .and()
                    .authorizeRequests()
                    .antMatchers("/js/**", "/css/**", "/img/**", "/login", "/processLogin").permitAll()
                    .antMatchers("/index.jsp", "/index.html", "/index").hasRole("USER")
                    .antMatchers("/admin", "/admin.html", "/admin.jsp", "/js/saic/jswe/admin/**").hasRole("ADMIN")
                    .and()
                    .formLogin().loginProcessingUrl("/processLogin").loginPage("/login").usernameParameter("username").passwordParameter("password").permitAll()
                    .and()
                    .exceptionHandling().accessDeniedPage("/login")
                    .and()
                    .logout().permitAll();
        }
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/js/**", "/css/**", "/img/**");
        }
    
        @Bean
        public BCryptPasswordEncoder bCryptPasswordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
        @Bean
        public AuthenticationManager authenticationManager(List<AuthenticationProvider> authenticationProviders) {
            return new ProviderManager(authenticationProviders);
        }
    
        @Bean
        public TokenBasedRememberMeServices tokenBasedRememberMeServices() {
            return new TokenBasedRememberMeServices("testKey", userDetailsService);
        }
    
        @Bean
        public AuthenticationProvider rememberMeAuthenticationProvider() {
            return new org.springframework.security.authentication.RememberMeAuthenticationProvider("testKey");
        }
    
        protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
        }
    }
    

    나는 방금 HttpSecurity 객체에 인증 공급자를 추가하면 내 중단 점에 충돌이 발생한다는 것을 발견했습니다.

    http
                    .csrf().disable()
                    .headers().disable()
                    .authenticationProvider(customAuthenticationProvider)
    

    내 목표는이 구성으로하지 않는 BCryptPasswordEncoder를 작동시키는 것입니다. 모든 것이 잘못된 자격 증명으로 반환됩니다. 어쨌든, 그냥 나눌 줄 알았어.

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

    2.나는 똑같은 문제에 직면했다. 문제는 항상 false를 리턴 할 당신의 방법에있다.

    나는 똑같은 문제에 직면했다. 문제는 항상 false를 리턴 할 당신의 방법에있다.

    @Override
    public boolean supports(Class<?> authentication) {
          return authentication.equals
      (UsernamePasswordAuthenticationToken.class);
    }
    

    위의 방법을 아래의 방법으로 변경하면 문제가 해결됩니다.

    @Override
        public boolean supports(Class<?> authentication) {
              return (UsernamePasswordAuthenticationToken.class
                        .isAssignableFrom(authentication));
        }
    
  3. ==============================

    3.@Autowired 주석을 잊어 버렸습니다.

    @Autowired 주석을 잊어 버렸습니다.

    @Autowired
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.authenticationProvider(getKBServicesAuthenticationProvider());
    }
    

    또한 .antMatchers ( "/"). permitAll ()을 제거 할 수 있습니다.

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests().anyRequest().authenticated();
      http.formLogin().loginPage("/login").permitAll().and().logout().permitAll();
    }
    
  4. ==============================

    4.Spring Security가 Tomcat에서 작동하는 이유를 읽은 후에 springSecurityFilterChain을 도입하여 동일한 문제 (내 맞춤형 인증 공급자가 공격받지 못함)를 해결하고이 문제를 해결했지만 Weblogic에 배포 할 때가 아닙니다. 그래서 문제는 아마 WebServer와 관련이 있을지 모르지만 Tomcat에서도 맞춤형 인증 제공자 문제를 겪었고 이제 Tomcat에서 내 구성이 작동하는지 확인했습니다.

    Spring Security가 Tomcat에서 작동하는 이유를 읽은 후에 springSecurityFilterChain을 도입하여 동일한 문제 (내 맞춤형 인증 공급자가 공격받지 못함)를 해결하고이 문제를 해결했지만 Weblogic에 배포 할 때가 아닙니다. 그래서 문제는 아마 WebServer와 관련이 있을지 모르지만 Tomcat에서도 맞춤형 인증 제공자 문제를 겪었고 이제 Tomcat에서 내 구성이 작동하는지 확인했습니다.

    나는 Spring 4.3.3과 Spring Security 4.1.3을 포함하고 전통적인 배치를 따르는 Spring boot 1.4.1 버전을 사용하고있다.

    Tomcat v9.0 및 WebLogic 12c R2에 대한 구성을 테스트하고이 구성이 모두 작동하는지 확인했습니다. 적어도 Tomcat을 사용하는 누군가에게 도움이되기를 바랍니다.

    아래는 메인 클래스에서 시작된 구성입니다.

    Application.java

    public class Application {
        public static void main( String[] args ) {
            SpringApplication.run(new Class[] {AppConfig.class, Initializer.class, SecurityInitializer.class}, args);
        }
    }
    

    Initializer.java

    public class Initializer extends SpringBootServletInitializer implements WebApplicationInitializer {
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
            return application.sources(AppConfig.class);
        }
    
        @Override
        public void onStartup(ServletContext container) throws ServletException {
            AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
            rootContext.register(AppConfig.class);
    
            // Manage the lifecycle of the root application context
            container.addListener(new ContextLoaderListener(rootContext));
    
            // Create the dispatcher servlet's Spring application context
            AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
            dispatcherContext.register(WebConfig.class);
    
            // Register and map the dispatcher servlet
            ServletRegistration.Dynamic dispatcher = container.addServlet("my-servlet", new DispatcherServlet(dispatcherContext));
            dispatcher.setLoadOnStartup(1);
            dispatcher.addMapping("/*");
        }
    }
    

    여기서 AbstractSecurityWebApplicationInitializer는 onStartup 메소드에서 springSecurityFilterChain을 빌드합니다. 기본 구성을 사용하려고하므로 아무 것도 구현하지 않았습니다.

    SecurityInitializer.java

    public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
    
    }
    

    AppConfig.java

    @Configuration
    @EnableAutoConfiguration
    @EnableScheduling
    @EnableMBeanExport
    @EnableAsync
    @EnableAspectJAutoProxy
    @ComponentScan("com.my.package")
    public class AppConfig {
    
    
    }
    

    SecurityConfig.java

    @Configuration
    @EnableWebSecurity
    @ComponentScan("com.my.package")
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private RestfulRemoteAuthenticationProvider restfulRemoteAuthenticationProvider;
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(restfulRemoteAuthenticationProvider);
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable();
            http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
        }
    }
    

    WebConfig.java

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = "com.my.controller.package")
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Bean
        public InternalResourceViewResolver internalViewResolver() {
            InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
            viewResolver.setPrefix("/WEB-INF/jsp/");
            viewResolver.setSuffix(".jsp");
            viewResolver.setOrder(1);
            return viewResolver;
        }
    }
    

    이것은 안정적인 요청을 통해 다른 구성 요소에서 인증 정보를 가져 오는 내 사용자 지정 인증 공급자입니다.

    RestfulRemoteAuthenticationProvider.java

    @Component
    public class RestfulRemoteAuthenticationProvider implements AuthenticationProvider {
    
        @Autowired
        private ManagementClientAdapterFactory managementClientAdapterFactory;
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            String username = authentication.getName();
            String password = authentication.getCredentials().toString();
    
            // my logic to get and configure authSource which is my environment specific thing, also same for RemoteAuthRequestResult
    
            RemoteAuthRequestResult result = (RemoteAuthRequestResult)authSource.sendRequest();
            if(result.isAuthenticated()) {
                List<GrantedAuthority> grantedAuths = new ArrayList<>();
                grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
                return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
            }
            throw new BadCredentialsException("User not found by given credential");
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return authentication.equals(UsernamePasswordAuthenticationToken.class);
        }
    }
    
  5. ==============================

    5.

       Something like should be present in java config 
    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled=true)
    public class HelloMethodSecurityConfig {
    }
    
  6. ==============================

    6.@EnableWebMvcSecurity는 4.0 https://jira.spring.io/browse/SEC-2790에서 더 이상 사용되지 않습니다.

    @EnableWebMvcSecurity는 4.0 https://jira.spring.io/browse/SEC-2790에서 더 이상 사용되지 않습니다.

    구성을 다시 고려할 수도 있습니다.

  7. ==============================

    7.

    <security:global-method-security pre-post-annotations="enabled"/>
    
  8. from https://stackoverflow.com/questions/22453550/custom-authentication-provider-not-being-called by cc-by-sa and MIT license