spring-security Sping Boot -启用CSRF- Postman - Get请求不需要任何令牌或授权

mbskvtky  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(227)

由于我不是安全Maven,我在这里再次向你寻求建议,重新保护CSRF处理,在我的情况下,通过Spring Boot 配置。
我有以下设置:

安全配置

@EnableWebSecurity
public class WebSecurityConfig {

    private static final String ADMIN = "ADMIN";
    private static final String USER = "USER";

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User
                .withUsername("user")
                .password(passwordEncoder().encode("password"))
                .roles(USER)
                .build();

        UserDetails admin = User
                .withUsername("admin")
                .password(passwordEncoder().encode("password"))
                .roles(ADMIN)
                .build();

        return new InMemoryUserDetailsManager(user, admin);
    }

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

    @Bean
    //@Order(1) // Order is required incase you create multiple filterchains for security
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeRequests()
                .antMatchers("/auth/login").permitAll()
                .antMatchers("/books/special").hasAnyRole("ADMIN")
                .antMatchers("/books/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
                .and()
                .httpBasic()
                .and()
                .logout().logoutRequestMatcher(new AntPathRequestMatcher("/auth/logout"))
                .and()
                .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .and()
                .build();
    }
}

休息控制器

@RestController
@RequestMapping("/auth")
public class AuthenticationController {

    @GetMapping("/login")
    public String login() {
        return "You are logged in";
    }

    @PostMapping("/logout")
    public String logout() {
        return "You are logged out";
    }
}

@RestController
@RequestMapping("/books")
public class BookController {

    @GetMapping
    public List<String> getAllBooks() {
        return Arrays.asList("Book1", "Book2", "Book3", "Book4", "Book5");
    }

    @GetMapping("/special")
    public String getSpecialBook() {
        return "Special book";
    }

    @PostMapping
    public String createBook() {
        return "Book6";
    }

    @PatchMapping
    public String updateBook() {
        return "Book6 is now book7";
    }

    @DeleteMapping("/special")
    public String deleteBook() {
        return "Some book was deleted";
    }
}

我目前正在使用Postman来验证身份验证部分是否按预期运行。
我从Spring安全性生成的cookie中获取XSRF-TOKEN,并在POST / PATCH / DELETE的头文件中使用它(不用于GET方法)
POST / PATCH / DELETE按预期工作,如果X-XSRF-TOKEN不存在,我们将得到403禁止,如果存在,我将从控制器接收字符串。
我有点困惑的问题来了。
似乎只要我的应用程序通过调用ex /login的用户的身份验证
用户的身份验证保存在某个地方,我现在可以访问所有的GET端点,而无需任何进一步的身份验证。即使我重新启动应用程序,也不需要重新进行身份验证。
只有在明确调用“/logout”端点之后,我才需要在调用GET请求时再次进行身份验证。
在spring文档中,他们说我们需要为所有操作请求(POST/PUT/PATCH/DELETE)显式设置X-XSRF-TOKEN,但是他们并没有真正提到应该如何处理GET请求,除了
我们可以放宽期望,只要求为每个更新状态的HTTP请求提供令牌。这样做是安全的,因为同源策略确保恶意站点无法读取响应。此外,我们不希望在HTTP GET中包含随机令牌,因为这可能导致令牌泄漏。
我希望这不是太混乱,读起来像写起来一样,我很高兴,如果人们能给我提供理论,这样我就可以扩展我的研究,因为我觉得这可能会导致一些漏洞,我还没有发现。
谨致问候

rbl8hiat

rbl8hiat1#

代努姆先生在评论中或多或少地回答了我的问题。
我的应用程序行为的原因是SessionManagement没有设置为无状态,因此为登录用户保留了一个会话,并在每次请求时自动从 Postman 发送。
为了对每个请求进行身份验证,我需要在WebSecurityConfig中添加以下行:

.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()

这将删除我收到的JSESSIONID cookie,并在每次请求时刷新我的CSRF令牌。
之前,我的CSRF令牌在每个请求上都是相同的,这可能是由于已识别的会话。
感谢您帮助解开谜团!

相关问题