几天来,我一直在尝试解决 Spring Security 6 的问题。我几乎阅读了 Spring Security 6 的所有 Spring 文档,也看了几个教程,但就是看不出错误在哪里。我在放大镜下看代码:
WebSecurityConfigurer.class:
package com.transfer.market.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager;
@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer {
private final String ADMIN;
private final String ADMIN_PASS;
private final String SUPER;
private final String SUPER_PASS;
@Autowired
public WebSecurityConfigurer(AppSecurityExternalConfig appSecurityExternalConfig) {
this.ADMIN = appSecurityExternalConfig.getUser().getAdmin();
this.ADMIN_PASS = appSecurityExternalConfig.getPassword().getAdmin();
this.SUPER = appSecurityExternalConfig.getUser().getSup();
this.SUPER_PASS = appSecurityExternalConfig.getPassword().getSup();
}
@Bean
public UserDetailsService users() {
UserDetails admin = User.builder()
.username(ADMIN)
.password(encoder().encode(ADMIN_PASS))
.roles("ADMIN")
.build();
UserDetails sup = User.builder()
.username(SUPER)
.password(encoder().encode(SUPER_PASS))
.roles("ADMIN", "DBA")
.build();
return new InMemoryUserDetailsManager(admin, sup);
}
@Bean
public SecurityFilterChain web(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/resource/**").permitAll()
.requestMatchers("/api/**").hasAnyRole("ADMIN", "DBA")
.requestMatchers("/db/**")
.access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')"))
.anyRequest().denyAll()
);
return http.build();
}
@Bean
public static BCryptPasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
我已将 ADMIN、SUPER 及其密码打印到控制台,并且肯定可以从 application.properties 中正确读取它们。所以这不是问题。
AppSecurityExternalConfig.class:
package com.transfer.market.configuration;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Data
@Configuration
@ConfigurationProperties(prefix = "config.security")
public class AppSecurityExternalConfig {
private User user;
private Password password;
@Data
@Component
@ConfigurationProperties(prefix = "user")
public static class User {
private String user;
private String admin;
private String sup;
}
@Data
@Component
@ConfigurationProperties(prefix = "password")
public static class Password {
private String user;
private String admin;
private String sup;
}
}
应用程序属性:
...
# Security:
config.security.user.admin=admin
config.security.password.admin=pass
config.security.user.sup=super
config.security.password.sup=pass
...
PlayerController.class:
@RestController
@Validated
public class PlayerController {
private final PlayerService playerService;
@Autowired
public PlayerController(PlayerService playerService) {
this.playerService = playerService;
}
@PostMapping("/api/players")
public ResponseEntity<Player> addSingle(@RequestBody @Valid Player player) {
return new ResponseEntity<>(playerService.addSingle(player), HttpStatus.CREATED);
}
...
它只是不断收到“403 Forbidden”,但对于所有以“/resource”开头的端点(其中它们是 .permitAll()),它可以工作并且是 200 OK。为什么其他 requestMatchers 不起作用?请帮忙。
@Bean public SecurityFilterChain web(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeHttpRequests(auth -> auth.requestMatchers("/resource/**").permitAll() .requestMatchers("/api/**") .hasAnyRole("ADMIN", "DBA") .requestMatchers("/db/**") .access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')")) .anyRequest().denyAll()); return http.build(); }
您必须配置基本身份验证。在 SecurityFilterChain bean 中添加以下语句。
http.httpBasic();
即
@Bean
public SecurityFilterChain web(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests(auth -> auth.requestMatchers("/resource/**").permitAll()
.requestMatchers("/api/**")
.hasAnyRole("ADMIN")
.requestMatchers("/db/**")
.access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')"))
.anyRequest().denyAll());
http.httpBasic();
return http.build();
}
对于那些使用 Spring Security 6 的人,我遇到了这个问题并使用以下方法解决了它:
@Configuration
public class DisableSecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable);
http.authorizeHttpRequests(auth -> auth
.anyRequest()
.permitAll()
);
return http.build();
}
}