Upload
beom-kyun-choi
View
4.820
Download
1
Embed Size (px)
DESCRIPTION
스프링 시큐리티의 주요 구성 요소인 SecurityFilterChain, AuthenticationManager, SecurityInterceptor의 구조 소개
Citation preview
스프링 시큐리티 구조 이해(웹 어플리케이션 중심)신림 프로그래머, 최범균, 2014-07-09
목표
● 스프링 시큐리티의 구성 요소와 동작 방식 이해○ 이를 통한 커스터마이징 포인트 잡기!
기본 구성 요소
보안 관련 3요소
● 접근 주체(Principal)○ 보호된 대상에 접근하는 사용자
● 인증(Authenticate)○ 현재 사용자가 누군인지 확인하는 과정○ 일반적으로 아이디/암호를 이용해서 인증을 처리
● 인가(Authorize)○ 현재 사용자가 특정 대상(URL, 기능 등)을 사용(접근)할 권한이 있는지 검사하는 것
스프링 시큐리티와 보안 3요소의 매칭
접근 주체
인증
인가
Authentication
AuthenticationManager
SecurityInterceptor
Authentication와 SecurityContext
● Authentication의 용도○ 현재 접근 주체 정보를 담는 목적○ 인증 요청할 때, 요청 정보를 담는 목적
● SecurityContext○ Authentication을 보관○ 스프링 시큐리티는 현재 사용자에 대한
Authentication 객체를 구할 때 SecurityContext로부터 구함
SecurityContextHolder
● SecurityContext를 보관○ 기본: 쓰레드로컬에 SecurityContext를 보관
● 전형적인 SecurityContext 설정 코드Authentication auth = someMethodForGettingAuth(req, resp);try { SecurityContextHolder.getContext().setAuthentication(auth); chain.doFilter(request, response); // 이후 코드에서 동일 SecurityContext 사용} finally { SecurityContextHolder.clearContext();} 스프링 시큐리티가 유사한 필터 이미 제공
참고, Authentication의 주요 메서드
● Authentication의 주요 메서드○ String getName(): 사용자의 이름○ Object getCredential(): 증명 값 (비밀번호 등)○ Object getPrincipal(): 인증 주체 정보○ boolean isAuthenticated(): 인증되었는지 여부○ Collection<GrantedAuthority) getAuthorities(): 현재 사용자가 가진 권한(GrantedAuthority)
AuthenticationManager
● 인증을 처리함public interface AuthenticationManager { Authentication authenticate(Authentication authentication) throws AuthenticationException;}
● 인증에 성공하면 인증 정보를 담고 있는 Authentication 객체 리턴○ 스프링 시큐리티는 리턴한 Authentication 객체를 SecurityContext에 보관 및 인증 상태를 유지하기 위해 세션에 보관
● 인증 실패시 AuthenticationException을 발생시킴
(Abstract)SecurityInterceptor
● 인가를 처리○ 웹의 경우 FilterSecurityInterceptor 구현 사용○ AccessDecisionManager에 권한 검사 위임
public interface AccessDecisionManager { void decide(Authentication authentication, // 사용자 Object object, // 접근 자원 Collection<ConfigAttribute> configAttributes) // 보안 설정 throws AccessDeniedException, InsufficientAuthenticationException; boolean supports(ConfigAttribute attribute); boolean supports(Class<?> clazz);}
● 사용자가 자원의 보안 설정 기준으로, 접근 권한이 없을 경우 익셉션 발생
SecurityFilterChain
웹 어플리케이션 보안 지원
● 보인 필터 체인를 이용한 보안 처리FilterChainProxy
보안 필터 체인
실제 자원
주로 다음 기능을 제공- Authentication 정보 생성- 접근 권한 검사- 인증 요청 처리
<sec:http use-expressions="true"> <sec:intercept-url pattern="/admin/**" access="hasAuthority('ROLE_ADMIN')" /> <sec:intercept-url pattern="/manager/**" access="hasRole('ROLE_MANAGER')" /> <sec:intercept-url pattern="/member/**" access="isAuthenticated()" /> <sec:intercept-url pattern="/**" access="permitAll"/>
<sec:form-login /> <sec:logout />
</sec:http>
생성
생성
스프링 빈으로 등록된 필터(springSecurityFilterChain)
웹 요청을 FilterChainProxy 적용
<filter> <filter-name> springSecurityFilterChain </filter-name> <filter-class> o...filter.DelegatingFilterProxy </filter-class></filter><filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
FilterChainProxy
보안 필터 체인
DelegatingFilterProxy
보안 필터 체인
보안 필터 체인의 주요 구성 요소
SecurityContextPersistenceFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor접근 권한 검사
익셉션 처리
로그인 폼 출력
인증 요청 처리
로그아웃 요청 처리
Authentication 로딩 ● 필터 체인은 순서대로 실행
● 필터에 따라 요청을 처리하고 체인 실행을 끝내기도 함
임의 사용자 처리
접근 권한 없을 때 처리, 인증 전보안 필터 체인
SecurityContextPersistenceFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
1. 요청
AccessDecisionManager 2. 권한 검사
요청
4. 익셉션 발생
AuthenticationEntryPoint
5. 인증 과정 시작 처리
<sec:form-login login-page="/user/loginform"/>
접근 권한 없을 때 처리, 인증 상태보안 필터 체인
SecurityContextPersistenceFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
1. 요청
AccessDecisionManager 3. 권한 검사
요청
4. 익셉션 발생
AccessDeniedHandler
5. 접근 거부 응답 처리
<sec:access-denied-handler error-page="/accessDenied"/>
SecurityContextRepository
2. 보관된 SecurityContext를 로딩
기본 로그인 폼 제공보안 필터 체인
SecurityContextPersistenceFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
1. /spring_security_login 경로 요청
2. 로그인 폼 응답 전송
인증 요청 처리 과정 (성공시)보안 필터 체인
SecurityContextPersistenceFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
1. 인증 요청
AuthenticationManager
2. 인증 실행
SecurityContext
3. Authentication 보관
AuthenticationSuccessHandler
4. 성공 후처리
SecurityContextRepository
5. SecurityContext 보관
<sec:form-login login-processing-url="/user/login" username-parameter="userid" password-parameter="password" default-target-url="/index"/>
인증 요청 처리 과정 (실패시)보안 필터 체인
SecurityContextPersistenceFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
1. 인증 요청
AuthenticationManager
2. 인증 실행
AuthenticationFailureHandler
3. 실패 후처리
<sec:form-login ... authentication-failure-url="/user/loginform?error=true"/>
로그아웃 요청 처리 과정보안 필터 체인
SecurityContextPersistenceFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
1. 로그 아웃 요청
LogoutSuccessHandler
3. 로그아웃 후 처리
LogoutHandler2. 로그아웃 처리
<sec:logout logout-url="/user/logout" logout-success-url=”/”/>
AuthenticationManager
AuthenticationManager 구조1<sec:authentication-manager> <sec:authentication-provider> ... </sec:authentication-provider></sec:authentication-manager>
사용자 정보 제공사용자 암호 비교
AuthenticationProvider에 위임
AuthenticationManager 구조2
<sec:authentication-provider> <sec:user-service> <sec:user name="bkchoi" password="1234" authorities="ROLE_USER" /> </sec:user-service></sec:authentication-provider>
<sec:authentication-provider> <sec:jdbc-user-service data-source-ref="dataSource" id="jdbcUserService" /></sec:authentication-provider>
커스텀 구현 설정
<sec:authentication-manager >
<!-- AuthenticationProvider의 커스텀 구현 사용 --> <sec:authentication-provider ref="customAuthenticationProvider" />
<!-- DaoAuthenticationProvider 구현 사용 → <!-- UserDetailsService의 커스텀 구현 사용 --> <sec:authentication-provider user-service-ref="customUserDetailsService" />
</sec:authentication-manager>
FilterSecurityInterceptor &
AccessDecisionManager
FilterSecurityInterceptor
<sec:http use-expressions="true"> <sec:intercept-url pattern="/user/loginform" access="permitAll" /> <sec:intercept-url pattern="/user/login" access="permitAll" /> <sec:intercept-url pattern="/admin/usermanager/**" access="hasAuthority('USER_MANAGER')" /> ...</sec:http>
AccessDecisionManager
<sec:http use-expressions="true"> ...</sec:http>