JCF3.0™ Spring security 가이드

From JCFWiKi

(Spring security에서 넘어옴.)
Jump to: navigation, search

그림:check.gif

  • 산출물 :Spring security 가이드
  • 작성자: 고경철
  • 최초작성일 : 2007/12/03
  • 최종작성일 : 2008/05/21

Copyright © 2008 Daewoo Information Systems Co., Ltd.

그림:information.gif

  • spring security 2.0 업데이트 내용 추가(2008년 5월)

목차

[편집] Preview: Authentication & Authorization

인증과 권한 절차(출처:http://whiteship.tistory.com/1060)
인증과 권한 절차(출처: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

acegi filter의 흐름
acegi filter의 흐름
acegi filter chain의 역할
acegi filter chain의 역할

[편집] 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 흐름

Authentication 흐름
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에서 사용하는 객체들을 저장해둔 곳이다.

[편집] 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