如何解决Vaadin 在使用带有登录表单的 Spring security 时陷入循环
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);
}
这实际上返回了一个经过身份验证的用户=假...
通过将代码更改为:
@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 用户界面按预期工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。