Spring/Security

Spring Security

leeh96 2023. 3. 12. 13:55

Spring Security

์ธ์ฆ(Authentication)๊ณผ ์ธ๊ฐ€(Authorization) ๋ฅผ ์ œ๊ณตํ•˜๋Š”๋ฐ ์ดˆ์ ์„ ๋งž์ถ˜ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ
  • ์ธ์ฆ(Authentication) : ํ•ด๋‹น ์‚ฌ์šฉ์ž๊ฐ€ ๋ณธ์ธ์ด ๋งž๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •
  • ์ธ๊ฐ€(Authorization) : ํ•ด๋‹น ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•˜๋Š” ์ž์›์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์ด ์žˆ๋Š”๊ฐ€๋ฅผ ํ™•์ธํ•˜๋Š” ๊ณผ์ •

 

Spring Security ์—์„œ๋Š”..

Principal์„ ์•„์ด๋””๋กœ, Credential์„ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ ์‚ฌ์šฉํ•˜๋Š” Credential ๊ธฐ๋ฐ˜์˜ ์ธ์ฆ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.

=> ๊ฐœ๋ฐœ์ž ์ž…์žฅ์—์„œ ์ผ์ผ์ด ๋ณด์•ˆ ๊ด€๋ จ ๋กœ์ง์„ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

  • Principal(์ ‘๊ทผ ์ฃผ์ฒด) : ๋ณดํ˜ธ๋ฐ›๋Š” Resource์— ์ ‘๊ทผํ•˜๋Š” ๋Œ€์ƒ
  • Credential(๋น„๋ฐ€๋ฒˆํ˜ธ) : Resource์— ์ ‘๊ทผํ•˜๋Š” ๋Œ€์ƒ์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ

 

Spring Security๋Š” '์ธ์ฆ'๊ณผ '๊ถŒํ•œ'์— ๋Œ€ํ•œ ๋ถ€๋ถ„์„ Filter ํ๋ฆ„์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค.

  • Client (request) → Filter → DispatcherServlet → Interceptor → Controller

 

ํŠน์ง•

1) ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ชจ๋“  URL์— ๋Œ€ํ•œ ์ธ์ฆ ์š”๊ตฌ

  • ์ธ์ฆ, ์ธ๊ฐ€๋˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๋Š” Security Filter์—์„œ ๊ฑธ๋Ÿฌ๋‚ธ๋‹ค.

2) ์‹œํ๋ฆฌํ‹ฐ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

  • ์‹œํ๋ฆฌํ‹ฐ ๋‚ด์˜ ์†Œ์Šค๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • LoginSuccessHandler, LoginFailHandler, UserDetailsService ๋“ฑ

3) CSRF ๊ณต๊ฒฉ, ์„ธ์…˜ ๊ณ ์ • ๋ฐฉ์ง€

  • CSRF, ์„ธ์…˜ ๊ณ ์ • ๋“ฑ ์„ธ์…˜์„ ํ™œ์šฉํ•œ ๊ณต๊ฒฉ๋“ค์„ ๋ฐฉ์ง€ํ•œ๋‹ค.
  • CSRF(Cross Site Request Forgery)
    ์‚ฌ์šฉ์ž์˜ ์˜์ง€์™€๋Š” ๋ฌด๊ด€ํ•˜๊ฒŒ ๊ณต๊ฒฉ์ž๊ฐ€ ์ˆ˜์ •, ์‚ญ์ œ, ๋“ฑ๋ก ๋“ฑ์„ ํŠน์ • ์›น์‚ฌ์ดํŠธ์— ์š”์ฒญํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ณต๊ฒฉ
  • ์„ธ์…˜ ๊ณ ์ •(Session Fixation)
    ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ณ ์ •๋œ ์„ธ์…˜ID๊ฐ€ ๋ฐœ๊ธ‰๋˜๋Š” ๊ฒฝ์šฐ, ๊ณต๊ฒฉ์ž๊ฐ€ ์„ธ์…˜ID๋ฅผ ํƒˆ์ทจํ•˜์—ฌ ์ ‘๊ทผ ๋ฐ ๊ถŒํ•œ์„ ์šฐํšŒํ•˜๋Š” ๊ณต๊ฒฉ

4) HTTP ๋ณด์•ˆ ํ—ค๋” ๊ฐ•ํ™”

  • HTTP ํ—ค๋”๋ฅผ ๊ฐ•ํ™”ํ•˜์—ฌ XSS, X-Frame-Options ๋“ฑ์— ๋Œ€์‘ํ•œ๋‹ค.
  • - HSTS (HTTP Strict Transport Security)
    WEB์— ์ ‘๊ทผํ•  ๋•Œ, ๊ฐ•์ œ์ ์œผ๋กœ HTTPS๋กœ ์ ‘๊ทผํ•˜๋„๋ก ํ•œ๋‹ค.
  • - XSS(Cross-Site Scripting) ๋ณด์•ˆ
    ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํฌํ•จ๋œ URL์„ ํ•„ํ„ฐ๋ง ํ•œ๋‹ค.
  • - X-Frame-Options
    X-Frame-Options HTTP ์‘๋‹ต ํ—ค๋”๋Š” ํ•ด๋‹น ํŽ˜์ด์ง€๋ฅผ <frame> ๋˜๋Š”<iframe>, <object> ์—์„œ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์‚ฌ์ดํŠธ ๋‚ด ์ฝ˜ํ…์ธ ๋“ค์ด ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์— ํฌํ•จ๋˜์ง€ ์•Š๋„๋ก ํ•˜์—ฌ clickjacking ๊ณต๊ฒฉ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์ด ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. 

 

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•

 

Spring Security Architecture

  • ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ์ •๋ณด์™€ ํ•จ๊ป˜ ์ธ์ฆ์„ ์š”์ฒญํ•œ๋‹ค.
  • AuthenticationFilter๊ฐ€ Http ์„œ๋ธ”๋ฆฟ ๋ฆฌํ€˜์ŠคํŠธ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋‚ธ ์ •๋ณด๋ฅผ ์ธํ„ฐ์…‰ํŠธํ•œ๋‹ค.
  • UsernamePasswordAuthenticationToken์˜ ์ธ์ฆ์šฉ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • AuthenticationManager์˜ ๊ตฌํ˜„์ฒด์ธ ProviderManager์—๊ฒŒ ์ƒ์„ฑํ•œ UsernamePasswordToken ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
  • AuthenticationManager๋Š” ๋“ฑ๋ก๋œ AuthenticationProvider์„ ์กฐํšŒํ•˜์—ฌ ์ธ์ฆ์„ ์š”๊ตฌํ•œ๋‹ค.
  • ์‹ค์ œ DB์—์„œ ์‚ฌ์šฉ์ž ์ธ์ฆ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” UserDetailsService์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.
  • ๋„˜๊ฒจ๋ฐ›์€ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํ†ตํ•ด DB์—์„œ ์ฐพ์€ ์‚ฌ์šฉ์ž ์ •๋ณด์ธ UserDetails ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค.
  • AuthenticationProvider๋Š” UserDetails๋ฅผ ๋„˜๊ฒจ๋ฐ›๊ณ  ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋น„๊ตํ•œ๋‹ค.
  • ์ธ์ฆ์ด ์™„๋ฃŒ๋˜๋ฉด ๊ถŒํ•œ ๋“ฑ์˜ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋‹ด์€ Authentication ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ๋‹ค์‹œ ์ตœ์ดˆ์˜ AuthenticationFilter์— Authentication ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.
  •  Authenticaton ๊ฐ์ฒด๋ฅผ SecurityContext์— ์ €์žฅํ•œ๋‹ค.

์ฃผ์š” ๋ชจ๋“ˆ

UsernamePasswordAuthenticationToken

User์˜ ID๊ฐ€ Principal ์—ญํ• ์„ ํ•˜๊ณ , Password๊ฐ€ Credential์˜ ์—ญํ• ์„ ํ•œ๋‹ค.

์ฒซ ๋ฒˆ์งธ ์ƒ์„ฑ์ž๋Š” ์ธ์ฆ ์ „์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๋‘๋ฒˆ์งธ๋Š” ์ธ์ฆ์ด ์™„๋ฃŒ๋œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

public abstract class AbstractAuthenticationToken implements Authentication, CredentialsContainer {
}
 
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
 
	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
 
	// ์ฃผ๋กœ ์‚ฌ์šฉ์ž์˜ ID์— ํ•ด๋‹น
	private final Object principal;
 
	// ์ฃผ๋กœ ์‚ฌ์šฉ์ž์˜ PW์— ํ•ด๋‹น
	private Object credentials;
 
	// ์ธ์ฆ ์™„๋ฃŒ ์ „์˜ ๊ฐ์ฒด ์ƒ์„ฑ
	public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
		super(null);
		this.principal = principal;
		this.credentials = credentials;
		setAuthenticated(false);
	}
 
	// ์ธ์ฆ ์™„๋ฃŒ ํ›„์˜ ๊ฐ์ฒด ์ƒ์„ฑ
	public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
			Collection<? extends GrantedAuthority> authorities) {
		super(authorities);
		this.principal = principal;
		this.credentials = credentials;
		super.setAuthenticated(true); // must use super, as we override
	}
}

AuthenticationManager

public interface AuthenticationManager {
 
	Authentication authenticate(Authentication authentication) throws AuthenticationException;
 
}

AuthenticationProvider

public interface AuthenticationProvider {
 
	Authentication authenticate(Authentication authentication) throws AuthenticationException;
 
	boolean supports(Class<?> authentication);
 
}

 

์‹ค์ œ ์ธ์ฆ์— ๋Œ€ํ•œ ๋ถ€๋ถ„ ์ฒ˜๋ฆฌ

์ธ์ฆ ์ „์˜ Authentication ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ ์ธ์ฆ์ด ์™„๋ฃŒ๋œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด Customํ•œ AuthenticationProvider๋ฅผ ์ž‘์„ฑํ•˜๊ณ  AuthenticationManager์— ๋“ฑ๋กํ•˜๋ฉด ๋œ๋‹ค.

 

ProviderManager

public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
	
    public List<AuthenticationProvider> getProviders() {
		return this.providers;
	}
    
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		Class<? extends Authentication> toTest = authentication.getClass();
		AuthenticationException lastException = null;
		AuthenticationException parentException = null;
		Authentication result = null;
		Authentication parentResult = null;
		int currentPosition = 0;
		int size = this.providers.size();
        
        // for๋ฌธ์œผ๋กœ ๋ชจ๋“  provider๋ฅผ ์ˆœํšŒํ•˜์—ฌ ์ฒ˜๋ฆฌํ•˜๊ณ  result๊ฐ€ ๋‚˜์˜ฌ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•œ๋‹ค.
		for (AuthenticationProvider provider : getProviders()) { ... }
	}
}

 

AuthenticationManager๋ฅผ implementsํ•œ ProviderManager๋Š” AuthenticationProvider๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ชฉ๋ก์„ ๊ฐ–๋Š”๋‹ค.

 

UserDetailsService

public interface UserDetailsService {
 
	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
 
}

UserDetailsService๋Š” UserDetails ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•˜๋‚˜์˜ ๋ฉ”์†Œ๋“œ๋งŒ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋ฅผ implementsํ•œ ํด๋ž˜์Šค์— UserRepository๋ฅผ ์ฃผ์ž…๋ฐ›์•„ DB์™€ ์—ฐ๊ฒฐํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.

 

UserDetails

public interface UserDetails extends Serializable {
 
	// ๊ถŒํ•œ ๋ชฉ๋ก
	Collection<? extends GrantedAuthority> getAuthorities();
 
	String getPassword();
 
	String getUsername();
 
	// ๊ณ„์ • ๋งŒ๋ฃŒ ์—ฌ๋ถ€
	boolean isAccountNonExpired();
 
	// ๊ณ„์ • ์ž ๊น€ ์—ฌ๋ถ€
	boolean isAccountNonLocked();
 
	// ๋น„๋ฐ€๋ฒˆํ˜ธ ๋งŒ๋ฃŒ ์—ฌ๋ถ€
	boolean isCredentialsNonExpired();
 
	// ์‚ฌ์šฉ์ž ํ™œ์„ฑํ™” ์—ฌ๋ถ€
	boolean isEnabled();
 
}

์ธ์ฆ์— ์„ฑ๊ณตํ•˜์—ฌ ์ƒ์„ฑ๋œ UserDetails ๊ฐ์ฒด๋Š” Authentication๊ฐ์ฒด๋ฅผ ๊ตฌํ˜„ํ•œ UsernamePasswordAuthenticationToken์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค. UserDetails๋ฅผ implementsํ•˜์—ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

SecurityContextHolder

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

 

SecurityContext

SecurityContextHolder.getContext().setAuthentication(authentication);
SecurityContextHolder.getContext().getAuthentication(authentication);

Authentication์„ ๋ณด๊ด€ํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋ฉฐ, SecurityContext๋ฅผ ํ†ตํ•ด Authentication์„ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ๊บผ๋‚ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

 

 

 

์‹œํ๋ฆฌํ‹ฐ์˜ ์ฃผ์š” ํ•„ํ„ฐ

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๋ฅผ ์ด์•ผ๊ธฐ ํ•  ๋•Œ "์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๋Š” ์Šคํ”„๋ง MVC์— ์ข…์†์ ์ด์ง€ ์•Š๋‹ค" ๋ผ๊ณ  ์ด์•ผ๊ธฐ ํ•˜๋Š”๋ฐ
์ด๋Š” ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ํ•„ํ„ฐ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๋™์ž‘ํ•˜๊ณ , ํ•„ํ„ฐ๋Š” ์Šคํ”„๋ง์— ์†ํ•œ ๊ธฐ์ˆ ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋Ÿฌํ•œ ๊ฒƒ์ด๋‹ค.

ํ•„ํ„ฐ์˜ ๊ฐ€์žฅ ํฐ ์—ญํ• ์€ ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ๊ฒ€์ฆํ•˜๊ณ  ํ•„์š”์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ณ€์กฐํ•˜๋Š” ๊ฒƒ

 

SecurityContextPersistenceFilter

  • SecurityContextRepository๋ฅผ ํ†ตํ•ด SecurityContext๋ฅผ Load/Save ์ฒ˜๋ฆฌ

LogoutFilter

  • ๋กœ๊ทธ์•„์›ƒ URL๋กœ์˜ ์š”์ฒญ์„ ๊ฐ์‹œํ•˜์—ฌ ํ•ด๋‹น ์‚ฌ์šฉ์ž๋ฅผ ๋กœ๊ทธ์•„์›ƒ ์‹œํ‚ด

UsernamePasswordAuthenticationFilter

  • ID /๋น„๋ฐ€๋ฒˆํ˜ธ ๊ธฐ๋ฐ˜ Form ์ธ์ฆ ์š”์ฒญ url์„ ๊ฐ์‹œํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•จ

ExceptionTranslationFilter

  • ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ค‘์— ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์œ„์ž„ํ•˜๊ฑฐ๋‚˜ ์ „๋‹ฌ

FilterSecurityInterceptor

  • ์ ‘๊ทผ ๊ถŒํ•œ ํ™•์ธ์„ ์œ„ํ•ด ์š”์ฒญ์„ AccessDecisionManager๋กœ ์œ„์ž„
    ์ด ํ•„ํ„ฐ๊ฐ€ ์‹คํ–‰๋˜๋Š” ์‹œ์ ์—๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ๋๋‹ค๊ณ  ํŒ๋‹จ

 


SpringSecurity ๋ฉด์ ‘ ์งˆ๋ฌธ

๐Ÿ’ก Spring Security๋ฅผ ์ ์šฉํ•ด๋ณด์•˜๋‚˜์š”?

๐Ÿ’ก Spring Security์˜ pricipal์—๋Š” ์–ด๋– ํ•œ ์ •๋ณด๋“ค์ด ๋‹ด๊ฒจ์žˆ๋‚˜์š”?

๐Ÿ’ก Spring Security์˜ ์–ด๋…ธํ…Œ์ด์…˜๋“ค์„ ์‚ฌ์šฉํ•ด๋ณด์•˜๋‚˜์š”?

๐Ÿ’ก Spring Security์˜ UserDetails ๊ฐ์ฒด๋ฅผ ์ƒ์†ํ•˜์—ฌ ์ปค์Šคํ…€๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์•˜๋‚˜์š”?

๐Ÿ’ก Spring Security์˜ ๋™์ž‘๊ณผ์ •์„ ์„ค๋ช…ํ•˜์„ธ์š”.

๐Ÿ’ก Spring Security์˜ ํ•„ํ„ฐ์— ๋Œ€ํ•ด ๋งํ•ด๋ณด์„ธ์š”.