Пользователь не аутентифицирован

Я пытаюсь настроить клиента AuthenticationProvider с помощью Spring Security, но не успел заставить его работать. Я использую конфигурацию Java, поэтому я, вероятно, пропустил что-то простое, но поскольку большинство учебных материалов основано на XML-конфигурации, оно не выпрыгивает на меня.

Это использует 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

Это может быть не полный ответ, поскольку я немного борюсь с этим. Я использую собственный поставщик проверки подлинности и пользовательскую службу пользовательских данных. Я вижу то же поведение, что и вы - точки останова попадают в мою службу пользовательских данных, но не в моем провайдере проверки подлинности. Вот как выглядит мой весь класс конфигурации:

@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

Я столкнулся с одной и той же проблемой. Проблема заключается в вашем методе, который всегда будет возвращать false.

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

Измените приведенный выше метод ниже, и проблема будет решена.

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

Ответ 3

Вы забыли аннотацию @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

У меня была такая же проблема (мой пользовательский поставщик auth не попал) и решил проблему, введя springSecurityFilterChain, прочитав Почему Spring Безопасность работает в Tomcat, но не при развертывании в Weblogic? Таким образом, моя проблема, возможно, была связана с WebServer, но у меня была проблема с автоответчиком на Tomcat и теперь проверена моя работа по настройке Tomcat.

Я использую версию Spring boot 1.4.1, которая содержит Spring 4.3.3 и Spring Security 4.1.3 и после Traditional развертывание

Я тестировал свою конфигурацию против 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 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 создает SpringSecurityFilterChain из метода onStartup. Я ничего не реализовал, так как я пытаюсь использовать конфигурацию по умолчанию.

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;
    }
}

Это мой пользовательский поставщик auth для получения информации аутентификации от другого компонента через Restful request

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

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

Ответ 6

@EnableWebMvcSecurity будет устаревшим в 4.0 https://jira.spring.io/browse/SEC-2790

Возможно, вы захотите рассмотреть конфигурацию.

Ответ 7

<security:global-method-security pre-post-annotations="enabled"/>

Ответ 8

У меня была похожая проблема, и это было потому, что я использовал экземпляр @Autowire-ed AuthenticationManager, который был создан весенней загрузкой и просто не содержал мой пользовательский AuthenticationProvider.

После двух дней отладки весенних потрохов я наконец понимаю, что это не тот же экземпляр, как менеджер из org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#authenticationManager() который я настроил в своем настраиваемом WebSecurityConfigurerAdapter через WebSecurityConfigurerAdapter#configure(AuthenticationManagerBuilder).

Теперь я просто получаю этот экземпляр из WebSecurityConfigurerAdapter#authenticationManager() и GenericFilterBean его в мой GenericFilterBean, который обрабатывает мою логику аутентификации. Работает отлично.

Ответ 9

Также убедитесь, что вы отправляете имя пользователя и пароль с правильными заголовками.

Проверьте скручивание ниже и проверьте, был ли вызван класс

curl -X GET\http://localhost: 8080\-H 'Авторизация: Basic cmdlbGxtYW5AYnIuaWJtLmNvbTphYmM ='\-H 'X-Requested-With: XMLHttpRequest'\-H 'контроль кэша: нет кэша'