Spring Security如何防止已登录用户访问登录页重复登录
问题说明
在Spring Boot应用中通过Spring Security配置登录认证时,出现已登录用户仍可访问/login端点、重复提交登录会生成新会话ID的问题,当前未自定义登录页,也未编写/login对应的自定义控制器,原有配置如下:
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().hasRole("ADMIN") .and() .formLogin() .loginPage("/login") .and() .httpBasic() .and() .logout() .logoutSuccessUrl("/") ; // Disabled to allow file upload. http .csrf().disable(); }
解决方案
不需要编写自定义控制器,也不需要替换默认登录页,直接修改Spring Security配置即可解决,核心逻辑是限制已认证用户对/login路径的访问,同时配置访问拦截后的跳转规则,修改后的完整配置如下:
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() // 限制/login仅允许未认证用户访问,已认证用户访问直接判定为无权限 .antMatchers("/login").access("permitAll and !isAuthenticated()") .anyRequest().hasRole("ADMIN") .and() // 配置无权限访问的处理逻辑 .exceptionHandling() .accessDeniedHandler((req, resp, ex) -> { // 已认证用户访问/login时直接重定向到系统首页 resp.sendRedirect("/"); }) .and() .formLogin() .loginPage("/login") // 登录成功后强制跳转到首页,避免回跳到登录页 .defaultSuccessUrl("/", true) .and() .httpBasic() .and() .logout() .logoutSuccessUrl("/") ; // 允许文件上传禁用CSRF http.csrf().disable(); }
配置说明
- 权限规则必须按顺序配置,
/login的访问规则要放在anyRequest()之前,Spring Security会按照配置顺序匹配路径,第一条匹配的规则会直接生效 access("permitAll and !isAuthenticated()")是Spring Security内置的权限表达式,含义是:未认证用户可以直接访问该路径,已认证用户不允许访问defaultSuccessUrl("/", true)的第二个参数设置为true时,无论用户登录前访问的是什么路径,登录成功后都会强制跳转到指定的根路径,避免出现登录后回跳登录页的异常- 整个配置不需要新增任何控制器、页面代码,完全在安全配置层实现逻辑,适配当前无自定义登录逻辑的场景
问题原因补充:Spring Security在未手动指定
loginPage时,内置的默认登录页自带已认证用户跳转判断;手动指定登录页路径后,这个内置判断会自动失效,因此需要手动添加访问限制。
内容的提问来源于stack exchange,提问作者Jsef bch
相关产品推荐
相关产品推荐

