(1) ์ฌ์ฉ์๊ฐ ๋ณดํธ๋ ๋ฆฌ์์ค ์์ฒญ
(2) ์ธ์ฆ ๊ด๋ฆฌ์ ์ญํ ์ ํ๋ ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉ์์ ํฌ๋ฆฌ๋ด์ (Credential) ์์ฒญ
โ๏ธ ์ฌ์ฉ์์ ํฌ๋ฆฌ๋ด์ (Credential)
โ ํด๋น ์ฌ์ฉ์๋ฅผ ์ฆ๋ช ํ๊ธฐ ์ํ ๊ตฌ์ฒด์ ์ธ ์๋จ
Ex. password
(3) ์ฌ์ฉ์๊ฐ ์ธ์ฆ ๊ด๋ฆฌ์์๊ฒ ํฌ๋ฆฌ๋ด์ ์ ๊ณต
(4) ์ธ์ฆ ๊ด๋ฆฌ์๊ฐ ํฌ๋ฆฌ๋ด์ ์ ์ฅ์์์ ์ฌ์ฉ์์ ํฌ๋ฆฌ๋ด์ ์กฐํ
(5) ์ธ์ฆ ๊ด๋ฆฌ์๊ฐ ์ฌ์ฉ์๊ฐ ์ ๊ณตํ ํฌ๋ฆฌ๋ด์ ๊ณผ ํฌ๋ฆฌ๋ด์ ์ ์ฅ์์ ์ ์ฅ๋ ํฌ๋ฆฌ๋ด์ ์ ๋น๊ตํด ๊ฒ์ฆ ์์ ์ํ
(5-1) ์ ํจํ ํฌ๋ฆฌ๋ด์ ์ด ์๋๋ผ๋ฉด Exception throw
(5-2) ์ ํจํ ํฌ๋ฆฌ๋ด์ ์ด๋ผ๋ฉด
(6) ์ ๊ทผ ๊ฒฐ์ ๊ด๋ฆฌ์ ์ญํ ์ ํ๋ ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉ์๊ฐ ์ ์ ํ ๊ถํ์ ๋ถ์ฌ๋ฐ์๋์ง ๊ฒ์ฆ
(6-1) ์ ์ ํ ๊ถํ์ ๋ถ์ฌ๋ฐ์ง ๋ชปํ ์ฌ์ฉ์๋ผ๋ฉด Exception throw
(6-2) ์ ์ ํ ๊ถํ์ ๋ถ์ฌ ๋ฐ์ ์ฌ์ฉ์๋ผ๋ฉด ๋ณดํธ๋ ๋ฆฌ์์ค์ ์ ๊ทผ ํ์ฉ
์ ํ๋ฆฌ์ผ์ด์
์ ์๋ํฌ์ธํธ์ ์์ฒญ์ด ๋๋ฌํ๊ธฐ ์ ์ ์ค๊ฐ์์ ์์ฒญ์ ๊ฐ๋ก์ฑ ํ ์ด๋ค ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๋๋ก ํด์ฃผ๋ Java ์ ๊ณต ์ปดํฌ๋ํธ
( javax.servlet.Filter
์ธํฐํ์ด์ค )
์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์๋ธ๋ฆฟ ํํฐ๋ ์น ์์ฒญ(request)์ ๊ฐ๋ก์ฑ ์ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๊ณ ,
์๋ํฌ์ธํธ์์ ์์ฒญ ์ฒ๋ฆฌ๊ฐ ๋๋ ํ ๋๋ฌ๋๋ ์๋ต(response)์ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํ๊ธฐ ์ ์ ํ์ฒ๋ฆฌ๋ฅผ ํ ์ ์์
์๋ธ๋ฆฟ ํํฐ๋ ํ๋ ์ด์์ ํํฐ๋ค์ ์ฐ๊ฒฐํด ํํฐ ์ฒด์ธ ๊ตฌ์ฑ ๊ฐ๋ฅ
์์ฒญ URI path๋ฅผ ๊ธฐ๋ฐ์ผ๋ก HttpServletRequest ์ฒ๋ฆฌ
โ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ ์ ์กํ๋ฉด, ์๋ธ๋ฆฟ ์ปจํ
์ด๋๋ ์์ฒญ URI์ ๊ฒฝ๋ก๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ด๋ค Filter์ ์ด๋ค Servlet์ ๋งคํํ ์ง ๊ฒฐ์
โ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ ์ ์กํ๋ฉด ์ ์ผ ๋จผ์ 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
์ด์ฉํด ๋ช ์์ ์ผ๋ก ์์ ์ง์ ๊ฐ๋ฅ
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๊ฐ ์ถ๊ฐ๋ ๋ชจ์ต )
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 ์คํ
Ex.
/api/**
ํจํด์ Filter Chain์ด ์๊ณ ,/api/message
URL ์์ฒญ ์ ์กํ๋ ๊ฒฝ์ฐ
โ
โ ๋ํดํธ ํจํด์ธ/**
๋ ์ผ์นํ์ง๋ง,
/api/**
ํจํด๊ณผ ์ ์ผ ๋จผ์ ๋งค์นญ๋๋ฏ๋ก, ๊ฐ์ฅ ๋จผ์ ๋งค์นญ๋๋ /api/** ํจํด๊ณผ ์ผ์นํ๋ Filter Chain๋ง ์คํ
/message/**
ํจํด์ Filter Chain์ด ์๋๋ฐ,/message/
URL ์์ฒญ์ ์ ์กํ๋ ๊ฒฝ์ฐ
โ
โ ๋งค์นญ๋๋ Filter Chain์ด ์์ผ๋ฏ๋ก, ๋ํดํธ ํจํด์ธ/**
ํจํด์ Filter Chain ์คํ
[์ฐธ๊ณ ]
https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-security-filters
( Spring Security๋ Filter๋ก ์์ํด์ Filter๋ก ๋๋๋ค ! )
( โฌ๏ธ ๋ก๊ทธ์ธ์ ๋ํ ์ธ์ฆ ์ฒ๋ฆฌ ํ๋ฆ )
(1) ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ํผ ๋ฑ์ผ๋ก Spring Security๊ฐ ์ ์ฉ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ request(Username/Password) ์ ์ก
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
์๊ฒ ์ ๋ฌ
(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
์ฌ์ฉ์์ ๋ก๊ทธ์ธ 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์ผ ๊ฒฝ์ฐ ๋งค์น ๋ ๊ฑฐ๋ผ๋ ์ฌ์ค ์์ธก ๊ฐ๋ฅ
( ์ฌ์ฉ์ ์ธ์ฆ ํ, ์ ํ๋ฆฌ์ผ์ด์
๋ฆฌ์์ค์ ์ ๊ทผ ๊ถํ์ ๋ถ์ฌํ๋ ํ๋ฆ )
(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
์ฒ๋ฆฌ
โ
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
๊ฐ์ฒด๋ฅผ ์ป์ ๋ค, ์ฌ์ฉ์์ ๊ถํ ์ฒดํฌ
๊ทธ๋๋ ํ๋ฆ๊น์ง๋ ์ธ์ฐ๋ฉด ๊ด์ฐฎ๋ค !!
์ฝ๋์์ ๋ณด๊ณ ํ๋ฆ์ ๋๋ ์ ์๋๋ก ๊ณต๋ถํด์ผ์ง
๊ทธ๋ฆผ ๊ทธ๋ฆฌ์ ๋ถ ๋ก์ก์ผ์ จ๋ค..