Java/Spring

[SpringBoot] Spring Security: permitAll()이 λ™μž‘ν•˜μ§€ μ•ŠμŒ

벼리01 2024. 3. 27. 17:43

πŸ“Œν™˜κ²½

IntelliJ Ultimate

Java 17

 

Spring boot 3.2.3

Gradle - Groovy

Dependencies: 

Spring Web

Thymeleaf

Spring Data JPA

lombok

MariaDB 10.11

Spring Dev tool

Spring Security

 

 

πŸ“Œλ¬Έμ œ

κ΄€λ¦¬μž νŽ˜μ΄μ§€λ₯Ό μ˜λ―Έν•˜λŠ” `/member`λ₯Ό μ œμ™Έν•œ λͺ¨λ“  url에 μš”μ²­μ„ ν—ˆμš©ν•˜λ €κ³  ν•œλ‹€. 정적 λ¦¬μ†ŒμŠ€μ™€ μž‘μ„±λœ λ‹€λ₯Έ url의 μš”μ²­μ„ λͺ¨λ‘ ν—ˆμš©ν•˜κΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같이 μž‘μ„±ν–ˆλ‹€.

 

 http.csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(request ->
                    request.requestMatchers(HttpMethod.POST, "/another/**")
                            .permitAll()
                            .requestMatchers(HttpMethod.GET, "/", "/another/**", "/member/login", "/css/**", "/img/**", "/js/**")
                            .permitAll()
                            .anyRequest()
                            .authenticated())
            .exceptionHandling(exceptionHandler -> exceptionHandler.accessDeniedHandler(accessDeniedHandler()));

 

 

λ¨Όμ € ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•΄ μž„μ‹œλ‘œ csrfλ₯Ό λΉ„ν™œμ„±ν™”ν–ˆλ‹€.

메인 νŽ˜μ΄μ§€μΈ `/`와 `/another`의 ν•˜μœ„ νŽ˜μ΄μ§€μ˜ 접근을 `permitAll()`을 μ‚¬μš©ν•΄ λͺ¨λ‘ ν—ˆμš©ν–ˆλ‹€.

둜그인 νŽ˜μ΄μ§€μ— μ ‘κ·Όν•  수 μžˆλ„λ‘ `/member/login`λ₯Ό ν—ˆμš©ν–ˆλ‹€.

정적 λ¦¬μ†ŒμŠ€ λ˜ν•œ μ ‘κ·Ό μ œν•œμ„ ν•΄μ œν•˜κΈ° μœ„ν•΄ `/css/**` `/img/**` `/js/**` 와 같이 μ„€μ •ν–ˆλ‹€. 

 

μ΄λ•Œ `GET` μš”μ²­μœΌλ‘œ νŽ˜μ΄μ§€μ— μ ‘μ†ν–ˆμ„ λ•Œ μž‘μ„±ν•΄λ‘” λͺ¨λ“  νŽ˜μ΄μ§€μ˜ 접근이 ν—ˆμš©λ˜μ—ˆμœΌλ‚˜ `/another`μ—μ„œ form을 보내기 μœ„ν•΄ `POST`  λ°©μ‹μœΌλ‘œ μš”μ²­ν•  경우 access denied μ—λŸ¬κ°€ λ°œμƒν–ˆλ‹€. 

 

 

λ¬Έμ œλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

 

1. μ„€μ •ν•œ url에 λŒ€ν•΄ `GET` λ°©μ‹μœΌλ‘œ μš”μ²­ν•  경우 접근이 ν—ˆμš©λ˜μ—ˆμœΌλ‚˜ `GET` μ΄μ™Έμ˜ λͺ¨λ“  μš”μ²­ 방식에 λŒ€ν•΄ μ—λŸ¬κ°€ λ°œμƒν•˜μ˜€μŒ.

2. κΆŒν•œμ΄ μ—†μœΌλ©΄ λ’€λ‘œ νŠ•κ²¨λ‚˜κ°ˆ 수 μžˆλ„λ‘ 403 handler μž‘μ„± ν›„ μ„€μ •ν•΄λ‘μ—ˆμœΌλ―€λ‘œ λ§Œμ•½ 403 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€λ©΄ ν•΄λ‹Ή handler의 둜직이 μ‹€ν–‰λ˜μ–΄μ•Ό ν•˜μ§€λ§Œ, μš”μ²­μ„ ν—ˆμš©ν•˜μ§€ μ•Šμ€ λ‹€λ₯Έ url처럼 둜그인 νŽ˜μ΄μ§€λ‘œ νŠ•κ²¨μ Έ λ‚˜μ™”μŒ.

 

 

πŸ“Œν•΄κ²°

`permitAll()`을 μž‘μ„±ν–ˆμŒμ—λ„ λ‹€λ₯Έ `filter`κ°€ λ™μž‘ν•˜λŠ” 문제둜 보고, μ²˜μŒλΆ€ν„° λ¬΄μ‹œν•˜κΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같은 섀정을 μΆ”κ°€ν–ˆλ‹€.

 

  @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web -> web.ignoring()
            .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
            .requestMatchers("/another/**"));
    }

 

 

κ·ΈλŸ¬λ‚˜ ν•΄λ‹Ή 섀정이 λ™μž‘ν•˜μ§€ μ•Šκ³  같은 였λ₯˜κ°€ μ§€μ†μ μœΌλ‘œ λ°œμƒν–ˆλ‹€.

 

 

`Controller`에 이미 `@PreAuthorize("hasRole('MEMBER')")`둜 κΆŒν•œμ„ κ²€μ¦ν•˜κ³  μžˆμœΌλ―€λ‘œ, κΆŒν•œμ΄ ν•„μš”ν•œ νŽ˜μ΄μ§€λ§Œ 인증을 μš”κ΅¬ν•˜κ³  λ‹€λ₯Έ λͺ¨λ“  νŽ˜μ΄μ§€μ—λŠ” λ‘œκ·ΈμΈν•˜μ§€ μ•Šμ€ μ‚¬μš©μžλ„ 접근을 ν—ˆμš©ν•  수 μžˆλ„λ‘ λ‘œμ§μ„ λ³€κ²½ν•˜κΈ°λ‘œ ν–ˆλ‹€.

 

 

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        http.csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests(request ->
                        request.requestMatchers("/member/**")
                                .hasRole("MEMBER")
                                .anyRequest()
                                .anonymous()
                                )
                .exceptionHandling(exceptionHandler -> 
                		exceptionHandler.accessDeniedHandler(accessDeniedHandler()))
                .formLogin(formLogin -> 
                    	formLogin.loginPage("/member/login")
                        .loginProcessingUrl("/member/login")
                        .defaultSuccessUrl("/member")
                        .permitAll());
                
        return http.build();

    }

 

 

 

 request.requestMatchers("/member/**")
        .hasRole("MEMBER")

 

 

`requestMatcher`에 μž‘μ„±λœ `/member/**` 의 ν•˜μœ„ νŽ˜μ΄μ§€μ— λŒ€ν•΄μ„œλ§Œ `MEMBER` κΆŒν•œμ„ μš”κ΅¬ν•œλ‹€.

 

 

.anyRequest()
.anonymous()

 

 

λ‹€λ₯Έ λͺ¨λ“  νŽ˜μ΄μ§€λŠ” λ‘œκ·ΈμΈν•˜μ§€ μ•Šμ€ μ‚¬μš©μž(anonymous)도 μ ‘κ·Όν•  수 μžˆλ„λ‘ ν—ˆμš©ν•œλ‹€.

 

 

 

 

잘 λ™μž‘ν•˜λŠ” 것을 확인할 수 μžˆλ‹€.

이제 접근을 μ œμ–΄ν•œ `/member`둜 μ ‘μ†ν•΄λ³΄μž.

 

 

 

 

`/member`둜 μ ‘κ·Όν•  경우 `member/login`으둜 νŠ•κ²¨μ Έ λ‚˜κ°€λŠ” 것을 확인할 수 μžˆλ‹€.