Ваадин застревает в цикле при использовании безопасности Spring с формой входа в систему

Vaadin 19 + Spring Boot + пользовательский поток аутентификации

Работает: логин отображается правильно + аутентификация прошла успешно + перенаправление на правильный URL-адрес домашней страницы Проблема: на главной странице снова отображается поле входа

Моя реализация основана на https://vaadin.com/learn/tutorials/securing-your-app-with-spring-security/setting-up-spring-security

    @Autowired
    private UserService userService;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(new CustomAuthenticationProvider(userService))
                .userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * Require login to access internal pages and configure login form.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // Not using Spring CSRF here to be able to use plain HTML for the login page
        http.csrf().disable()
                // Register our CustomRequestCache that saves unauthorized access attempts, so
                // the user is redirected after login.
                .requestCache().requestCache(new CustomRequestCache())
                // Restrict access to our application.
                .and().authorizeRequests()
                // Allow all flow internal requests.
                .requestMatchers(SecurityUtil::isFrameworkInternalRequest).permitAll()
                // Allow all requests by logged in users.
                .anyRequest().authenticated()
                // Configure the login page.
                .and()
                .formLogin()
                .loginPage(URL_LOGIN).permitAll()
                .loginProcessingUrl(URL_LOGIN_PROCESSING)
                .failureUrl(URL_LOGIN_FAILURE)
                .successHandler(new CustomAuthenticationSuccessHandler())
                // Configure logout
                .and()
                .logout()
                .logoutUrl(URL_LOGOUT)
                .logoutSuccessUrl(URL_LOGOUT_SUCCESS);
    }

/**
 * Allows access to static resources, bypassing Spring security.
 */
@Override
public void configure(WebSecurity web) {
    web.ignoring().antMatchers(
            // Vaadin Flow static resources
            "/VAADIN/**",
            // the standard favicon URI
            "/favicon.ico",
            // the robots exclusion standard
            "/robots.txt",
            // style related files, needed here to prevent download of files between login and home
            "/icons/**",
            "/images/**",
            "/fonts/**",
            "/styles/**",
            "/sw-runtime-resources-precache.js",
            // web application manifest
            "/manifest.webmanifest",
            "/sw.js",
            "/offline-page.html",
            // (development mode) static resources
            "/frontend/**",
            // (development mode) webjars
            "/webjars/**",
            // (production mode) static resources
            "/frontend-es5/**", "/frontend-es6/**");
}

В журнале показаны повторяющиеся вызовы CustomAuthenticationProvider этого метода:

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException 

Может быть, это отсутствующая роль пользователя? Это нужно настраивать?

Мое приложение работало нормально и раньше, когда я впервые тестировал одну фиксированную учетную запись, например:

@Bean
@Override
public UserDetailsService userDetailsService() {
    UserDetails user = User.withUsername("username")
            .password("{noop}password")
            .roles("USER")
            .build();
    return new InMemoryUserDetailsManager(user);
}

person Frank    schedule 07.05.2021    source источник
comment
Вы не скопировали весь код класса конфигурации безопасности. Игнорированный путь важен!   -  person Simon Martinelli    schedule 07.05.2021
comment
Спасибо, хорошее замечание, теперь добавлен в вопрос   -  person Frank    schedule 07.05.2021
comment
Из вашего вопроса я не могу сказать, что не так. Не могли бы вы разместить проект на GitHub?   -  person Simon Martinelli    schedule 07.05.2021
comment
К сожалению, нет ... и зависит от другой службы для проверки входа в систему. Может быть, в сеансе парного программирования «код со мной»? ;-)   -  person Frank    schedule 07.05.2021


Ответы (2)


Проверьте, исключаете ли вы LoginView в ConfigureUIServiceInitListener.java

private void beforeEnter(BeforeEnterEvent event) {
        if (!LoginView.class.equals(event.getNavigationTarget()) // <--
            && !SecurityUtils.isUserLoggedIn()) { 
            event.rerouteTo(LoginView.class); 
        }
    }
person Ruslan    schedule 07.05.2021
comment
Ага, вот он! Спасибо за совет - person Frank; 10.05.2021

Как я уже подозревал, проблема заключалась в отсутствии РОЛИ.

В моем CustomAuthenticationProvider я возвращал такого пользователя:

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
   var email = authentication.getName();
   var password = authentication.getCredentials().toString();
   // Call here to backend to check login
   return new UsernamePasswordAuthenticationToken(email, password);
}

Что на самом деле возвращает пользователя, который аутентифицирован = false ...

Изменив код на:

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
   var email = authentication.getName();
   var password = authentication.getCredentials().toString();
   // Call here to backend to check login
   Collection<GrantedAuthority> roles = new ArrayList<>();
   roles.add(new SimpleGrantedAuthority("USER"));
   return new UsernamePasswordAuthenticationToken(email, password, roles);
}

пользователь аутентифицирован = true, и пользовательский интерфейс Vaadin работает должным образом.

person Frank    schedule 10.05.2021