Vaadin14升级Vaadin23后用户频繁自动登出问题排查与解决
已登录用户频繁自动登出/登录多次才成功的Vaadin问题排查与解决
问题现象
- Vaadin14环境下,已登录用户会频繁出现自动登出情况;升级至Vaadin23后问题未解决,还新增了用户有时需多次点击登录按钮才能成功登录的现象。
- 网站前端无报错提示,初始日志中也未发现相关异常信息。
- 项目基于Vaadin官方启动模板搭建。
相关配置代码
SecurityConfiguration
@EnableWebSecurity @Configuration public class SecurityConfiguration extends VaadinWebSecurity { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().requestMatchers(new AntPathRequestMatcher("/images/*.png")).permitAll(); http.authorizeRequests().requestMatchers(new AntPathRequestMatcher("/VAADIN/**")).permitAll(); //http.authorizeRequests().requestMatchers(new AntPathRequestMatcher("/VAADIN/*")).permitAll(); super.configure(http); setLoginView(http, LoginView2.class); } @Override public void configure(WebSecurity web) { } }
CustomAuthenticationProvider
@Component public class CustomAuthenticationProvider implements AuthenticationProvider { private final Logger logger = LogManager.getLogger(CustomAuthenticationProvider.class); @Autowired private DatabaseController dbc; @Autowired private UserRepository _userRepository; @Autowired private MsGraphService _msGraphService; CustomAuthenticationProvider(UserRepository userRepository) { _userRepository = userRepository; } //@Autowired //private AuthenticationManager authenticationManager; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { //user authentication by pw stored in DB ... if(authResult) { //add authorities UserSessionInfo info = new UserSessionInfo(user, organisations, admins, mans, accesslists); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(info, password, autorities); logger.info("user "+user.email+" successfully logged in"); return token; } else { logger.info("user "+user.email+" entered the wrong password"); throw new BadCredentialsException("Authentication failed"); } } @Override public boolean supports(Class<?> aClass) { return aClass.equals(UsernamePasswordAuthenticationToken.class); } }
ServiceListener(调试用)
升级至Vaadin23后,尝试通过监听Vaadin服务事件排查问题,未获取有效线索:
public class ServiceListener implements VaadinServiceInitListener { private final Logger logger = LogManager.getLogger(ServiceListener.class); @Override public void serviceInit(ServiceInitEvent event) { logger.info("serviceInit"); event.getSource().addSessionInitListener( initEvent -> logger.info("A new Session has been initialized!")); event.getSource().addUIInitListener( initEvent ->logger.info("A new UI has been initialized!")); event.getSource().addSessionDestroyListener(destroyed-> { logger.info("session destroyed "+destroyed.getSource()); }); } }
调试发现的关键日志
开启org.springframework.security调试日志后,捕获到会话相关异常:
2023-04-05 15:00:09.255 DEBUG 1 --- [https-jsse-nio-8989-exec-10] o.s.s.w.session.SessionManagementFilter : Requested session ID 594190F39E29B84F68291BDDCA5E3DCC is invalid. ... org.springframework.security.access.AccessDeniedException: Access is denied ...
问题根源与解决办法
根源分析
经过超100小时调试验证,确认问题是同一域名下不同端口运行了两个Vaadin站点:浏览器会为同域名的站点共用Cookie,导致两个站点不断互相覆盖Cookie中的SessionId,最终引发会话失效、权限拒绝等问题。
解决步骤
在项目的application.properties文件中,为当前站点配置独立的会话Cookie名称,避免与同域名下的其他站点冲突:
server.servlet.session.cookie.name=somewebsitecookiename
内容的提问来源于stack exchange,提问作者syn-thomas
相关产品推荐
相关产品推荐

