[Spring] Spring Security

์‹œ๋‚ดยท2024๋…„ 4์›” 19์ผ

Spring

๋ชฉ๋ก ๋ณด๊ธฐ
7/10

๐Ÿง™๐Ÿปโ€โ™€๏ธ Spring Security๋ž€?

  • Java ๊ธฐ๋ฐ˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ณด์•ˆ(์ธ์ฆ, ์ธ๊ฐ€, ๊ถŒํ•œ)์„ ๋‹ด๋‹นํ•˜๋Š” Spring ํ•˜์œ„ ํ”„๋ ˆ์ž„์›Œํฌ
  • REST API ๋ฐ ์„œ๋น„์Šค๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ๋ณด์•ˆ ๊ธฐ๋Šฅ์„ ์ œ๊ณต
  • Filter ํ๋ฆ„์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌ

๐Ÿ•ฏ๏ธ Filter์™€ Interceptor

1. Filter

  • Filter๋Š” Dispatcher Servlet์œผ๋กœ ๊ฐ€๊ธฐ ์ „์— ์ ์šฉ๋จ
  • ๊ฐ€์žฅ ๋จผ์ € URL ์š”์ฒญ๋ฐ›์Œ
  • Web Container์—์„œ ๊ด€๋ฆฌ

2. Interceptor

  • Interceptor๋Š” Dispatcher Servlet๊ณผ Controller ์‚ฌ์ด์— ์œ„์น˜
  • Spring Container์—์„œ ๊ด€๋ฆฌ

๐Ÿ•ฏ๏ธ Security๊ด€๋ จ Filter

1. FilterChain

  • ๊ธฐ์กด Web Application Server (WAS)์˜ filter chain
  • client๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ•˜๋‚˜์˜ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด, container๋Š” ํ•˜๋‚˜์˜ FilterChain ์ƒ์„ฑ
  • filter์™€ servlet ํฌํ•จ

2. DelegationgFilterProxy

  • HTTP ์š”์ฒญ์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ํ•„ํ„ฐ

3. FilterChainProxy

  • DelegatingFilterProxy๋ฅผ ํ†ตํ•ด ๋ฐ›์€ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ SecurityFilterChain์— ์ „๋‹ฌํ•˜๊ณ  ์ž‘์—…์„ ์œ„์ž„ํ•˜๋Š” ์—ญํ• 

4. SecurityFilterChain

  • ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ•„ํ„ฐ

  • ์ธ์ฆ๊ณผ ์ธ๊ฐ€์— ๋Œ€ํ•œ ํ•„ํ„ฐ๋“ค ์ •์˜

  • SecurityFilterChain์€ @Configuration ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์ธ ์„ค์ • ์ •๋ณด ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์Šคํ”„๋ง ๋นˆ (@Bean)์œผ๋กœ ๋“ฑ๋ก ๊ฐ€๋Šฅ

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ SecurityFilterChain์„ ๊ตฌ์„ฑํ•˜์—ฌ ๋งค์นญ๋˜๋Š” URL์— ๋”ฐ๋ผ ๋‹ค๋ฅธ SecurityFilterChain์ด ์‚ฌ์šฉ๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Œ

5. SecurityFilter

  • ์š”์ฒญ์„ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ๋งค์ปค๋‹ˆ์ฆ˜์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•„ํ„ฐ
  • ์‹œํ๋ฆฌํ‹ฐ์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ง€์ 

๐Ÿง™๐Ÿปโ€โ™€๏ธ Authentication vs Authorization

  • Authentication (์ธ์ฆ) : ์‚ฌ์šฉ์ž์˜ ์‹ ์›์„ ํ™•์ธํ•˜๋Š” ๊ณผ์ •
  • Authorization (์ธ๊ฐ€) : ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์—๊ฒŒ ํŠน์ • ๋ฆฌ์†Œ์Šค ๋˜๋Š” ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ๊ณผ์ •

๐Ÿง™๐Ÿปโ€โ™€๏ธ Authentication Architecture

1. ์œ ์ €๊ฐ€ ๋กœ๊ทธ์ธ์„ ์š”์ฒญํ•œ๋‹ค. (Http Request)
2. AuthenticationFilter ์—์„œ UsernamePasswordAuthenticationToken ์ƒ์„ฑํ•œ๋‹ค.
3. ํ•ด๋‹น Token์„ AuthenticationManager ์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.
4. AuthenticationManager ๋Š” ๋“ฑ๋ก๋œ AuthenticationProvider ๋“ค์„ ์กฐํšŒํ•˜์—ฌ ์ธ์ฆ์„ ์š”๊ตฌํ•œ๋‹ค.
5. ์‹ค์ œ DB์—์„œ ์‚ฌ์šฉ์ž ์ธ์ฆ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” UserDetailsService ์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.
6. ๋„˜๊ฒจ๋ฐ›์€ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํ†ตํ•ด DB์—์„œ ์ฐพ์€ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋‹ด์€ UserDetails ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค.
7. AuthenticationProvider ๋Š” UserDetails ๋ฅผ ๋„˜๊ฒจ๋ฐ›๊ณ  ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋น„๊ตํ•œ๋‹ค.
8. ์ธ์ฆ์ด ์™„๋ฃŒ๋˜๋ฉด ๊ถŒํ•œ ๋“ฑ์˜ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋‹ด์€ Authentication ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
9. ๋‹ค์‹œ AuthenticationFilter ์— Authentication ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.
10. Authenticaton ๊ฐ์ฒด๋ฅผ SecurityContext ์— ์ €์žฅํ•œ๋‹ค.
(์„ธ์…˜-์ฟ ํ‚ค ๊ธฐ๋ฐ˜์˜ ์ธ์ฆ ๋ฐฉ์‹)

๐Ÿ•ฏ๏ธ UsernamePasswordAuthenticationToken

  • UsernamePasswordAuthenticationToken ์€ Authentication ์„ implementํ•œ AbstractAuthenticationToken ์˜ ํ•˜์œ„ํด๋ž˜์Šค
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
    private static final long serialVersionUID = 570L;
    // ์ฃผ๋กœ ์‚ฌ์šฉ์ž์˜ UserID ์‚ฌ์šฉ
    private final Object principal;
    // ์ฃผ๋กœ ์‚ฌ์šฉ์ž์˜ password ์‚ฌ์šฉ
    private Object credentials;

	// ์ธ์ฆ ์™„๋ฃŒ ์ „์˜ ๊ฐ์ฒด ์ƒ์„ฑ
    public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
        super((Collection)null);
        this.principal = principal;
        this.credentials = credentials;
        this.setAuthenticated(false);
    }
    
	// ์ธ์ฆ ์™„๋ฃŒ ํ›„์˜ ๊ฐ์ฒด ์ƒ์„ฑ
    public UsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }

    public static UsernamePasswordAuthenticationToken unauthenticated(Object principal, Object credentials) {
        return new UsernamePasswordAuthenticationToken(principal, credentials);
    }

    public static UsernamePasswordAuthenticationToken authenticated(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        return new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
    }
}

๐Ÿ•ฏ๏ธ AuthenticationManager

  • ์ธ์ฆ์€ AuthenticationManager ๋ฅผ ํ†ตํ•ด์„œ ์ฒ˜๋ฆฌ
  • ์‹ค์งˆ์ ์œผ๋กœ๋Š” AuthenticationManager ์—๋“ฑ๋ก๋œ AuthenticationProvider์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋จ
  • ์ธ์ฆ ์„ฑ๊ณต์‹œ, _UsernamePasswordAuthenticationToken์˜ ๋‘ ๋ฒˆ์งธ ์ƒ์„ฑ์ž๋ฅผ ์ด์šฉํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ SecurityContext์— ์ €์žฅ
public interface AuthenticationManager { 
	Authentication authenticate(Authentication authentication) throws AuthenticationException; 
}

๐Ÿ•ฏ๏ธ AuthenticationProvider

  • ์‹ค์ œ ์ธ์ฆ์— ๋Œ€ํ•œ ๋ถ€๋ถ„ ์ฒ˜๋ฆฌ
  • ์ธ์ฆ ์ „์˜ Authentication ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ ์ธ์ฆ์ด ์™„๋ฃŒ๋œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
public interface AuthenticationProvider { 
	Authentication authenticate(Authentication authentication) throws AuthenticationException; 	
    boolean supports(Class<?> authentication); 
}

๐Ÿ•ฏ๏ธ ProviderManager

  • AuthenticationProvider๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ชฉ๋ก ๊ฐ€์ง

๐Ÿ•ฏ๏ธ UserDetailsService

  • UserDetails ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋‹จ ํ•˜๋‚˜์˜ ๋ฉ”์†Œ๋“œ ๊ฐ€์ง
  • ์ด interface๋ฅผ implementsํ•œ ํด๋ž˜์Šค์— UserRepository ๋ฅผ ์ฃผ์ž…๋ฐ›์•„ DB์™€ ์—ฐ๊ฒฐํ•˜์—ฌ ์ฒ˜๋ฆฌ
public interface UserDetailsService {
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

๐Ÿ•ฏ๏ธ UserDetails

  • ์ธ์ฆ ์„ฑ๊ณต ํ›„, Authentication ๊ฐ์ฒด๋ฅผ ๊ตฌํ˜„ํ•œ UsernamePasswordAuthenticationToken ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ
public interface UserDetails extends Serializable {

	// ๊ถŒํ•œ ๋ชฉ๋ก
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();

	// ๊ณ„์ • ๋งŒ๋ฃŒ ์—ฌ๋ถ€
    boolean isAccountNonExpired();

	// ๊ณ„์ • ์ž ๊น€ ์—ฌ๋ถ€
    boolean isAccountNonLocked();

	// ๋น„๋ฐ€๋ฒˆํ˜ธ ๋งŒ๋ฃŒ ์—ฌ๋ถ€
    boolean isCredentialsNonExpired();

	// ์‚ฌ์šฉ์ž ํ™œ์„ฑํ™” ์—ฌ๋ถ€
    boolean isEnabled();
}

๐Ÿ•ฏ๏ธ SecurityContextHolder

  • ๋ณด์•ˆ ์ฃผ์ฒด์˜ ์„ธ๋ถ€ ์ •๋ณด, ์‘์šฉํ”„๋กœ๊ทธ๋žจ์˜ ํ˜„์žฌ ๋ณด์•ˆ ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด ์ €์žฅ

๐Ÿ•ฏ๏ธ SecurityContext

  • Authentication ๋ณด๊ด€
  • SecurityContext ํ†ตํ•ด์„œ Authentication ์ €์žฅ / ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Œ
SecurityContextHolder.getContext().setAuthentication(authentication);
SecurityContextHolder.getContext().getAuthentication(authentication);

๐Ÿ•ฏ๏ธ Authentication

  • ์ ‘๊ทผํ•˜๋Š” ์ฃผ์ฒด์— ๋Œ€ํ•œ ์ •๋ณด์™€ ๊ถŒํ•œ ๋‹ด์€ ์ธํ„ฐํŽ˜์ด์Šค
  • SecurityContextHolder ํ†ตํ•ด์„œ SecurityContext์— ์ ‘๊ทผ
    ->
    SecurityContext ํ†ตํ•ด์„œ Authentication์— ์ ‘๊ทผ

public interface Authentication extends Principal, Serializable {

	// ํ˜„์žฌ ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ ๋ชฉ๋ก
    Collection<? extends GrantedAuthority> getAuthorities();

	// ์ฃผ๋กœ password๋ฅผ ๊ฐ€์ ธ์˜ด
    Object getCredentials();

    Object getDetails();

	// Principal (๋ณดํ˜ธ๋œ ๋Œ€์ƒ์— ์ ‘๊ทผํ•˜๋Š” ์œ ์ €) ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ด
    Object getPrincipal();

	// ์ธ์ฆ ์—ฌ๋ถ€ ๊ฐ€์ ธ์˜ด
    boolean isAuthenticated();

	// ์ธ์ฆ ์—ฌ๋ถ€ ์„ค์ •
    void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

๐Ÿ•ฏ๏ธ GrantedAuthority

  • ํ˜„์žฌ ์‚ฌ์šฉ์ž(Principal)๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ถŒํ•œ
  • ROLE_*์˜ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉ
    ex) ROLE_USER, ROLE_ADMIN
  • UserDetailsService ์— ์˜ํ•ด ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Œ

์ถœ์ฒ˜ : https://velog.io/@dlthgml0108/Spring-Security-%EC%9D%B8%EC%A6%9D%EA%B3%BC-%EC%9D%B8%EA%B0%80

https://limdevbasic.tistory.com/19#google_vignette

profile
contact ๐Ÿ“จ ksw08215@gmail.com

0๊ฐœ์˜ ๋Œ“๊ธ€