Spring Security
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์ ํํฐ์ ๋ํด ๋งํด๋ณด์ธ์.