Spring Boot 3 + Spring Security 6 => 403 禁止使用“requestMatchers”

问题描述 投票:0回答:2

几天来,我一直在尝试解决 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);
    }
...

enter image description here enter image description here

它只是不断收到“403 Forbidden”,但对于所有以“/resource”开头的端点(其中它们是 .permitAll()),它可以工作并且是 200 OK。为什么其他 requestMatchers 不起作用?请帮忙。

spring security
2个回答
3
投票
@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();
}

enter image description here


0
投票

对于那些使用 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();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.