๐ํ๋ก๊ทธ๋๋จธ์ค ๋ฐฑ์๋ ๋ฐ๋ธ์ฝ์ค 4๊ธฐ ๊ต์ก๊ณผ์ ์ ๋ฃ๊ณ ์ ๋ฆฌํ ๊ธ์
๋๋ค.๐
SecurityContextHolderFilter
- SecurityContextRepository ์ธํฐํ์ด์ค ๊ตฌํ์ฒด๋ฅผ ํตํด ์ฌ์ฉ์์ SecurityContext๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ๊ฐฑ์ ํจ
- ์ธ์ฆ ๊ด๋ จ ํํฐ ์ค ๊ฐ์ฅ ์ต ์๋จ์ ์์นํ๋ฉฐ, ์ด๋ฏธ ์ธ์ฆ๋ ์ฌ์ฉ์๋ ๋ค์ ๋ก๊ทธ์ธํ ํ์๊ฐ ์์
- SecurityContext๊ฐ ์กด์ฌํ์ง ์๋๋ค๋ฉด, empty SecurityContext๋ฅผ ์์ฑํจ
๋์๊ณผ์
- ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ์ ์๋ํ์ฌ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ ์ถ
- UsernamePasswordAuthenticationFilter ๋๋ ๋ค๋ฅธ ์ธ์ฆ ํํฐ๊ฐ ์ฌ์ฉ์์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํ๊ณ , Authentication ๊ฐ์ฒด๋ฅผ ์์ฑ
- ์ธ์ฆ ๋งค๋์ (AuthenticationManager)๋ ํด๋น Authentication ๊ฐ์ฒด๋ฅผ ๊ฒ์ฆํ๊ณ , ์ฌ์ฉ์๊ฐ ์ธ์ฆ๋์๋ค๊ณ ํ๋จํ๋ฉด, ์ธ์ฆ๋ ์ฌ์ฉ์๋ฅผ ๋ํ๋ด๋ SecurityContext ๊ฐ์ฒด๋ฅผ ์์ฑ
- SecurityContextHolderFilter๋ ์์ฑ๋ SecurityContext ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์์, HttpSession์ ์ ์ฅ
- ์ธ์ฆ๋ ์ฌ์ฉ์๋ ํด๋น ์ธ์
์์ ๋ค๋ฅธ ์์ฒญ์ ๋ณด๋ผ ๋๋ง๋ค, SecurityContextHolderFilter๊ฐ ์์ฒญ์ ์์ ํ์ฌ ํด๋น ์ธ์
์์ SecurityContext ๊ฐ์ ธ์ด
- ์ฌ์ฉ์๋ ์ธ์ฆ๋ ์ฌ์ฉ์๋ก ๊ฐ์ฃผ๋์ด ์ ํ๋ฆฌ์ผ์ด์
์ ๋ณดํธ๋ ์์์ ์ ๊ทผ ๊ฐ๋ฅ
SessionManagementFilter
- ์ธ์
๊ณ ์ ๋ณดํธ (session-fixation protection)
- ์ธ์ฆ ์ ์ ๋ฐ๊ธ ๋ฐ์ ์ธ์
ID๊ฐ ์ธ์ฆ ํ์๋ ๋์ผํ๊ฒ ์ฌ์ฉ๋๋ฉด ์ ์ ์ฌ์ฉ์์ ์ธ์
์ ํ์ทจํ์ฌ ์ธ์ฆ์ ์ฐํํ๊ณ , ์
์์ ์ผ๋ก ์ฌ์ฉ๋ ์ ์์
- ์ฆ, ์ธ์ฆ ์ ์ ์ฌ์ฉ์๊ฐ ๊ฐ์ง๊ณ ์๋ ์ธ์
์ด ์ธ์ฆ ํ์๋ ์ฌ์ฉ๋์ง ์๋๋ก ํ๋ฉด ํด๋น ๊ณต๊ฒฉ์ ํจ๊ณผ์ ์ผ๋ก ๋์ํ ์ ์์
- Spring Security์์๋ 4๊ฐ์ง ์ค์ ๊ฐ๋ฅํ ์ต์
์ ์ ๊ณต
- none: ์๋ฌด๊ฒ๋ ํ์ง ์์ (์ธ์
์ ๊ทธ๋๋ก ์ ์งํจ)
- newSession: ์๋ก์ด ์ธ์
์ ๋ง๋ค๊ณ , ๊ธฐ์กด ๋ฐ์ดํฐ๋ ๋ณต์ ํ์ง ์์
- migrateSession: ์๋ก์ด ์ธ์
์ ๋ง๋ค๊ณ , ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ๋ณต์ ํจ
- changeSession: ์๋ก์ด ์ธ์
์ ๋ง๋ค์ง ์์ง๋ง, session-fixation ๊ณต๊ฒฉ์ ๋ฐฉ์ดํจ
- ์ ํจํ์ง ์์ ์ธ์
๊ฐ์ง ์ ์ง์ ๋ URL๋ก ๋ฆฌ๋ค์ด๋ ํธ ์ํด
- ์ธ์
์์ฑ ์ ๋ต ์ค์
- IF_REQUIRED: ํ์์ ์์ฑํจ (๊ธฐ๋ณธ๊ฐ)
- NEVER: Spring Security์์๋ ์ธ์
์ ์์ฑํ์ง ์์ง๋ง, ์ธ์
์ด ์กด์ฌํ๋ฉด ์ฌ์ฉํจ
- STATELESS: ์ธ์
์ ์์ ํ ์ฌ์ฉํ์ง ์์ (JWT ์ธ์ฆ์ด ์ฌ์ฉ๋๋ REST API ์๋น์ค์ ์ ํฉ)
- ALWAYS: ํญ์ ์ธ์
์ ์ฌ์ฉํจ
- ๋์ผ ์ฌ์ฉ์์ ์ค๋ณต ๋ก๊ทธ์ธ ๊ฐ์ง ๋ฐ ์ฒ๋ฆฌ
- maximumSessions: ๋์ผ ์ฌ์ฉ์์ ์ต๋ ๋์ ์ธ์
๊ฐฏ์
- maxSessionsPreventsLogin: ์ต๋ ๊ฐฏ์๋ฅผ ์ด๊ณผํ๊ฒ ๋ ๊ฒฝ์ฐ ์ธ์ฆ ์๋๋ฅผ ์ฐจ๋จํ ์ง ์ฌ๋ถ (๊ธฐ๋ณธ๊ฐ false)
- AbstractAuthenticationProcessingFilter ๊ฐ์ฒด๋ SessionManagementFilter์ ๋์ผํ ์ธ์
๊ณ ์ ๋ณดํธ, ์ต๋ ๋ก๊ทธ์ธ ์ธ์
์ ์ด๋ฅผ ์ํํจ
Spring Security ์ค์
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.sessionManagement(auth -> auth
.sessionFixation().changeSessionId()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/")
.maximumSessions(1)
.maxSessionsPreventsLogin(false))
.build();
}
- ๊ธฐ์กด SecurityFilterChain ๋น์ SessionManagementFilter ์ค์
- http.sessionManagement()๋ ์ฌ์ฉ์ ์ธ์
๊ณผ ๊ด๋ จ๋ ๋ณด์ ์ค์ ์ ํ๋ ์ธ์
๊ด๋ฆฌ์ ์ค์
์ธ๊ฐ(Authorization) ์ฒ๋ฆฌ
- ์ธ๊ฐ(Authorization): ๊ถํ์ด ๋ถ์ฌ๋ ์ฌ์ฉ์๋ค๋ง ํน์ ๊ธฐ๋ฅ ๋๋ ๋ฐ์ดํฐ์ ์ ๊ทผ์ ํ์ฉํ๋ ๊ธฐ๋ฅ์ด๋ฉฐ, ์ด๋ฅผ ์ํด ์ธ๊ฐ ์ฒ๋ฆฌ๋ ๋ ๊ฐ์ ์์
์ผ๋ก ๊ตฌ๋ถ
- ์ธ์ฆ๋ ์ฌ์ฉ์์ ๊ถํ(์ญํ )์ ๋งคํ: ROLE_USER, ROLE_ADMIN, ROLE_ANONYMOUS
- ๋ณดํธ๋๋ ๋ฆฌ์์ค์ ๋ํ ๊ถํ ํ์ธ: ๊ด๋ฆฌ์ ๊ถํ์ ๊ฐ์ง ์ฌ์ฉ์๋ง ๊ด๋ฆฌ์ ํ์ด์ง์ ์ ๊ทผ ๊ฐ๋ฅ
FilterSecurityInterceptor
- ํํฐ ์ฒด์ธ ์์์ ๊ฐ์ฅ ๋ง์ง๋ง์ ์์นํ๋ฉฐ, ์ฌ์ฉ์๊ฐ ๊ฐ๊ณ ์๋ ๊ถํ๊ณผ ๋ฆฌ์์ค์์ ์๊ตฌํ๋ ๊ถํ์ ์ทจํฉํ์ฌ ์ ๊ทผ์ ํ์ฉํ ์ง ๊ฒฐ์ ํจ
- ์ค์ง์ ์ผ๋ก ์ ๊ทผ ํ์ฉ ์ฌ๋ถ ํ๋จ์ AccessDecisionManager ์ธํฐํ์ด์ค ๊ตฌํ์ฒด์์ ์๋ 3๊ฐ์ง๋ฅผ ์ทจํฉํ์ฌ ์ด๋ฃจ์ด์ง
- Authentication(์ฌ์ฉ์ ๊ฐ์ฒด): SecurityContexHolder์์ ๊ฐ์ ธ์ด
- FilterInvocation: ํ์ฌ ์์ฒญ์ ๋ํ ์ ๋ณด ์ ๊ณต
- ConfigAttributes(๋ฆฌ์์ค์์ ์๊ตฌํ๋ ๊ถํ): SecurityMetadataSource์์ ๊ฐ์ ธ์ด
- FilterSecurityInterceptor ํํฐ๊ฐ ํธ์ถ๋๋ ์์ ์์ ์ฌ์ฉ์๋ ์ด๋ฏธ ์ธ์ฆ์ด ์๋ฃ๋๊ณ , Authentication ์ธํฐํ์ด์ค์ getAuthorities() ๋ฉ์๋๋ฅผ ํตํด ์ธ์ฆ๋ ์ฌ์ฉ์์ ๊ถํ ๋ชฉ๋ก์ ๊ฐ์ ธ์ฌ์ ์์
- ์ด๋ ์ต๋ช
์ฌ์ฉ์๋ ์ธ์ฆ์ด ์๋ฃ๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ๋ฉฐ, ROLE_ANONYMOUS ๊ถํ์ ๊ฐ์
- ๋ณดํธ๋๋ ๋ฆฌ์์ค์์ ์๊ตฌํ๋ ๊ถํ ์ ๋ณด๋ SecurityMetadataSource ์ธํฐํ์ด์ค๋ฅผ ํตํด ConfigAttribute ํ์
์ผ๋ก ๊ฐ์ ธ์ด
AccessDecisionManager ์ธํฐํ์ด์ค
- ์ฌ์ฉ์๊ฐ ๊ฐ๊ณ ์๋ ๊ถํ๊ณผ ๋ฆฌ์์ค์์ ์๊ตฌํ๋ ๊ถํ์ ํ์ธํ๊ณ , ์ฌ์ฉ์๊ฐ ์ ์ ํ ๊ถํ์ ๊ฐ๊ณ ์์ง ์๋ค๋ฉด ์ ๊ทผ ๊ฑฐ๋ถ ์ฒ๋ฆฌํจ
- AccessDecisionVoter ๋ชฉ๋ก์ ๊ฐ๊ณ ์์
- AccessDecisionVoter๋ค์ ํฌํ(vote)๊ฒฐ๊ณผ๋ฅผ ์ทจํฉํ๊ณ , ์ ๊ทผ ์น์ธ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ 3๊ฐ์ง ๊ตฌํ์ฒด๋ฅผ ์ ๊ณตํจ
- AffirmativeBased: AccessDecisionVoter๊ฐ ์น์ธํ๋ฉด ์ด์ ์ ๊ฑฐ๋ถ๋ ๋ด์ฉ๊ณผ ๊ด๊ณ์์ด ์ ๊ทผ์ด ์น์ธ๋จ (๊ธฐ๋ณธ๊ฐ)
- ConsensusBased: ๋ค์์ AccessDecisionVoter๊ฐ ์น์ธํ๋ฉด ์ ๊ทผ์ด ์น์ธ๋จ
- UnanimousBased: ๋ชจ๋ AccessDecisionVoter๊ฐ ๋ง์ฅ์ผ์น๋ก ์น์ธํด์ผ ์ ๊ทผ์ด ์น์ธ๋จ
AccessDecisionVoter ์ธํฐํ์ด์ค
int ACCESS_GRANTED = 1;
int ACCESS_ABSTAIN = 0;
int ACCESS_DENIED = -1;
int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
- AccessDecisionVoter๋ ์ ๊ทผ์ ์น์ธํ ์ง ๊ฑฐ์ ํ ์ง ํน์ ๋ณด๋ฅํ ์ง vote()๋ก ํ๋จํจ
- ๊ตฌํ์ฒด๋ก WebExpressionVoter๊ฐ ์์
WebExpressionVoter ๊ตฌํ์ฒด
- SpEL ํํ์์ ์ฌ์ฉํด ์ ๊ทผ ์น์ธ ์ฌ๋ถ์ ๋ํ ๊ท์น์ ์ง์ ํ ์ ์์
- SpEL ํํ์ ์ฒ๋ฆฌ๋ฅผ ์ํด DefaultWebSecurityExpressionHandler ๊ทธ๋ฆฌ๊ณ WebSecurityExpressionRoot ๊ตฌํ์ ์์กดํจ
- WebSecurityExpressionRoot ํด๋์ค๋ SpEL ํํ์์์ ์ฌ์ฉํ ์ ์๋ ๋ค์ํ ๋ฉ์๋๋ฅผ ์ ๊ณต