首页 > 解决方案 > 如何使用 Spring 保护 REST Web 服务,DELETE 是可能的,虽然我没有授权

问题描述

我在 Spring 中设置了一个安全配置,我希望只有用户才能访问我在配置中编写的资源。例如,如果我不写DELETE,我不希望任何用户可以使用此请求,除非我添加它,否则这是最严格的。我应该对我的代码进行哪些更改?

我写了下一个代码。GET没关系,POST但我可以删除并且我不添加此授权。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()                             
                .withUser("user")
                    .password(encoder().encode("passExample"))
                    .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            .httpBasic()
                .and()
            .csrf()
                .disable()
            .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/**").hasRole("USER")
                .antMatchers(HttpMethod.POST, "/**").hasRole("USER")
                .and()
            .formLogin()
                .permitAll();

....

我预计如果我使用 提出请求DELETE,应用程序不允许,因为我没有授权它。

curl -X Delete locahost/servicio/1
{
    "timestamp": "2019-05-09T17:43:30.253+0000",
    "status": 401,
    "error": "Unauthorized",
    "message": "Unauthorized",
    "path": "/service"
}

但实际输出的是状态 204。服务器成功处理了请求。

标签: springspring-security

解决方案


您必须限制任何其他请求,请参阅Spring Security Reference

6.4 授权请求

我们的示例只要求对用户进行身份验证,并且对我们应用程序中的每个 URL 都进行了验证。我们可以通过向我们的 http.authorizeRequests() 方法添加多个子项来为我们的 URL 指定自定义要求。例如:

protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()                                                                1
            .antMatchers("/resources/**", "/signup", "/about").permitAll()                  2
            .antMatchers("/admin/**").hasRole("ADMIN")                                      3
            .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")            4
            .anyRequest().authenticated()                                                   5
            .and()
        // ...
        .formLogin();
}
  1. http.authorizeRequests()方法有多个子项,每个匹配器都按照声明的顺序进行考虑。

  2. 我们指定了任何用户都可以访问的多个 URL 模式。具体来说,如果 URL 以“/resources/”开头、等于“/signup”或等于“/about”,则任何用户都可以访问请求。

  3. 任何以“/admin/”开头的 URL 都将被限制为具有“ROLE_ADMIN”角色的用户。您会注意到,由于我们正在调用 hasRole 方法,因此我们不需要指定“ROLE_”前缀。

  4. 任何以“/db/”开头的 URL 都要求用户同时拥有“ROLE_ADMIN”和“ROLE_DBA”。您会注意到,由于我们使用了 hasRole 表达式,我们不需要指定“ROLE_”前缀。

  5. 任何尚未匹配的 URL 只需要对用户进行身份验证

看看ExpressionUrlAuthorizationConfigurer#denyAll

全部拒绝

public ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry denyAll()

指定任何人都不允许使用 URL。

您修改后的代码:

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .httpBasic()
            .and()
        .csrf()
            .disable()
        .authorizeRequests()
            .antMatchers(HttpMethod.GET, "/**").hasRole("USER")
            .antMatchers(HttpMethod.POST, "/**").hasRole("USER")
            .anyRequest().denyAll()
            .and()
        .formLogin()
            .permitAll();
}

推荐阅读