Vaadin在登录表单中使用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);
}

检查是否在ConfigureUIServiceInitListener.java 中排除LoginView

private void beforeEnter(BeforeEnterEvent event) {
if (!LoginView.class.equals(event.getNavigationTarget()) // <--
&& !SecurityUtils.isUserLoggedIn()) { 
event.rerouteTo(LoginView.class); 
}
}

正如我已经怀疑的,问题是缺少一个角色。

在我的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);
}

用户已经authentication=true,并且Vaadin UI按预期工作。

最新更新