๐ ์ค๋ ๋ฐฐ์ด ๋ด์ฉ!
- Spring Security์ ์น ์์ฒญ ์ฒ๋ฆฌ ํ๋ฆ
- ์๋ธ๋ฆฟ ํํฐ (Servlet Filter)
- Spring Security์ ์ปดํฌ๋ํธ๋ก ๋ณด๋ ์ธ์ฆ ์ฒ๋ฆฌ ํ๋ฆ
- Spring Security์ ๊ถํ ๋ถ์ฌ ํ๋ฆ
โ๏ธ Spring Security์ ์น ์์ฒญ ์ฒ๋ฆฌ ํ๋ฆ
( ์ ๊ทธ๋ฆผ์์ 2 / 3 ํ์ดํ ๋ฐฉํฅ ๋ฐ๋ )
(1) ์ฌ์ฉ์๊ฐ ๋ณดํธ๋ ๋ฆฌ์์ค ์์ฒญ
(2) ์ธ์ฆ ๊ด๋ฆฌ์ ์ญํ ์ ํ๋ ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉ์์ ํฌ๋ฆฌ๋ด์ (Credential) ์์ฒญ
โ๏ธ ์ฌ์ฉ์์ ํฌ๋ฆฌ๋ด์ (Credential)
โ ํด๋น ์ฌ์ฉ์๋ฅผ ์ฆ๋ช ํ๊ธฐ ์ํ ๊ตฌ์ฒด์ ์ธ ์๋จ
Ex. password
(3) ์ฌ์ฉ์๊ฐ ์ธ์ฆ ๊ด๋ฆฌ์์๊ฒ ํฌ๋ฆฌ๋ด์ ์ ๊ณต
(4) ์ธ์ฆ ๊ด๋ฆฌ์๊ฐ ํฌ๋ฆฌ๋ด์ ์ ์ฅ์์์ ์ฌ์ฉ์์ ํฌ๋ฆฌ๋ด์ ์กฐํ
(5) ์ธ์ฆ ๊ด๋ฆฌ์๊ฐ ์ฌ์ฉ์๊ฐ ์ ๊ณตํ ํฌ๋ฆฌ๋ด์ ๊ณผ ํฌ๋ฆฌ๋ด์ ์ ์ฅ์์ ์ ์ฅ๋ ํฌ๋ฆฌ๋ด์ ์ ๋น๊ตํด ๊ฒ์ฆ ์์ ์ํ
(6) ์ ํจํ ํฌ๋ฆฌ๋ด์ ์ด ์๋๋ผ๋ฉด Exception throw
(7) ์ ํจํ ํฌ๋ฆฌ๋ด์ ์ด๋ผ๋ฉด
(8) ์ ๊ทผ ๊ฒฐ์ ๊ด๋ฆฌ์ ์ญํ ์ ํ๋ ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉ์๊ฐ ์ ์ ํ ๊ถํ์ ๋ถ์ฌ๋ฐ์๋์ง ๊ฒ์ฆ
(9) ์ ์ ํ ๊ถํ์ ๋ถ์ฌ๋ฐ์ง ๋ชปํ ์ฌ์ฉ์๋ผ๋ฉด Exception throw
(10) ์ ์ ํ ๊ถํ์ ๋ถ์ฌ ๋ฐ์ ์ฌ์ฉ์๋ผ๋ฉด ๋ณดํธ๋ ๋ฆฌ์์ค์ ์ ๊ทผ ํ์ฉ
โ๏ธ ์๋ธ๋ฆฟ ํํฐ (Servlet Filter)
- ์ ํ๋ฆฌ์ผ์ด์
์ ์๋ํฌ์ธํธ์ ์์ฒญ์ด ๋๋ฌํ๊ธฐ ์ ์ ์ค๊ฐ์์ ์์ฒญ์ ๊ฐ๋ก์ฑ ํ ์ด๋ค ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๋๋ก ํด์ฃผ๋ Java ์ ๊ณต API (์ปดํฌ๋ํธ)
โjavax.servlet.Filter
์ธํฐํ์ด์ค - ์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์๋ธ๋ฆฟ ํํฐ๋ ์น ์์ฒญ(request)์ ๊ฐ๋ก์ฑ ์ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๊ณ ,
์๋ํฌ์ธํธ์์ ์์ฒญ ์ฒ๋ฆฌ๊ฐ ๋๋ ํ ๋๋ฌ๋๋ ์๋ต(response)์ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํ๊ธฐ ์ ์ ํ์ฒ๋ฆฌ๋ฅผ ํ ์ ์์ - ์๋ธ๋ฆฟ ํํฐ๋ ํ๋ ์ด์์ ํํฐ๋ค์ ์ฐ๊ฒฐํด ํํฐ ์ฒด์ธ ๊ตฌ์ฑ ๊ฐ๋ฅ
- ์์ฒญ URI path๋ฅผ ๊ธฐ๋ฐ์ผ๋ก HttpServletRequest ์ฒ๋ฆฌ
โ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ ์ ์กํ๋ฉด, ์๋ธ๋ฆฟ ์ปจํ ์ด๋๋ ์์ฒญ URI์ ๊ฒฝ๋ก๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ด๋ค Filter์ ์ด๋ค Servlet์ ๋งคํํ ์ง ๊ฒฐ์
โ ์๋ธ๋ฆฟ ๊ธฐ๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์์ Servlet Filter ์์น
โ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ ์ ์กํ๋ฉด ์ ์ผ ๋จผ์ Servlet Filter ๊ฑฐ์น๊ณ ,
์ดํ Filter์์ ์ฒ๋ฆฌ๊ฐ ๋ชจ๋ ์๋ฃ๋๋ฉด DispatcherServlet์์ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ํธ๋ค๋ฌ์ ๋งคํํ๊ธฐ ์ํ ๋ค์ ์์
์คํ
[์ฐธ๊ณ ] https://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html
โ๏ธ ํํฐ ์ฒด์ธ (Filter Chain)
• ์ฌ๋ฌ๊ฐ์ Filter๊ฐ ์ฒด์ธ์ ํ์ฑํ๊ณ ์๋ Filter์ ๋ฌถ์
• ๊ฐ๊ฐ ํํฐ๋ค์ด doFilter() ๋ฉ์๋ ๊ตฌํํด์ผํ๊ณ , doFilter() ๋ฉ์๋ ํธ์ถ์ ํตํด ํํฐ์ฒด์ธ ํ์ฑ
( ๊ฐ ํํฐ๋ค์ ์์์ ๋ฐ๋ผ ๋์ํ๋๋ก ์ง์ ๊ฐ๋ฅ )
• Filter ์ธํฐํ์ด์ค ๊ตฌํํ๊ณ ์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ๊ตฌํํ๋ค๋ฉด,
์๋ธ๋ฆฟ ํํฐ์์ ์์ฑํ ํน๋ณํ ์์ ๋ค์ ์ํํ ๋ค,
HttpServlet์ ๊ฑฐ์ณ DispatcherServlet์ ์์ฒญ์ด ์ ๋ฌ๋๋ฉฐ,
๋ฐ๋๋ก DispatcherServlet์์ ์ ๋ฌํ ์๋ต์ ๋ํด ๋ํ ํน๋ณํ ์์ ์ ์ํํ ์ ์์
โ๏ธ ํํฐ ์ฒด์ธ์ ์์ ์ง์
- Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ Filter์ @Order ์ ๋ํ ์ด์ ์ถ๊ฐํด์ ์์ ์ง์ ๊ฐ๋ฅ
- Ordered ์ธํฐํ์ด์ค ๊ตฌํํด์ ์์ ์ง์ ๊ฐ๋ฅ
- FilterRegistrationBean ์ด์ฉํด ๋ช ์์ ์ผ๋ก ์์ ์ง์ ๊ฐ๋ฅ
โ Servlet Filter ๊ธฐ๋ณธ ๊ตฌ์กฐ
public class FirstFilter implements Filter {
// ์ด๊ธฐํ ์์
public void init(FilterConfig filterConfig) throws ServletException {
โ
}
โ
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// request(ServletRequest)๋ฅผ ์ด์ฉํด ๋ค์ Filter๋ก ๋์ด๊ฐ๊ธฐ ์ ์ฒ๋ฆฌ ์์
์ํ
โ
chain.doFilter(request, response);
โ
// response(ServletResponse)๋ฅผ ์ด์ฉํด response์ ๋ํ ํ์ฒ๋ฆฌ ์์
์ํ
}
โ
public void destroy() {
// Filter๊ฐ ์ฌ์ฉํ ์์์ ๋ฐ๋ฉํ๋ ์ฒ๋ฆฌ
}
}
init()
๋ฉ์๋
โ ์์ฑํ Filter์ ๋ํ ์ด๊ธฐํ ์์ ์งํdoFilter()
๋ฉ์๋
โ ํด๋น Filter๊ฐ ์ฒ๋ฆฌํ๋ ์ค์ง์ ์ธ ๋ก์ง ๊ตฌํdestroy()
๋ฉ์๋
โ Filter๊ฐ ์ปจํ ์ด๋์์ ์ข ๋ฃ๋ ๋ ํธ์ถ
โ ์ฃผ๋ก Filter๊ฐ ์ฌ์ฉํ ์์์ ๋ฐ๋ฉํ๋ ์ฒ๋ฆฌ ๋ฑ์ ๋ก์ง์ ์์ฑํ๊ณ ์ ํ ๋ ์ฌ์ฉ
โ Spring Security์ Filter Chain
( โฌ๏ธ ์๋ธ๋ฆฟ ํํฐ์ Spring Security Filter๊ฐ ์ถ๊ฐ๋ ๋ชจ์ต )
- Spring Security์์ ๋ณด์์ ์ํ ์์ ์ ์ฒ๋ฆฌํ๋ ํํฐ์ ๋ชจ์
- Spring Security์ Filter Chain์ URL ๋ณ๋ก ์ฌ๋ฌ๊ฐ ๋ฑ๋ก ๊ฐ๋ฅ
DelegatingFilterProxy
/FilterChainProxy
ํด๋์ค๋ Filter ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํ
โ ์๋ธ๋ฆฟ ํํฐ๋ก์จ์ ์ญํ ์ ํจ
( ์ด๋ฆ๋ง ์กฐ๊ธ ๋ค๋ฅผ๋ฟ )
โ๏ธ DelegatingFilterProxy
- Bean์ผ๋ก ๋ฑ๋ก๋ Spring Security์ ํํฐ ์ฌ์ฉ ์์์
( ์๋ธ๋ฆฟ ํํฐ์ ์ฐ๊ฒฐ๋๋ Spring Security๋ง์ ํํฐ๋ฅผ ApplicationContext์ Bean์ผ๋ก ๋ฑ๋กํ ํ, ์ด Bean๋ค์ ์ด์ฉํด์ ๋ณด์๊ณผ ๊ด๋ จ๋ ์ฌ๋ฌ๊ฐ์ง ์์ ๋ค์ ์ฒ๋ฆฌ ) - <์๋ธ๋ฆฟ ์ปจํ
์ด๋ ์์ญ์ ํํฐ>์ <ApplicationContext์ Bean์ผ๋ก ๋ฑ๋ก๋ ํํฐ๋ค>์ ์ฐ๊ฒฐํด์ฃผ๋ ๋ธ๋ฆฟ์ง ์ญํ
( ๋ณด์ ๊ด๋ จ X )
โ๏ธ FilterChainProxy
- Spring Security์ Filter๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ์์์
โ FilterChainProxy๋ถํฐ Spring Seucrity์์ ์ ๊ณตํ๋ ๋ณด์ ํํฐ๋ค์ด ํ์ํ ์์ ์ ์ํํจ
- Servlet Filter๋ค์ Bean์ผ๋ก ๋ฑ๋ก์ด ์๋์ง๋ง, Security Filter๋ค์ ๋ชจ๋ Bean์ผ๋ก ๋ฑ๋ก์ด ๋จ
- Filter Chain์ด ์์ ๋ ์ด๋ค Filter Chain์ ์ฌ์ฉํ ์ง ๊ฒฐ์
โ ๊ฐ์ฅ ๋จผ์ ๋งค์นญ๋ Filter Chain ์คํ
- Filter Chain์ด ์์ ๋ ์ด๋ค Filter Chain์ ์ฌ์ฉํ ์ง ๊ฒฐ์
Ex.
• /api/** ํจํด์ Filter Chain์ด ์๊ณ , /api/message URL ์์ฒญ ์ ์กํ๋ ๊ฒฝ์ฐ
โ ๋ํดํธ ํจํด์ธ /**๋ ์ผ์นํ์ง๋ง,
/api/** ํจํด๊ณผ ์ ์ผ ๋จผ์ ๋งค์นญ๋๋ฏ๋ก, ๊ฐ์ฅ ๋จผ์ ๋งค์นญ๋๋ /api/** ํจํด๊ณผ ์ผ์นํ๋ Filter Chain๋ง ์คํ
• /message/** ํจํด์ Filter Chain์ด ์๋๋ฐ, /message/ URL ์์ฒญ์ ์ ์กํ๋ ๊ฒฝ์ฐ
โ ๋งค์นญ๋๋ Filter Chain์ด ์์ผ๋ฏ๋ก, ๋ํดํธ ํจํด์ธ /** ํจํด์ Filter Chain ์คํ
โ๏ธ Spring Security์์ ์ง์ํ๋ Filter ์ข ๋ฅ
- ์์ฃผ ๋ง์ง๋ง, ํญ์ ๋ชจ๋ Filter๊ฐ ์ํ๋๋ ๊ฒ์ด ์๋๋ผ ํ๋ก์ ํธ ๊ตฌ์ฑ ๋ฐ ์ค์ ์ ๋ฐ๋ผ ์ผ๋ถ์ Filter๋ง ํ์ฑํ ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ง์ ์ ์ผ๋ก ๊ฐ๋ฐ์๊ฐ ํธ๋ค๋งํ ํ์๊ฐ ์๋ Filter๋ค์ด ๋๋ถ๋ถ
โ
โ ๊ฐ๋ฐ์๊ฐ Custom Filter๋ฅผ ์์ฑํ๊ณ ๋ฑ๋กํ ๊ฒฝ์ฐ ๊ธฐ์กด ํํฐ๋ค ์ฌ์ด์์ ์ฐ์ ์์๋ฅผ ์ ์ฉํด ์ํ๋์ด์ผํ ํ์๊ฐ ์๋ ๊ฒฝ์ฐ์ ์ฐธ๊ณ ํด์ ์ ์ฉํ๋ฉด ๋จ
[์ฐธ๊ณ ] https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-security-filters
โ๏ธ Spring Security์ ์ปดํฌ๋ํธ๋ก ๋ณด๋ ์ธ์ฆ(Authentication) ์ฒ๋ฆฌ ํ๋ฆ
( Spring Security๋ Filter๋ก ์์ํด์ Filter๋ก ๋๋๋ค ! )
( โฌ๏ธ ๋ก๊ทธ์ธ์ ๋ํ ์ธ์ฆ ์ฒ๋ฆฌ ํ๋ฆ )
(1) ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ํผ ๋ฑ์ผ๋ก Spring Security๊ฐ ์ ์ฉ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ request(Username/Password) ์ ์ก
- Filter Chain๊น์ง ๋ค์ด์ค๋ฉด
UsernamePasswordAuthenticationFilter
๊ฐ ํด๋น ์์ฒญ์ ์ ๋ฌ ๋ฐ์
(2) ๋ก๊ทธ์ธ ์์ฒญ์ ๋ฐ์ UsernamePasswordAuthenticationFilter
๊ฐ request์ ์ ๋ณด(Username/Password)๋ฅผ ์ด์ฉํ์ฌ UsernamePasswordAuthenticationToken
์์ฑ ํ,Authentication
์ UsernamePasswordAuthenticationFilter
์๊ฒ ๋ค์ ์ ๋ฌ
UsernamePasswordAuthenticationToken
โAuthentication
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ตฌํ ํด๋์ค- ์ฌ๊ธฐ์
Authentication
์ ์์ง ์ธ์ฆ์ด ๋์ง ์์
(3) UsernamePasswordAuthenticationFilter
๊ฐ ํด๋น Authentication
์ AuthenticationManager
์๊ฒ ์ ๋ฌ
AuthenticationManager
โ ์ธ์ฆ ์ฒ๋ฆฌ๋ฅผ ์ด๊ดํ๋ ๋งค๋์ ์ญํ ์ ํ๋ ์ธํฐํ์ด์คProviderManager
โAuthenticationManager
๋ฅผ ๊ตฌํํ ๊ตฌํ ํด๋์ค
โProviderManager implements AuthenticationManager
(4) ProviderManager
๊ฐ AuthenticationProvider
์๊ฒ Authentication
์ ๋ฌ
(5) Authentication
์ ๋ฌ๋ฐ์ AuthenticationProvider
๊ฐ UserDetailsService
๋ฅผ ์ด์ฉํด UserDetails
์กฐํ
โ๏ธ UserDetails
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฑ์ ์ ์ฅ์์ ์ ์ฅ๋ ์ฌ์ฉ์์ Username + ์ฌ์ฉ์์ ์๊ฒฉ์ ์ฆ๋ช ํด์ฃผ๋ ํฌ๋ฆฌ๋ด์ (Credential)์ธ Password + ์ฌ์ฉ์์ ๊ถํ ์ ๋ณด๋ฅผ ํฌํจํ๊ณ ์๋ ์ปดํฌ๋ํธ
- ์ด
UserDetails
๋ฅผ ์ ๊ณตํ๋ ์ปดํฌ๋ํธ๊ฐ ๋ฐ๋กUserDetailsService
(6) UserDetailsServic๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฑ์ ์ ์ฅ์์์ ์ฌ์ฉ์์ ํฌ๋ฆฌ๋ด์ (Credential)์ ํฌํจํ ์ฌ์ฉ์์ ์ ๋ณด ์กฐํ
(7) ์กฐํํ ์ฌ์ฉ์์ ํฌ๋ฆฌ๋ด์
+ ์ ๋ณด ๊ธฐ๋ฐ์ผ๋ก UserDetails
์์ฑ
(8) ์์ฑ๋ UserDetails
๋ฅผ ๋ค์ AuthenticationProvider
์๊ฒ ์ ๋ฌ
(9) UserDetails
๋ฅผ ์ ๋ฌ ๋ฐ์ AuthenticationProvider
๊ฐ PasswordEncoder
๋ฅผ ์ด์ฉํด <UserDetails
์ ํฌํจ๋ ์ํธํ ๋ Password>์ <์ธ์ฆ์ ์ํ Authentication ์์ ํฌํจ๋ Password>๊ฐ ์ผ์นํ๋์ง ๊ฒ์ฆ ํ,
- ๊ฒ์ฆ ์ฑ๊ณต ์ โ
UserDetails
๋ฅผ ์ด์ฉํด ์ธ์ฆ๋Authentication
์์ฑ - ๊ฒ์ฆ ์คํจ ์ โ
Exception
๋ฐ์์ํค๊ณ ์ธ์ฆ ์ฒ๋ฆฌ ์ค๋จ
(10) AuthenticationProvider
๊ฐ ์ธ์ฆ๋ Authentication
์ ProviderManager
์๊ฒ ์ ๋ฌ
- ์ฌ๊ธฐ์
Authentication
์ ์ธ์ฆ์ด ๋์ด, ์ธ์ฆ์ ์ฑ๊ณตํ ์ฌ์ฉ์์ ์ ๋ณด(Principal/Credential/GrantedAuthorities) ๊ฐ์ง๊ณ ์์
(11) ProviderManager
๊ฐ ์ธ์ฆ๋ Authentication
์ ๋ค์ UsernamePasswordAuthenticationFilter
์๊ฒ ์ ๋ฌ
- But, Credential์ ์ ์ถ๋๋ฉด ์๋๋ ๊ฐ์ธ์ ๋ณด์ด๊ธฐ ๋๋ฌธ์ ๋ด๋ถ์ ์ผ๋ก ์ญ์ ํ๊ณ ์ ๋ฌํจ
(12) ์ธ์ฆ๋ Authentication
์ ์ ๋ฌ ๋ฐ์ UsernamePasswordAuthenticationFilter
๊ฐ SecurityContextHolder
๋ฅผ ์ด์ฉํด SecurityContext
์ ์ธ์ฆ๋ Authentication
์ ์ฅ
- Principal / Credential / Collection< GrantedAuthority > ์ธ๊ฐ์ ํ๋๋ก ๋๋์ด ์ ์ฅ๋จ
- Credential ํ๋๋ ๊ฐ์ธ์ ๋ณด๊ฐ ์ญ์ ๋๊ณ ์ ๋ฌ๋๊ธฐ ๋๋ฌธ์ null๊ฐ์
- SecurityContext๋ Spring Security์ ์ธ์ ์ ์ฑ ์ ๋ฐ๋ผ์ HttpSession ์ ์ ์ฅ๋์ด ์ฌ์ฉ์์ ์ธ์ฆ ์ํ๋ฅผ ์ ์งํ๊ธฐ๋ ํ๊ณ , HttpSession์ ์์ฑํ์ง ์๊ณ ๋ฌด์ํ๋ฅผ ์ ์งํ๊ธฐ๋ ํจ
[์ฐธ๊ณ ] https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html
โ ์ธ์ฆ ์ฒ๋ฆฌ ํ๋ฆ์์ ์ฌ์ฉ๋ Spring Security ์ธ์ฆ ์ปดํฌ๋ํธ
โ UsernamePasswordAuthenticationFilter
- ์ฌ์ฉ์์ ๋ก๊ทธ์ธ request๋ฅผ ์ ์ผ ๋จผ์ ๋ง๋๋ ์ปดํฌ๋ํธ
- ๋ก๊ทธ์ธ ํผ์์ ์ ์ถ๋๋ Username๊ณผ Password๋ฅผ ํตํ ์ธ์ฆ์ ์ฒ๋ฆฌํ๋ Filter
- ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ์ ๋ฌ ๋ฐ์ Username/Password๋ฅผ Spring Security๊ฐ ์ธ์ฆ ํ๋ก์ธ์ค์์ ์ด์ฉํ ์ ์๋๋ก
UsernamePasswordAuthenticationToken
์์ฑ
๋ด๋ถ๋ฅผ ์ดํด๋ณด๋ฉด, โฌ๏ธ
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { // (1)
โ
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username"; // (2)
โ
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password"; // (3)
โ
private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/login","POST"); // (4)
โ
...
...
โ
public UsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager); // (5)
}
โ
// (6)
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
// (6-1)
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
โ โ
String username = obtainUsername(request);
...
โ
String password = obtainPassword(request);
...
โ
// (6-2)
UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
...
โ โ
return this.getAuthenticationManager().authenticate(authRequest); // (6-3)
}
โ
...
...
}
โ (1)๊ณผ ๊ฐ์ด AbstractAuthenticationProcessingFilter
์์
UsernamePasswordAuthenticationFilter ํด๋์ค์ ์ด๋ฆ์ด Filter๋ก ๋๋์ง๋ง doFilter() ๋ฉ์๋ ์กด์ฌ X
But, doFilter() ๋ฉ์๋๋ ๊ผญ ์์ด์ผ ํจ
โ ์์ ํด๋์ค์ธ AbstractAuthenticationProcessingFilter ํด๋์ค๊ฐ doFilter() ๋ฉ์๋๋ฅผ ํฌํจํ๊ณ ์์
โ ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ก๊ทธ์ธ request๋ฅผ ์ ์ผ ๋จผ์ ์ ๋ฌ ๋ฐ๋ ํด๋์ค๋ UsernamePasswordAuthenticationFilter์ ์์ ํด๋์ค์ธ AbstractAuthenticationProcessingFilter ํด๋์ค์ธ ๊ฒ
โ
โ (2)์ (3)์ ํตํด ํด๋ผ์ด์ธํธ์ ๋ก๊ทธ์ธ ํผ์ ํตํด ์ ์ก๋๋ request parameter์ ๋ํดํธ name์ username๊ณผ password๋ผ๋ ๊ฒ์ ์ ์ ์์
โ
โ (4)์ AntPathRequestMatcher๋ ํด๋ผ์ด์ธํธ์ URL์ ๋งค์น๋๋ ๋งค์ฒ
โ (4)๋ฅผ ํตํด ํด๋ผ์ด์ธํธ์ URL์ด "/login"์ด๊ณ , HTTP Method๊ฐ POST์ผ ๊ฒฝ์ฐ ๋งค์น ๋ ๊ฑฐ๋ผ๋ ์ฌ์ค ์์ธก ๊ฐ๋ฅ
โ๏ธ Spring Security์ ๊ถํ ๋ถ์ฌ ์ฒ๋ฆฌ ํ๋ฆ
( ์ฌ์ฉ์ ์ธ์ฆ ํ, ์ ํ๋ฆฌ์ผ์ด์ ๋ฆฌ์์ค์ ์ ๊ทผ ๊ถํ์ ๋ถ์ฌํ๋ ํ๋ฆ )
(1) AuthorizationFilter
๊ฐ SecurityContextHolder
๋ก ๋ถํฐ Authentication
ํ๋
AuthorizationManager
- ๊ถํ ๋ถ์ฌ ์ฒ๋ฆฌ๋ฅผ ์ด๊ดํ๋ ๋งค๋์ ์ญํ ์ ํ๋ ์ธํฐํ์ด์ค
(2) SecurityContextHolder
๋ก ๋ถํฐ ํ๋ํ Authentication
+ HttpServletRequest
๋ฅผ AuthorizationManager
์๊ฒ ์ ๋ฌ
RequestMatcherDelegatingAuthorizationManager
AuthorizationManager
๋ฅผ ๊ตฌํํ๋ ๊ตฌํ์ฒด ์ค ํ๋RequestMatcher
ํ๊ฐ์์ ๊ธฐ๋ฐ์ผ๋ก ํด๋น ํ๊ฐ์์ ๋งค์น๋๋AuthorizationManager
์๊ฒ ๊ถํ ๋ถ์ฌ ์ฒ๋ฆฌ๋ฅผ ์์ํ๋ ์ญํ
( ์ง์ ๊ถํ ๋ถ์ฌ ์ฒ๋ฆฌ X )
(3) RequestMatcherDelegatingAuthorizationManager
๋ด๋ถ์ ๋งค์น๋๋ AuthorizationManager
๊ตฌํ ํด๋์ค๊ฐ ์๋ค๋ฉด,
ํด๋น AuthorizationManager
๊ตฌํ ํด๋์ค๊ฐ ์ฌ์ฉ์์ ๊ถํ์ ์ฒดํฌ
(4) ์ ์ ํ ๊ถํ์ด๋ผ๋ฉด โ ๋ค์ ์์ฒญ ํ๋ก์ธ์ค๋ฅผ ๊ณ์ ์ด์ด๊ฐ
( Filter ๋ค ๋๋๋ฉด DispatcherServlet์ผ๋ก ๋์ด๊ฐ )
(5) ์ ํ ๊ถํ์ด ์๋๋ผ๋ฉด โ AccessDeniedException
์ด throw๋๊ณ , ExceptionTranslationFilter
๊ฐ AccessDeniedException
์ฒ๋ฆฌ
โ ๊ถํ ๋ถ์ฌ ํ๋ฆ์์ ์ฌ์ฉ๋ Spring Security ๊ถํ ๋ถ์ฌ ์ปดํฌ๋ํธ
โ
AuthorizationFilter
- URL์ ํตํด ์ฌ์ฉ์์ ์ก์ธ์ค๋ฅผ ์ ํํ๋ ๊ถํ ๋ถ์ฌ Filter
- Spring Security 5.5 ๋ฒ์ ๋ถํฐ FilterSecurityInterceptor๋ฅผ ๋์ฒด
๋ด๋ถ๋ฅผ ์ดํด๋ณด๋ฉด, โฌ๏ธ
public class AuthorizationFilter extends OncePerRequestFilter {
โ
private final AuthorizationManager<HttpServletRequest> authorizationManager;
โ
โ ...
...
โ
// (1)
public AuthorizationFilter(AuthorizationManager<HttpServletRequest> authorizationManager) {
Assert.notNull(authorizationManager, "authorizationManager cannot be null");
this.authorizationManager = authorizationManager;
}
โ
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
โ
AuthorizationDecision decision = this.authorizationManager.check(this::getAuthentication, request); // (2)
โ this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, request, decision);
if (decision != null && !decision.isGranted()) {
throw new AccessDeniedException("Access Denied");
}
filterChain.doFilter(request, response);
}
...
}
โ (1)๊ณผ ๊ฐ์ด AuthorizationFilter ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋, AuthorizationManager๋ฅผ DI
โ
โ DI ๋ฐ์ AuthorizationManager๋ฅผ ํตํด ๊ถํ ๋ถ์ฌ ์ฒ๋ฆฌ ์งํ
โ
โ (2)์ ๊ฐ์ด DI ๋ฐ์ AuthorizationManager์ check() ๋ฉ์๋๋ฅผ ํธ์ถํด ์ ์ ํ ๊ถํ ๋ถ์ฌ ์ฌ๋ถ๋ฅผ ์ฒดํฌ
( check() ๋ฉ์๋๋ AuthorizationManager ๊ตฌํ ํด๋์ค์ ๋ฐ๋ผ ๊ถํ ์ฒดํฌ ๋ก์ง์ด ๋ค๋ฆ )
URL ๊ธฐ๋ฐ์ผ๋ก ๊ถํ ๋ถ์ฌ ์ฒ๋ฆฌ๋ฅผ ํ๋ AuthorizationFilter๋ AuthorizationManager์ ๊ตฌํ ํด๋์ค๋ก RequestMatcherDelegatingAuthorizationManager๋ฅผ ์ฌ์ฉ
โ
AuthorizationManager
- ๊ถํ ๋ถ์ฌ ์ฒ๋ฆฌ๋ฅผ ์ด๊ดํ๋ ๋งค๋์ ์ญํ ์ ํ๋ ์ธํฐํ์ด์ค
๋ด๋ถ๋ฅผ ์ดํด๋ณด๋ฉด, โฌ๏ธ
@FunctionalInterface
public interface AuthorizationManager<T> {
...
โ
@Nullable
AuthorizationDecision check(Supplier<Authentication> authentication, T object);
โ
}
โ check()
๋ฉ์๋ ํ๋๋ง ์ ์๋์ด ์์
โ
โ Supplier์ ์ ๋๋ฆญ ํ์
์ ๊ฐ์ฒด๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๊ฐ์ง
โ
RequestMatcherDelegatingAuthorizationManager
- AuthorizationManager์ ๊ตฌํ ํด๋์ค ์ค ํ๋
- ์ง์ ๊ถํ ๋ถ์ฌ ์ฒ๋ฆฌ๋ฅผ ์ํ ํ์ง ์๊ณ
RequestMatcher
๋ฅผ ํตํด ๋งค์น๋๋AuthorizationManager
๊ตฌํ ํด๋์ค์๊ฒ ๊ถํ ๋ถ์ฌ ์ฒ๋ฆฌ๋ฅผ ์์
๋ด๋ถ๋ฅผ ์ดํด๋ณด๋ฉด, โฌ๏ธ
public final class RequestMatcherDelegatingAuthorizationManager implements AuthorizationManager<HttpServletRequest> {
โ
...
...
โ
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, HttpServletRequest request) {
if (this.logger.isTraceEnabled()) {
this.logger.trace(LogMessage.format("Authorizing %s", request));
}
โ
// (1)
for (RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>> mapping : this.mappings) {
โ
RequestMatcher matcher = mapping.getRequestMatcher(); // (2)
MatchResult matchResult = matcher.matcher(request);
if (matchResult.isMatch()) { // (3)
AuthorizationManager<RequestAuthorizationContext> manager = mapping.getEntry();
if (this.logger.isTraceEnabled()) {
this.logger.trace(LogMessage.format("Checking authorization on %s using %s", request, manager));
}
return manager.check(authentication,
new RequestAuthorizationContext(request, matchResult.getVariables()));
}
}
this.logger.trace("Abstaining since did not find matching RequestMatcher");
return null;
}
}
โ (1)์์ check()
๋ฉ์๋์ ๋ด๋ถ์์ ๋ฃจํ๋ฅผ ๋๋ฉด์ RequestMatcherEntry ์ ๋ณด๋ฅผ ์ป๊ณ
โ (2)์์ RequestMatcher ๊ฐ์ฒด๋ฅผ ์ป์
( ์ฌ๊ธฐ์์ RequestMatcher
๋ SecurityConfiguration
์์ .antMatchers("/orders/**").hasRole("ADMIN")
์ ๊ฐ์ ๋ฉ์๋ ์ฒด์ธ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋จ )
โ
โ (3)์์ MatchResult.isMatch()
๊ฐ true์ด๋ฉด AuthorizationManager
๊ฐ์ฒด๋ฅผ ์ป์ ๋ค, ์ฌ์ฉ์์ ๊ถํ ์ฒดํฌ
๐ ๋๋์
๊ทธ๋๋ ํ๋ฆ๊น์ง๋ ์ธ์ฐ๋ฉด ๊ด์ฐฎ๋ค !!
์ฝ๋์์ ๋ณด๊ณ ํ๋ฆ์ ๋๋ ์ ์๋๋ก ๊ณต๋ถํด์ผ์ง
( ๋ณธ ๊ฒ์๋ฌผ์ 2022/11/23์ ์์ฑํ ๊ธ์ ์ฎ๊ธด ๊ธ์ ๋๋ค. ์๋ฌธ์ ์๊ธฐ์ ์์! )
'โข CodeStates BootCamp > Section 4' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ [Section4] 6. [Spring Security] OAuth2 2 (0) | 2023.04.13 |
---|---|
๐ [Section4] 5. [ Spring Security ] OAuth2 1 (0) | 2023.04.13 |
๐ [Section4] 4. [ Spring Security ] JWT ์ธ์ฆ (0) | 2023.04.13 |
๐ [Section4] 2. [ Spring Security ] Security ๊ธฐ๋ณธ 1 (0) | 2023.04.12 |
๐ [Section4] 1. ์ธ์ฆ / ๋ณด์ (0) | 2023.04.12 |