Vaadin登录视图Chrome不保存密码及HTTPS重定向问题求助
Vaadin登录视图问题解决方案
问题1:浏览器不提示保存/自动填充登录密码
浏览器无法识别Vaadin默认生成的登录表单,导致密码保存、自动填充功能失效。
解决方案
手动为登录表单及字段添加标准name属性,帮助浏览器识别为登录表单:
@Route("login") @PageTitle("Login | My App") public class LoginView extends VerticalLayout implements BeforeEnterObserver { private final LoginForm login = new LoginForm(); public LoginView() { addClassName("login-view"); setSizeFull(); setAlignItems(Alignment.CENTER); setJustifyContentMode(JustifyContentMode.CENTER); login.setAction("login"); login.setForgotPasswordButtonVisible(false); // 添加标准表单属性,触发浏览器密码保存逻辑 login.getElement().setAttribute("name", "login-form"); login.getUsernameField().getElement().setAttribute("name", "username"); login.getPasswordField().getElement().setAttribute("name", "password"); add(new H1("My App"), login); } @Override public void beforeEnter(BeforeEnterEvent beforeEnterEvent) { if (beforeEnterEvent.getLocation().getQueryParameters().getParameters().containsKey("error")) { login.setError(true); } } }
同时确保测试环境使用HTTPS(需配置有效证书),浏览器仅在安全连接下触发密码保存提示。
问题2:HTTPS重定向导致密码功能异常
当前重定向配置强制所有请求走HTTPS,登录请求的重定向流程破坏了浏览器的密码保存上下文。
解决方案
修改重定向配置,排除登录路径,避免登录请求被重复重定向:
@Configuration public class HttpsConfiguration { @Autowired private Environment environment; @Bean public ServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() { @Override protected void postProcessContext(Context context) { SecurityConstraint securityConstraint = new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); // 包含所有路径,但排除登录相关请求 collection.addPattern("/*"); collection.addExcludedPattern("/login"); collection.addExcludedPattern("/login/*"); securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); } }; tomcat.addAdditionalTomcatConnectors(redirectConnector()); return tomcat; } private Connector redirectConnector() { Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL); connector.setScheme("http"); connector.setPort(Integer.parseInt(environment.getProperty("server.http.port"))); connector.setSecure(false); connector.setRedirectPort(Integer.parseInt(environment.getProperty("server.port"))); return connector; } }
问题3:setLoginView方法过时的替代方案
VaadinWebSecurityConfigurerAdapter中的setLoginView已过时,改用Spring Security标准的formLogin配置:
修改SecurityConfiguration类
@EnableWebSecurity @Configuration public class SecurityConfiguration extends VaadinWebSecurityConfigurerAdapter { // ... 原有依赖注入及Bean定义 public static final String LOGOUT_URL = "/"; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().ignoringRequestMatchers(requestUtil::isFrameworkInternalRequest); http.csrf().ignoringRequestMatchers(requestUtil::isEndpointRequest); http.requestCache().requestCache(vaadinDefaultRequestCache); http.authorizeRequests().antMatchers("/api/**").permitAll(); ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry urlRegistry = http .authorizeRequests(); urlRegistry.requestMatchers(requestUtil::isFrameworkInternalRequest).permitAll(); urlRegistry.requestMatchers(requestUtil::isAnonymousEndpoint).permitAll(); urlRegistry.requestMatchers(requestUtil::isAnonymousRoute).permitAll(); urlRegistry.requestMatchers(getDefaultHttpSecurityPermitMatcher()).permitAll(); urlRegistry.anyRequest().authenticated(); viewAccessChecker.enable(); // 替代过时的setLoginView http.formLogin() .loginPage("/login") // 指定登录视图路径 .loginProcessingUrl("/login") // 表单提交处理路径 .defaultSuccessUrl("/", true) // 登录成功后跳转首页 .failureUrl("/login?error"); // 登录失败跳转回登录页并携带错误参数 // 配置登出逻辑 http.logout() .logoutUrl(LOGOUT_URL) .logoutSuccessUrl("/login"); } // ... 原有configure(AuthenticationManagerBuilder)及configure(WebSecurity)方法 }
内容的提问来源于stack exchange,提问作者Süniür
相关产品推荐
相关产品推荐

