- 描述错误**在Spring Security 5中有效的配置规则在6.0.1中无效。
在将安全配置迁移到Spring Security 6.0.1之后,如果我们使用了一个错误的凭据,那么浏览器就会被卡住,Hibernate会无休止地运行查询,并且控件不会重定向到登录页面。
为了从Spring Security 5(Spring启动2.1.3.RELEASE)迁移到Spring Security 6.0.1(Spring启动3.0.2),我将SecurityConfiguration.java
文件从
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.authorizeRequests()
.antMatchers("/","/h2-console/**").permitAll()
.antMatchers("/admin").access("hasAuthority('ADMIN')")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login").permitAll()
.and()
.httpBasic();
http
.csrf().disable();
http
.headers().frameOptions().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userDetailsServiceBean())
.passwordEncoder(passwordEncoder());
}
到
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/h2-console/**")
.permitAll()
.requestMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.failureUrl("/login?error=true")
.permitAll())
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll())
.httpBasic(Customizer.withDefaults());
http
.csrf().disable();
http
.headers().frameOptions().disable();
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder())
.and()
.build();
}
}
并将SSUserDetailsService.java
文件从
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
User appUser = userRepository.findByUsername(username);
if(appUser == null){
System.out.println("User not found with the provided username" + appUser.toString());
return null;
}
System.out.println("User from username " + appUser.toString());
return new org.springframework.security.core.userdetails.User(
appUser.getUsername(),
appUser.getPassword(),
getAuthorities(appUser));
} catch (Exception e){
throw new UsernameNotFoundException("User not found");
}
}
private Set<GrantedAuthority> getAuthorities(User appUser) {
Set<GrantedAuthority> authorities = new HashSet<>();
for(Role role: appUser.getRoles()){
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRole());
authorities.add(grantedAuthority);
}
System.out.println("User authorities are" + authorities.toString());
return authorities;
}
到
@Override
public UserDetails loadUserByUsername(String username){
try {
User appUser = userRepository.findByUsername(username);
if (appUser == null) {
System.out.println("User not found with the provided username" + appUser.toString());
return null;
}
System.out.println("User from username " + appUser.getUsername());
return org.springframework.security.core.userdetails.User
.withUsername(appUser.getUsername())
.password(appUser.getPassword())
.roles(getAuthorities(appUser))
.build();
} catch (Exception e) {
throw new UsernameNotFoundException("User not found");
}
}
private String[] getAuthorities(User appUser) {
var authorities = new HashSet<String>();
for (var role : appUser.getRoles()) {
var grantedAuthority = new SimpleGrantedAuthority(role.getRole());
authorities.add(grantedAuthority.getAuthority());
}
System.out.println("User authorities are " + authorities);
return Arrays.copyOf(authorities.toArray(),authorities.size(), String[].class);
}
- 重现**重现错误行为的步骤(springboot_3.0分支包含Spring Security 6.0.1(Spring Boot 3.0.2)的示例):
- git克隆-b springboot_3.0 https://github.com/mhussainshah1/SpringBoot_404.git
1.光盘Spring启动_404 - mvn清洁包
- mvnSpring罩:运行
1.打开带有链接http://localhost:8080/的浏览器
1.使用用户/密码登录(用户为admin,密码为password)
Hibernate: select u1_0.id,u1_0.email,u1_0.enabled,u1_0.first_name,u1_0.last_name,u1_0.password,u1_0.username from user_data u1_0 where u1_0.username=?
Hibernate: select r1_0.user_id,r1_1.id,r1_1.role from user_data_roles r1_0 join role r1_1 on r1_1.id=r1_0.role_id where r1_0.user_id=?
User from username admin
User authorities are [ADMIN]
1.使用错误凭据登录(用户为dave,密码为begreat)
浏览器卡顿,Hibernate查询无休止运行,直到CTRL + C
命令停止
Hibernate: select u1_0.id,u1_0.email,u1_0.enabled,u1_0.first_name,u1_0.last_name,u1_0.password,u1_0.username from user_data u1_0 where u1_0.username=?
Hibernate: select u1_0.id,u1_0.email,u1_0.enabled,u1_0.first_name,u1_0.last_name,u1_0.password,u1_0.username from user_data u1_0 where u1_0.username=?
Hibernate: select u1_0.id,u1_0.email,u1_0.enabled,u1_0.first_name,u1_0.last_name,u1_0.password,u1_0.username from user_data u1_0 where u1_0.username=?
Hibernate: select u1_0.id,u1_0.email,u1_0.enabled,u1_0.first_name,u1_0.last_name,u1_0.password,u1_0.username from user_data u1_0 where u1_0.username=?
- 预期行为**输入错误凭据(用户名或密码)后,登录页面应显示以下文本
Invalid username or password
- 预期行为**输入错误凭据(用户名或密码)后,登录页面应显示以下文本
重现成功行为的步骤(主分支包含Spring Security 5(Spring Boot 2.1.3.RELEASE)的示例):
- git克隆https://github.com/mhussainshah1/SpringBoot_404.git
1.光盘Spring启动_404 - mvn清洁包
- mvnSpring罩:运行
1.打开带有链接http://localhost:8080/的浏览器
1.登录页面将成功打开
1.使用用户名/密码登录(用户名为admin,密码为password)主页将在链接http://localhost:8080/处打开
1.使用错误凭据登录(用户为dave,密码为begreat),应重定向到登录页面,然后
比如Invalid username or password
- 示例**一个指向GitHub仓库的minimal, reproducible sample链接。(参见springboot_3.0分支)。
2条答案
按热度按时间9udxz4iz1#
我的怀疑是,你陷入了一些
AuthorizationFilter
转发循环。**要排除此问题,*您可以检查用(已弃用但仍可用)
.authorizeRequests()
替换.authorizeHttpRequests()
是否会显示相同的问题(它在幕后使用FilterSecurityInterceptor
而不是AuthorizationFilter)。如果是这样-您仍可以尝试我的提示,在下面添加“/login”,但如果使用其他方法时问题消失,您可以如下所示替换弃用项:装回并在
.authorizeHttpRequests()
后添加(链)以下之一:或
这是一个有点弱...
我可能还会尝试**添加
"/login*"
**作为允许所有调用的第一个requestMatchers
中的第三个字符串,因为在转发时尝试对login?...
进行身份验证可能(!)是进入循环的原因。我在迁移Spring安全性时也遇到过类似的问题,而向autorization过滤器发送指令为我完成了这项工作--所以我认为无论如何,有它们也没有坏处。
您可以在此处cf:Spring security 6.0 AuthorizationFilter - questionable default for shouldFilterAllDispatcherTypes
avkwfej42#
我已将
SecurityConfiguration.java
文件中的以下方法从到
使用
DaoAuthenticationProvider
可以在身份验证失败时停止循环,并正常工作