JCF3.0™ Spring security 가이드
From JCFWiKi
(Spring security에서 넘어옴.)
Copyright © 2008 Daewoo Information Systems Co., Ltd. |
|
목차
|
[편집] Preview: Authentication & Authorization
인증과 권한 절차(출처:http://whiteship.tistory.com/1060)
[편집] Authentication(인증)
- 자원에 대한 접근을 승인하거나 제한하기로 결정하기 전에, 사용자는 적절한 보안 확인을 해야 함.
- 로그인 페이지
[편집] Authorization(권한)
- 자원 별 접근 권한을 제한 하여야 함.
- 유저 등급별 다른 서비스 제공
[편집] spring security의 필요성
- 자바 플렛폼에서 스프링 프레임워크를 기반으로 개발된 보안 프레임워크의 필요성
- 이식성과 확장성이 우수한 보안프레임워크 필요성
[편집] Spring Security의 개요
[편집] acegi란?
- Ben Alex
- 알파벳 홀수 1, 3, 5, 7, 9를 따서 만든 이름
- Acegi는 스프링 프레임워크의 공인 서브 프로젝트이며 http://acegisecurity.org 에서 운영되고 있는 오픈소스 프로젝트
[편집] Spring Security(acegi)의 기능
- 로그인 기능 제공
- password를 통한 user 인증
- 각 개인이 허락된 리소스에 대한 check과 리소스 redirect
- 로그인 실패 시 Denied page 보여줌
- 인증 성공한 유저에 대해 유저 클라이언트에 보한 쿠키를 세팅해줌으로서 다음 인증 때 로그인 없이 열람가능
- 로그아웃 시 유저 클라이언트의 보안세션을 삭제
- 유저들의 security 등급 및 정책을 DB에서 관리할 수 있음.
[편집] Shared Component
[편집] Filters
[편집] filter?
- Acegi의 가장 상위 layer로서 인증 process,세션 핸들링, 로그아웃과 같은 common한 security 서비스를 제공한다.
- Manager와 provider등과 같이 실제적인 작업자들을 연결하여 하나의 서비스로 만든 단위이다.
- Acegi는 security에 관련된 filter들의 모임.
[편집] filter chains
- web.xml에 과도한 filter가 존재하는 복잡함을 감소시키기 위해 FilterChainProxy를 사용
- acegi를 사용하려면 web.xml에 단지 FilterChainProxy filter하나만 선언하면 됨.
[편집] AuthenticationProcessingFilter
[편집] 역할
- 로그인과 패스워드를 통한 인증을 함.
- 로그인과 관련된 요청에 폼 서브밋 URL 값(filterProcessUrl 속성)이나 로그인 실패 시 URL 값(authenticationFailureUrl 속성)들을 설정
[편집] 설정 값
- 인증 실패시 URL(authenticationFailureUrl)
- 인증 성공 시 기본적으로 이동할 URL(defaultTargetUrl)
- filter통과 시 보여지는 URL(filterProcessesUrl)
[편집] example
<bean id="authenticationProcessingFilter" class="/j_acegi_security_check org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <property name="authenticationManager" ref="authenticationManager" /> <property name="authenticationFailureUrl" value="/login.jsp?login_error=1" /> <property name="defaultTargetUrl" value="/domain.jsp" /> </bean>
[편집] Authentication 흐름
<bean id="authenticationManager“
class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list><ref local="daoAuthenticationProvider" />
<ref local="anonymousAuthenticationProvider"/></list>
</property>
</bean>
<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="jdbcDaoImpl"/> <property name="userCache" ref="userCache"/> </bean>
<bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl"> <property name="dataSource"> <ref bean="dataSource"/></property> <property name="usersByUsernameQuery"> <value>SELECT userId, password, enabled FROM USERINFO WHERE userId = ?</value> </property> <property name="authoritiesByUsernameQuery"> <value>SELECT username, authority FROM AUTHORITIES WHERE username = ?</value> </property> </bean>
[편집] HttpSessionContextIntegrationFilter
[편집] 역할
- Acegi의 Security Context를 서블릿 세션과 연결하는 역할을 담당.
- 사용자의 Authentication 객체를 매번 만드는 것은 비효율적임.
- Authentication을 저장하고 재사용하기 위하여 Acegi는 Security ContextHolder의 ThreadLocal 멤버 변수에 SecurityContext를 저장한다.
- ThreadLocal?
- 쓰레드 당 데이터 저장소,각각의 Thread에서 사용하는 객체들을 저장해둔 곳이다.
- ThreadLocal?
[편집] example
<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"> </bean>
[편집] ExceptionTranslationFilter
[편집] 역할
- 예외 상황이 발생한 경우 어떻게 처리할 것인가를 정의한다
[편집] 설정 값
- 허락되지 않은 권한으로 리소스 접근 시 이동하는 페이지 지정(errorPage)
- 인증이 되지 않은 상태에서 리소스 접근 시 이동하는 페이지 지정(loginFormUrl)
[편집] example
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"> <property name="authenticationEntryPoint"> <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl" value="/anonymouslogin.jsp" /> </bean></property> <property name="accessDeniedHandler"> <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl"> <property name="errorPage" value="/accessDenied.jsp" /></bean></property></bean>
[편집] FilterSecurityInterceptor
[편집] 역할
- 보안 대상 자원을 설정하는 부분
- 실제 특정 URL과 role을 맵핑하는 정보인 objectDefinitionSource 속성을 설정
[편집] 설정 값
- URL 별로 접근 가능한 role을 명시함.
[편집] example
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> <property name="authenticationManager"> <ref bean="authenticationManager"/> </property> <property name="accessDecisionManager"> <ref local="httpRequestAccessDecisionManager"/></property> <property name="objectDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /index.jsp=ROLE_ANONYMOUS,ROLE_USER /hello.htm=ROLE_ANONYMOUS,ROLE_USER /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER /switchuser.jsp=ROLE_SUPERVISOR /j_acegi_switch_user=ROLE_SUPERVISOR /login.jsp*=ROLE_ANONYMOUS,ROLE_USER /**=ROLE_USER </value> </property> </bean>
[편집] Spring security db로 권한지정하기
[편집] Configurations
[편집] Configurations-JDBC
- 사용자 로그인 정보와 권한 관련한 테이블을 생성한다.
- 테이블 생성Query
CREATE TABLE users ( username VARCHAR(50) NOT NULL PRIMARY KEY, password VARCHAR(50) NOT NULL, enabled BIT NOT NULL ); CREATE TABLE authorities ( username VARCHAR(50) NOT NULL, authority VARCHAR(50) NOT NULL );
- 샘플 Query
INSERT INTO users VALUES ('marissa', 'koala', true); INSERT INTO users VALUES ('dianne', 'emu', true); INSERT INTO users VALUES ('scott', 'wombat', true); INSERT INTO users VALUES ('peter', 'opal', false); INSERT INTO authorities VALUES ('marissa', 'ROLE_TELLER'); INSERT INTO authorities VALUES ('marissa', 'ROLE_SUPERVISOR'); INSERT INTO authorities VALUES ('dianne', 'ROLE_TELLER'); INSERT INTO authorities VALUES ('scott', 'ROLE_TELLER'); INSERT INTO authorities VALUES ('peter', 'ROLE_TELLER');
[편집] Configurations-web.xml
- web.xml에 Acegi Filter Chain Proxy filter를 선언한다.
- struts2의 action에도 Acegi를 적용해야 하기 때문에 filter mapping 순서는 Acegi filter가 struts2 filter보다 먼저 오도록 한다.
… <filter> <filter-name>struts-cleanup</filter-name> <filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class> </filter> <filter> <filter-name> Acegi Filter Chain Proxy</filter-name> <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class> <init-param> <param-name>targetClass</param-name> <param-value>org.acegisecurity.util.FilterChainProxy</param-value> </init-param> </filter> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts-cleanup</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name> Acegi Filter Chain Proxy</filter-name> <url-pattern>/*</url-pattern></filter-mapping> <filter-mapping> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> …
[편집] Configurations-view
[편집] login veiw
<form action="<c:url value='j_acegi_security_check'/>" method="POST">
<table>
<tr><td>User:</td>
<td><input type='text' name='j_username'
<c:if test="${not empty param.login_error}">
value='<c:out value="${ACEGI_SECURITY_LAST_USERNAME}"/>
</c:if>>
</td>
</tr>
<tr><td>Password:</td>
<td><input type='password' name='j_password'></td></tr>
<tr><td colspan='2'><input name="submit" type="submit"></td></tr>
<tr><td colspan='2'><input name="reset" type="reset"></td></tr>
</table>
</form>
[편집] logout veiw
<p><a href="<s:url value="../j_acegi_logout"/>">Logoff</a>
[편집] Configurations-tags
[편집] acegi tags
- 선언
<%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %>
- 사용
<authz:authentication operation="username"/> <authz:authentication operation=“password"/>
[편집] acegi 변수값 가져오기
- 선언
<%@ page import="org.acegisecurity.context.SecurityContextHolder" %> <%@ page import="org.acegisecurity.Authentication" %> <%@ page import="org.acegisecurity.GrantedAuthority" %> <%@ page import="org.acegisecurity.adapters.AuthByAdapter" %>
- 사용
Authentication object is of type: <%= auth.getClass().getName() %> // Authentication 객체 이름 가져오기 Authentication object as a String: <%= auth.toString() %><BR><BR> //authentication 정보 가져오기=> session ID, password, RemoteIpAddress, Granted Authorities
[편집] spring security 2.0 소개
- spring security 2.0에는 다음 기능이 추가되었다.
2.0에 추가된 기능들 요약 - OpenID 지원 - NTLM - JSR 250 애노테이션 - AspectJ 포인트컷 표현식 - 도메인 ACL 기능강화 - RESTful URI 권한 - 그룹 - 계층적인 권한 - user 관리 API - 데이터베이스 기반 "remember me" - portlet 인증(로그인) - 언어 추가 - Web Flow 2.0 지원 - Spring IDE 시각화와 자동완성 - 스프링 웹 서비스 1.5를 사용하여 WSS 기능 지원
[편집] (2.0 버전 추가사항)namespace Configuration
가장 흔하게 사용되는 형태를 잡아서 네임스페이스를 설계했다. 다음과 같이 나눠져 있다.
- Web/Http Security - 인증, URL 보안, 로그인 페이지 보여주기, 에러 페이지 보여주기 등...
- Business Object (Method) Security - 서비스 계층
- AuthenticationManager - 프레임워크 내 다른 부분들에서 필요한 인증 요청을 다룬다.
- AccessDecisionManager - 해당 리소스에 접근 권한이 있는지 결정하는 곳.
- AuthenticationProviders - 인증 담당자가 사용할 인증 방법들. remeberme, OpenID, 로그인 페이지 등...
- UserDetailService - 인증 담당자가 사용자 정보를 가져올 때 사용하는 빈.
[편집] DelegatingFilterProxy로 web.xml 설정하기
- spring security 2.0의 namespace configuration을 적용하기 위해서는 모든 필터들을 위임하는 DelegatingFilterProxy를 선언해주어야 한다.
<filter> <filter-name>struts-cleanup</filter-name> <filter-class> org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class> </filter> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts-cleanup</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
[편집] <http> 설정
- <http>설정을 사용하면 xml을 최소화로 줄일 수 있다. 또한 기본 설정 지원이 가능하여 아래와 같이 설정해주어도 사용할 수 있다.
<http auto-config="true"> <form-login /> <anonymous /> <http-basic /> <logout /> <remember-me /> </http>
- 사용자가 직접 이동 페이지나 옵션을 지정할 수 도 있다.
<http auto-config="true" access-denied-page="/403.jsp"> <concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true" /> <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp" default-target-url="/index.jsp" /> <logout logout-success-url="/login.jsp"/> </http>
- intercept-url을 통해 웹 주소 url에 권한을 걸 수 있다.
<http auto-config="true" access-denied-page="/403.jsp"> <intercept-url pattern="/index.jsp" access="ROLE_ADMINISTRATOR,ROLE_USER"/> <intercept-url pattern="/securePage.jsp" access="ROLE_ADMINISTRATOR"/> <intercept-url pattern="/**" access="ROLE_ANONYMOUS" /> </http>
[편집] annotation을 이용한 method 권한
- 아래 엘리먼트를 등록해서 애노테이션 기반 보안이 가능하도록 설정한다.
<global-method-security secured-annotations="enabled"> <!-- AspectJ pointcut expression that locates our "post" method and applies security that way--> <!-- <protect-pointcut expression="execution(sample.user.action.UserAction*(..))" access="ROLE_SUPERVISOR"/> --> </global-method-security>
- 혹은 다음과 같은 방법으로 bean으로 설정한다.
<bean id="securedObject" class="com.habuma.expectations.springsecurity.intercept.SecuredObject"> <sec:intercept-methods> <sec:protect access="ROLE_SECRET_AGENT" method="getSecuredData"/> </sec:intercept-methods> </bean>
- 권한을 설정할 메소드에는 다음과 같이 annotation을 등록한다.
@Secured( {"ROLE_SUPERVISOR"}) public void createUser(User user) { userDao.createUser(user); //jdbcUserDetailsManager.createUser(user); }
[편집] References
- Acegi Homepage: http://acegisecurity.org
- acegi에 관한 Architectural overview and filter:
- http://blog.empas.com/ahnyounghoe/read.html
- Acegi 보안 스타일(번역본):
- Spring Acegi Tutorial:
- Acegi Security 분석(박재성) :
- http://www.tfo-eservices.eu/wb_tutorials/media/SpringAcegiTutorial/HTML/SpringAcegiTutorial-1_1-html.html
- http://whiteship.tistory.com/category/Spring%20Security
