SpringSecurity使用内存认证在http put方法中不要returns错误403

SpringSecurity using memory authentication don't returns error 403 in http put method

我在内存验证中使用 SpringSecurity 的 http“put”方法中没有收到错误 403。方法 returned 200 而它应该 return 403。 使用 http "post" 方法的相同代码可以正常工作。 注意例子:

网络安全配置:

@Configuration
public class WebSecutiryConfigurer extends WebSecurityConfigurerAdapter {

    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Override
    @Bean
    protected UserDetailsService userDetailsService() {
        return super.userDetailsService();
    }

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(passwordEncoder()).withUser("11111111111")
                .password(passwordEncoder().encode("minhasenha")).roles("Administrador").and().withUser("22222222222")
                .password(passwordEncoder().encode("minhasenha")).roles("Consulta");
    }

}

这是我的 ResourceServerConfigurerAdapter:

@Configuration
public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        
         http
          .csrf().disable()
            .authorizeRequests()

        
                .antMatchers(HttpMethod.GET, "/v1/cnaes").hasAnyRole("Administrador", "Alteracao", "Consulta")
                .antMatchers(HttpMethod.POST, "/v1/cnaes").hasRole("Administrador")
                .antMatchers(HttpMethod.DELETE, "/v1/cnaes").hasRole("Administrador")
                .antMatchers(HttpMethod.PUT, "/v1/cnaes/delete").hasRole("Administrador")
                .antMatchers(HttpMethod.PUT, "/v1/cnaes").hasRole("Administrador")

              .and()
                .anonymous().disable()
                .exceptionHandling();
                
    }
}

这是我测试的方法class:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CnaeTeste {

    @LocalServerPort
    private int port;

    private String urlGeracaoToken = "http://localhost:8088/oauth/token";

    private String oauthTokenPerfilAdministrador;
    private String oauthTokenPerfilConsulta;

    @Before
    public void setup() {

        RestAssured.baseURI = "http://localhost:5555/mysystem/v1/cnaes";

    }

    @Before
    public void autenticarPerfilAdministrador() {

        Response response = RestAssured.given().auth().basic("usuario-bearer", "omissospj-pwd-bearer")
                .formParam("scope", "intranet").formParam("username", "07068684718").formParam("password", "minhasenha")
                .formParam("grant_type", "password").when().post(this.urlGeracaoToken);
        this.oauthTokenPerfilAdministrador = response.jsonPath().get("access_token");

    }

    @Before
    public void autenticarPerfilConsulta() {

        Response response = RestAssured.given().auth().basic("usuario-bearer", "omissospj-pwd-bearer")
                .formParam("scope", "intranet").formParam("username", "22222222222").formParam("password", "minhasenha")
                .formParam("grant_type", "password").when().post(this.urlGeracaoToken);
        this.oauthTokenPerfilConsulta = response.jsonPath().get("access_token");

    }

    @Test
    public void falhaAtualizarQuandoUsuarioPerfilAlteracaoStatusCode403() throws Exception {

        // insert
        Cnae cnae = new Cnae(0L, "2222222", "CNAE de Teste - Criada - Perfil Administrador", false);

        ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
        String json = ow.writeValueAsString(cnae);

        Response responseInclusao = RestAssured.given()
                .headers("Authorization", "Bearer " + this.oauthTokenPerfilAdministrador, "Content-Type",
                        ContentType.JSON, "Accept", ContentType.JSON)
                .body(json).when().post();

        Assertions.assertThat(responseInclusao.getStatusCode()).isEqualTo(201);

        // update
        String stringResponse = responseInclusao.getBody().asString();
        JSONObject jsonObject = new JSONObject(stringResponse);
        String idCadastrado = jsonObject.getString("id");
        Long idAtualizado = Long.parseLong(idCadastrado);

        cnae = new Cnae(idAtualizado, "2222222", "CNAE de Teste - Atualizada - Perfil Alteração", false);

        ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
        json = ow.writeValueAsString(cnae);

        Response responseAlteracao = RestAssured.given().headers("Authorization",
                "Bearer " + this.oauthTokenPerfilConsulta, "Content-Type", ContentType.JSON, "Accept", ContentType.JSON)
                .body(json).when().put("/" + idCadastrado);

        Assertions.assertThat(responseAlteracao.getStatusCode()).isEqualTo(403);

        // delete
        Response responseExcluir = RestAssured.given()
                .headers("Authorization", "Bearer " + this.oauthTokenPerfilAdministrador, "Content-Type",
                        ContentType.JSON, "Accept", ContentType.JSON)
                .when().delete("/" + idCadastrado).then().extract().response();

        Assertions.assertThat(responseExcluir.getStatusCode()).isEqualTo(200);

    }
}

我收到了 200 状态码,而我预计会收到 403:

Assertions.assertThat(responseAlteracao.getStatusCode()).isEqualTo(403);

有什么建议吗?

是删除也失败,还是只能放?

您的 put 指向 url
http://localhost:5555/mysystem/v1/cnaes/idCadastrado

但你只匹配 /v1/cnaes :
.antMatchers(HttpMethod.PUT, "/v1/cnaes").hasRole("Administrador")

也许您需要确保对其他请求进行身份验证:
.antMatchers(HttpMethod.PUT, "/v1/cnaes/**").authenticated()
.antMatchers(HttpMethod.PUT, "/v1/cnaes/**").hasRole("Administrador")
.anyRequest().hasRole("Administrador")(添加所有其他 antMatchers 后放在最后)

如果你的控制器中没有映射到 /v1/cnaes/:id,它应该仍然会失败,但我在你提供的代码中看不到你的控制器入口点.我想如果入口点存在,并且安全级别为 @PreAuthorize("permitAll"),那么您将成功调用它。