You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vaadin 24.3.x + Spring Boot 3.2.4 记住我认证开发求助(旧API已弃用)

Vaadin 24.3.x + Spring Boot 3.2.4 实现Remember-Me认证方案

针对Spring Security中rememberMe()方法弃用的情况,结合Vaadin登录组件,可通过以下步骤实现持久化的Remember-Me功能:

1. 更新Security配置类

注入用户详情服务和数据源,配置基于数据库的令牌存储,用新的lambda配置方式替代弃用方法:

@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends VaadinWebSecurity {

    private final UserDetailsService userDetailsService;
    private final DataSource dataSource;

    // 构造注入依赖
    public SecurityConfiguration(UserDetailsService userDetailsService, DataSource dataSource) {
        this.userDetailsService = userDetailsService;
        this.dataSource = dataSource;
    }

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

    // 配置数据库令牌存储
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        // 首次启动可开启自动建表,生产环境建议手动执行下方SQL
        // tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(
                authorize -> authorize.requestMatchers(new AntPathRequestMatcher("/images/*.png")).permitAll());

        // 放行line-awesome图标资源
        http.authorizeHttpRequests(authorize -> authorize
                .requestMatchers(new AntPathRequestMatcher("/line-awesome/**/*.svg")).permitAll());

        // 配置Remember-Me
        http.rememberMe(remember -> remember
                .userDetailsService(userDetailsService)
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(86400) // 令牌有效期1天
                .rememberMeParameter("remember-me") // 与登录表单参数名保持一致
        );

        super.configure(http);
        setLoginView(http, LoginView.class);
    }
}

2. 自定义登录视图添加"记住我"复选框

在Vaadin登录视图中添加复选框,并在登录提交时传递remember-me参数:

@Route("login")
public class LoginView extends VerticalLayout implements BeforeEnterObserver {

    private final LoginForm loginForm = new LoginForm();
    private final Checkbox rememberMe = new Checkbox("记住我");

    public LoginView() {
        setSizeFull();
        setAlignItems(Alignment.CENTER);
        setJustifyContentMode(JustifyContentMode.CENTER);

        loginForm.setAction("login");
        rememberMe.setValue(false);

        // 将复选框添加到登录表单的额外区域
        loginForm.addExtraHeaderContent(new Div(rememberMe));

        // 处理登录提交逻辑
        loginForm.addLoginListener(event -> {
            // 构建未认证的令牌
            Authentication authentication = UsernamePasswordAuthenticationToken.unauthenticated(
                    event.getUsername(), event.getPassword());
            // 设置请求详情
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(
                    VaadinServletRequest.getCurrent().getHttpServletRequest()));

            // 传递remember-me参数到请求中
            VaadinServletRequest.getCurrent().getHttpServletRequest().setParameter(
                    "remember-me", rememberMe.getValue() ? "on" : null);

            try {
                // 执行认证
                Authentication authenticated = AuthenticationManagerResolver.forHttpServletRequest()
                        .resolve(VaadinServletRequest.getCurrent().getHttpServletRequest())
                        .authenticate(authentication);
                SecurityContextHolder.getContext().setAuthentication(authenticated);
                // 登录成功跳转首页
                UI.getCurrent().navigate("");
            } catch (AuthenticationException e) {
                loginForm.setError(true);
            }
        });

        add(loginForm);
    }

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        // 已登录用户直接跳转首页
        if (SecurityContextHolder.getContext().getAuthentication() != null
                && SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
            event.forwardTo("");
        }
    }
}

3. 创建数据库令牌存储表(生产环境必做)

若使用数据库存储令牌,需手动创建persistent_logins表,SQL如下:

CREATE TABLE persistent_logins (
    username VARCHAR(64) NOT NULL,
    series VARCHAR(64) PRIMARY KEY,
    token VARCHAR(64) NOT NULL,
    last_used TIMESTAMP NOT NULL
);

注意事项

  • 确保UserDetailsService已正确实现,能从数据库读取用户信息
  • 若无需持久化令牌,可移除PersistentTokenRepository配置,使用默认内存存储(仅适用于开发环境)
  • 可根据业务需求调整tokenValiditySeconds参数,例如7天有效期设为604800

内容的提问来源于stack exchange,提问作者Patrick Lange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 06:00:00