[20] Spring - Spring Security ์‚ฌ์šฉ๋ฐฉ๋ฒ•

2024. 11. 21. 14:32ใ†Spring/Spring Security

728x90

๐Ÿ“๏ธ github ์ฐธ๊ณ 

https://github.com/kuk1157/spring-plus/commit/bd962480c81770d7e04057345d45c62bedfa9f60

 

feat: ๋ ˆ๋ฒจ 2_9 Spring Security ๊ด€๋ จ ์„ธํŒ…ํŒŒ์ผ · kuk1157/spring-plus@bd96248

kuk1157 committed Nov 15, 2024

github.com

 

๐Ÿ› ๏ธ Spring Security ์‚ฌ์šฉ๋ฐฉ๋ฒ•

 

์‚ฌ์šฉํ•˜๊ฒŒ ๋œ ๋ชฉ์ )

- ํŠน์ • ์—ฌ๋Ÿฌ๊ฐœ์˜ API์—์„œ ํšŒ์›์ •๋ณด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ํ˜„์žฌ ์ปค์Šคํ…€์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ๋”ฐ๋กœ ์„ธํŒ…ํ•ด์„œ ๊ฐ€์ ธ์˜ค๋Š” ์ •๋ณด๋ฅผ Spring Security๋กœ ํ•ด๊ฒฐ ํ•˜๊ธฐ์œ„ํ•จ.

 

 

1. gradle ํŒŒ์ผ์— ์˜์กด์„ฑ ์ถ”๊ฐ€

// 2_9 Spring Security
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test:6.0.0'

- ๋ฒ„์ „์€ ๋ณธ์ธ์˜ springboot ๋ฒ„์ „๊ณผ ํ™•์ธํ•ด์•ผํ•œ๋‹ค.

- ๋‘๋ฒˆ์งธ์ค„์€ Spring Security๋ฅผ ์„ค์ •ํ•œ ํ›„ ํ…Œ์ŠคํŠธ์ฝ”๋“œ์— ๋Œ€ํ•œ ์˜์กด์„ฑ์œผ๋กœ ์—†์–ด๋„ ๋จ.

(ํ•„์ž๋Š” ํ…Œ์ŠคํŠธํ•  ๋ถ€๋ถ„์ด์žˆ์–ด์„œ ๋„ฃ์€์ƒํƒœ)

 

2. config  ํŒจํ‚ค์ง€์— WebSecurityConfig ํŒŒ์ผ ์„ธํŒ…

โ€ป WebSecurityConfig.java

- Spring Security๋ฅผ ํ™œ์šฉํ•˜์—ฌ JWT ๊ธฐ๋ฐ˜ ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ณด์•ˆ ์„ค์ •์„ ๊ตฌ์„ฑํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์ธ ์›น ๋ณด์•ˆ ์„ค์ • ํ›„,

JWT ํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์—์„œ ํ† ํฐ์„ ๊ฒ€์‚ฌํ•˜๊ณ  ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์„ค๊ณ„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. 
@EnableWebSecurity๋กœ ๋ณด์•ˆ์„ ํ™œ์„ฑํ™”,
์ธ์ฆ์ด ํ•„์š”ํ•œ URL๊ณผ ํ•„์š”์—†๋Š” URL์„ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ ‘๊ทผ์„ ์ œ์–ดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig {
    private final JwtRequestFilter jwtRequestFilter;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // CSRF ์„ค์ •
        http.csrf((csrf) -> csrf.disable());
        http.authorizeHttpRequests((authorizeHttpRequests) ->
            authorizeHttpRequests
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // resources ์ ‘๊ทผ ํ—ˆ์šฉ ์„ค์ •
                .requestMatchers("/auth/**").permitAll()
                .requestMatchers("/error").permitAll() // ๊ถŒ์žฅํ•˜์ง€๋Š” ์•Š๋Š” ๋ฐฉ๋ฒ•
        );
        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
    @Bean
    AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}

WebSecurityConfig ์ฝ”๋“œํ•ด์„)

1. SecurityFilterChain Spring Security์—์„œ ์ œ๊ณต๋˜๋Š” ๋ณด์•ˆํ•„ํ„ฐ์ฒด์ธ์ด๊ณ  HttpSecurity๋กœ ๋ฆฌ์†Œ์Šค(url)๋ณ„๋กœ ์ ‘๊ทผ ๊ถŒํ•œ์„ ์„ค์ •


2. CSRF์„ค์ •์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋‚˜ ์™ธ๋ถ€api์—ฐ๋™ํ• ๋•Œ ๊ฐœ๋ฐœ์ž๋„๊ตฌ์—์„œ ์—๋Ÿฌ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฉด ๋งŽ์ด ๋ณด๊ฒŒ๋˜๋Š” ๊ฒƒ์ด๋ฉฐ, csrf๊ณต๊ฒฉ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋น„ํ™œ์„ฑํ™” ํ•œ๋‹ค. (์ „์ฒด ํŽ˜์ด์ง€์— ๋Œ€ํ•˜์—ฌ 403์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ๊ณ ,  REST API์—์„œ๋Š” CSRF๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ์— ๋น„ํ™œ์„ฑํ™”)


3. authorizeHttpRequests - HTTP ์š”์ฒญ์— ๋Œ€ํ•œ ๊ถŒํ•œ์„ ์„ค์ •ํ•จ.


4. requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() 

- ์ •์  ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด์„œ ์ธ์ฆ์—†์ด ์ ‘๊ทผ ํ—ˆ์šฉํ•จ.(๊ณตํ†ตํŒŒ์ผ์ด๋‚˜ css, ๊ณตํ†ตjs, ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋“ฑ)


5. requestMatchers("/auth/**").permitAll() - /auth/๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ชจ๋“  ์š”์ฒญ(api)๋Š” ์ธ์ฆ ์—†์ด ์ ‘๊ทผํ—ˆ์šฉ(๋กœ๊ทธ์ธ,ํšŒ์›๊ฐ€์ž…)


6. anyRequest().authenticated() - ๊ทธ ์™ธ์˜ ๋ชจ๋“  ์š”์ฒญ์€ ์ธ์ฆ์„ ํ•˜๋„๋ก ์ง„ํ–‰


7. addFilterBefore: JwtRequestFilter - jwtRequestFilter๋ผ๋Š” ์ปค์Šคํ…€ ํ•„ํ„ฐ(jwtํ† ํฐํ•„ํ„ฐ) ์‚ฌ์šฉ์ž ์š”์ฒญ์‹œ ๊ฒ€์‚ฌ


8. UsernamePasswordAuthenticationFilter.class 
- Spring Security์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ์‚ฌ์šฉ์ž์ด๋ฆ„,๋น„๋ฐ€๋ฒˆํ˜ธ ์ธ์ฆ ํ•„ํ„ฐ. 

- jwtRequestFilterํ•ด๋‹น ์ปค์Šคํ…€ํ•„ํ„ฐ๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋˜๋„๋ก ์„ค์ •


9. AuthenticationManager - Spring Security์—์„œ ์ธ์ฆ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ๋งค๋‹ˆ์ €


10. AuthenticationConfiguration - Spring Security์˜ ์ธ์ฆ ์„ค์ •์„ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค(์ด ํด๋ž˜์Šค์—์„œ Manager๋ฅผ ๊ฐ€์ ธ์˜ด)

 

 

3. JwtRequestFilter ํŒŒ์ผ์„ธํŒ…

โ€ป JwtRequestFilter.java

- JwtRequestFilter๋Š” HTTP ์š”์ฒญ์— ํฌํ•จ๋œ JWT ํ† ํฐ์„ ๊ฒ€์ฆํ•˜๊ณ , 
ํ† ํฐ์ด ์œ ํšจํ•˜๋ฉด ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆ๋œ ์ƒํƒœ๋กœ ์„ค์ •ํ•˜์—ฌ, 
์ดํ›„์˜ ์š”์ฒญ์—์„œ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘๊ทผํ•˜๋„๋ก ์ฒ˜๋ฆฌํ•˜๋Š” ํ•„ํ„ฐ์ž…๋‹ˆ๋‹ค. 
์ด๋ฅผ ํ†ตํ•ด Spring Security์—์„œ JWT ๊ธฐ๋ฐ˜ ์ธ์ฆ์„ ์†์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Slf4j
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
    private final JwtUtil jwtUtil;
    @Autowired
    public JwtRequestFilter(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
        throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
            try {
                Long userId = jwtUtil.extractUserId(token);  // userId ์ถ”์ถœ
                if (userId != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                    UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(userId, null, new ArrayList<>());
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            } catch (Exception e) {
                log.error("Internal server error", e);
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
        }
        chain.doFilter(request, response);
    }
}

JwtRequestFilter ์ฝ”๋“œํ•ด์„)

1. OncePerRequestFilter - Spring Security์—์„œ ์ œ๊ณตํ•˜๋Š” ํ•„ํ„ฐ ํด๋ž˜์Šค
- doFilterInternal ๋ฉ”์„œ๋“œ๊ฐ€ ํ•œ ์š”์ฒญ์— ๋Œ€ํ•ด ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋„๋กํ•จ.(ํ•„ํ„ฐ์ค‘๋ณต์‹คํ–‰ ๋ฐฉ์ง€)


2. doFilterInternal  - ์ด ๋ฉ”์„œ๋“œ๋Š” ์š”์ฒญ์ด ํ•„ํ„ฐ ์ฒด์ธ์— ๋“ค์–ด์˜ฌ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋จ.

- ํ•„ํ„ฐ๋Š” ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„์„œ ์ฒ˜๋ฆฌ ํ›„ chain.doFilter()๋ฅผ ํ†ตํ•ด(์ตœํ•˜๋‹จ) ํ•„ํ„ฐ ์ฒด์ธ ๊ณ„์† ์‹คํ–‰


3. SecurityContextHolder - Spring Security ๋ณด์•ˆ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด 


4. UsernamePasswordAuthenticationToken - ์‚ฌ์šฉ์ž์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™œ์šฉํ•˜๋Š” ํ† ํฐ
- ํšŒ์› ๊ณ ์œ  id๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ธ์ฆ ๊ฐ์ฒด ์ƒ์„ฑ์ค‘


5. SecurityContextHolder.getContext().setAuthentication(authentication)
- ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ SecurityContextHolder ์— ์„ค์ •ํ•˜์—ฌ ํ›„์† ์š”์ฒญ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ๋œ ์ƒํƒœ๋กœ ์ฒ˜๋ฆฌ๋˜๋„๋ก ํ•จ.
(๊ณ„์†์ธ์ฆ๋œ์ƒํƒœ๋กœ ์ ‘๊ทผ๊ฐ€๋Šฅ)


6. chain.doFilter(request, response) - ํ† ํฐ ๊ฒ€์ฆ์ด ๋๋‚œ ํ›„ ํ•„ํ„ฐ ์ฒด์ธ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„๋„ ์‹คํ–‰๋˜๋„๋ก ์ง„ํ–‰.

 

 

๊ธฐํƒ€)

- JwtUtil ์ผ๋ถ€

- token์„ ํ™œ์šฉํ•ด์„œ ํšŒ์› id(๊ณ ์œ ๋ฒˆํ˜ธ) ์ถ”์ถœ ๋ฉ”์„œ๋“œ

 

 

โ€ป ์ฃผ์˜ํ•  ์ )

- jwtํ† ํฐ ๊ด€๋ จ ์˜ˆ์™ธ๋Š” ๋‹ค ํ•ด๋‹น ํŒŒ์ผ์—์„œ ์ง„ํ–‰ํ•ด์ค˜์•ผํ•จ. (์˜ˆ์‹œ)

 

 

- 403์—๋Ÿฌ์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๋งํฌ ์ฐธ๊ณ 

https://kuk1938.tistory.com/215

 

[19] Spring - Spring Security ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

๐Ÿ“๏ธ ํ•„์ˆ˜ ๊ณผ์ œ ์ฐธ๊ณ  - ๊ณผ์ œ ์ตœ์ข… Commit ๋‚ด์—ญ ๐Ÿ› ๏ธ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… -  Spring Security ์ ์šฉํ›„์— ๋ฐœ์ƒํ•œ api 403์—๋Ÿฌ ๋ฌธ์ œ 1. ๊ฐœ์š”- Spring Security์„ ์ ์šฉํ• ๋•Œ ๋ฐœ์ƒํ•œ API 403์—๋Ÿฌ(์ฝ”๋“œ์™€ ๋ฉ”์‹œ์ง€๋„์—†์Œ)์— ๋Œ€

kuk1938.tistory.com

 

 

 

 

 

4. ์‹ค์ œ ํ™œ์šฉ

โ€ป Spring Security์—์„œ ์ œ๊ณตํ•˜๋Š” Principal ์ธํ„ฐํŽ˜์ด์Šค ์‚ฌ์šฉ

 

- Controller์—์„œ Principal ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ต์งธ๋กœ ๋‹ด์•„์„œ ๋ณด๋‚ด๊ณ  ์žˆ๋‹ค.

 

- ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ฐ€์ ธ์˜จ userId๋กœ DB์— ์ง์ ‘ ์กฐํšŒํ•˜์—ฌ user๊ฐ์ฒด๋ฅผ ํ™œ์šฉ

 

โ€ป Principal ์žฅ์ )

1) ๊ฐ„๊ฒฐํ•˜๊ณ  ์ง๊ด€์ 
-  Spring Security์˜ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ๋งค์šฐ ์ง๊ด€์ ์ด๊ณ  ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.


2) Spring Security์™€์˜ ํ†ตํ•ฉ
-  Spring Security์™€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ†ตํ•ฉ๋˜์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ณด์•ˆ ์ƒํƒœ๋ฅผ ์•ˆ์ •์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


3) ์œ ์—ฐ์„ฑ
- Principal์€ ๋‹ค์–‘ํ•œ ๋ณด์•ˆ ์ธ์ฆ ๋ฐฉ์‹๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์—ฐํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
- ์˜ˆ๋ฅผ ๋“ค์–ด, OAuth2, SSO ๋“ฑ ๋‹ค์–‘ํ•œ ์ธ์ฆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•  ๋•Œ๋„ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

728x90