Whiteship's Note


[Spring Security] http 네임스페이스 쓰려면 필터 이름은 항상 고정(?)

Spring Security/etc : 2010.06.29 17:02


http://static.springsource.org/spring-security/site/docs/3.0.x/reference/appendix-namespace.html#nsa-http-attributes

<filter>
<filter-name>securityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

   <filter-mapping>
       <filter-name>securityFilterChain</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
    

자 이렇게 필터를 설정하고 

<http>
        <intercept-url pattern="/base/color/mgt" access="ROLE_USER" />
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<form-login login-page="/login" />
<logout logout-success-url="/index" />
<remember-me />
</http>

    <beans:bean id="smdisUserDetailsService" class="smdis.common.security.SmdisUserDetailsService"/>

<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="smdisUserDetailsService"/>
</authentication-manager>

<global-method-security secured-annotations="enabled"
jsr250-annotations="enabled" pre-post-annotations="enabled" />

이렇게 시큐리티 설정을 했다.

잘 돌아갈까?? 안 돌아간다.. 시큐리티 네임스페이스를 사용해서 <http>를 등록하면 FileChainProxy 빈 이름은 항상 springSecurityFilterChain이 된다. 그래서 필터 이름을 springSecurityFilterChain으로 설정해줘야 한다.

뭐.. DelegatingFilterProxy 필터 자체에 targetBeanName 속성을 사용해서 연결할 빈 이름을 설정할 수도 있지만 기본적으로 이 이름은 필터 이름을 따르게 된다. 필터 이름을 바꾸고 targetBeanName을 또 설정해 주느니 그냥 필터 이름을 springSecurityFileterChain으로 하는게 좋겠다.

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
top

Write a comment.


[Spring Security] sec:authentication

Spring Security/etc : 2010.05.11 07:36


참조: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/taglibs.html

스터디의 각 모임에는 댓글을 달 수 있습니다. 삭제 기능이 필요해져서 댓글 삭제 기능을 만들었는데 이것을 일반적인 User-Role 기반 Voter를 사용해서 권한 처리하는것이 그렇게 단순하지는 않습니다. 

관리자 권한이 있는 사람만 삭제할 수 있게 할까요? 아님 회원 권한을 가진 사람은 누구나 삭제하게 할까요? 비즈니스 룰이야 정하기 나름이지만 그렇게 무식하게 정하고 싶지는 않았습니다. 작성자만 자신이 작성한 댓글을 삭제하는 것이 가장 정당해 보입니다.

먼저 문제가 되는 부분은 뷰. 삭제 버튼을 감춰야 합니다.

<sec:authentication property="principal.username" var="currentUserName"/>
<c:if test="${currentUserName == comment.writer.email}">
//감출 버튼
</c:if>

이렇게 authenrication 태그를 사용해서 principal 객체와 그 속성값에 접근할 수 있습니다. 현재 로그인 되어있는 사용자의 username을 가져와서 현재 댓글 작성자의 email과 비교합니다. 봄싹에서는 email을 아이디로 사용하고 있기 때문에 이렇게 비교합니다. 그 둘이 일치하는 경우에만 버튼을 보여줍니다. 

참 쉽죠;

하지만... 버튼을 감춘다고 다가 아니죠. URL 보내면 보내집니다. 웹 보안으로는 위에서 언급했듯이 힘듭니다. 이럴 때는 서비스 쪽에서 객체 정보와 pricipal 정보를 기반으로 권한 처리를 해주면 되겠습니다. 그건 다음에.


top

Write a comment.


[스프링 시큐리티 3.0] @PreAuthorize

Spring Security/etc : 2009.08.23 14:38


    <global-method-security secured-annotations="enabled"
        jsr250-annotations="enabled" pre-post-annotations="enabled" />

시큐리티 설정 파일에 위와 같이 설정하면 @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter를 사용할 수 있습니다.

이들 애노테이션에서는 스프링 EL을 사용해서 현재 사용자 정보에 접근하거나, (pre 인 경우)메서드의 인자값 또는 (post 인 경우)메서드의 반환값의 정보에 접근할 수 있습니다.

    @PreAuthorize("(#study.manager.email == principal.Username) or hasRole('ROLE_ADMIN')")
    public void updateStudy(Study study) {
        repository.update(study);
    }

위 예제는 다음 주에 오픈 할 봄싹 프로젝트에서 사용하고 있는 코드입니다. Study를 수정하려는 사람이 관리자이거나, 스터디를 만든 사람인지 확인한 뒤에 메서드를 실행합니다. 만약 해당 EL이 false로 판단되면 Access Dinied 에러를 던져줍니다.

애노테이션을 메서드에만 붙이지 않고 클래스에도 붙여서 클래스에 정의한 모든 메서드에 적용할 수도 있습니다. 이런식으로요.

@Service
@Transactional
@PreAuthorize("hasRole('ROLE_USER')")
public class StudyService {

...

}





top

Write a comment.


스프링 시큐리티 3.0.0 M1 배포



참조 편역 요역: http://blog.springsource.com/2009/06/03/spring-security-300m1-released/

http://www.springsource.com/download 에서 직접 다운로드 할 수도 있고, 메이븐을 사용한다면, http://maven.springframework.org/milestone 메이븐 저장소를 추가하면 M1 의존성을 추가할 수 있다. JDK 1.5 이상, 스프링 3.0이 필요함.

표현식-기반 접근 제어

스프링 EL 기반 권한 관리를 지원한다. 메서드 애노테이션이나 웹 시큐리티에서 표현식을 사용할 수 있다. 속성이나 보터(voter)-기반 매커니즘에 비해 새로운 조합을 꾀할 수 있다. 다음은 웹 시큐리티에서 시큐리티 네임스페이스를 사용하는 간단한 예제다.

<http>
   <intercept-url pattern="/secure/**" access="hasRole('ROLE_SUPERVISOR') and hasIpAddress('192.168.1.0/24')" />
   ...
</http>

hasRole('ROLE_SUPERVISOR')은 사용자의 권한 목록을 확인하고 사용자가 해당 롤을 가지고 있다면, true를 반환한다. 여기에 IP를 확인할 수 있는 새로운 표현식을 추가했다.

@Pre와 @Post 애노테이션

메서드 시큐리티는 웹 요청을 수락하거나 거부하는 것과는 달리 조금 더 복잡하다. 메서드 시큐리티에 표현식을 사용해서 좀 더 다양한 기능을 제공하기 위해, 4개의 새로운 애노테이션을 추가했다. 이 애노테이션들을 사용하여 메서드 호출 전과 후에 특정 로직을 실행할 수 있다. 이 기능을 사용하려면 global-method-security 네임스페이스 엘리먼트에 새로운 속성을 사용해야한다.

<global-method-security pre-post-annotations="enabled"/>

가장 유용한 것으로 @PreAuthorize가 있는데, 이 애노테이션은 메서드를 실제로 실행할지 말지 여부를 제어한다. 예를 들어(예제 애플리케이션의 Contacts에서) 다음 메서드를 보자.

@PreAuthorize("hasRole('ROLE_USER')")
public void create(Contact contact);

이것은 ROLE_USER라는 롤을 가진 사용자만 접근을 허용한다는 뜻이다. 별 다른게 없다.

@PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);

이번에는 메서드 인자를 표현식에서 참조하고 있다. 해당 contact에 대해 현재 사용자가 admin 권한이 있는지 확인한다. hasPermission() 표현식은 애플리케이션 컨텍스트를 통해서 스프링 시큐리티 ACL 모듈과 연결되어 있다.(어떻게 연결되어 있는지는 Contacts 예제를 통해 살펴보기 바란다.) 메서드 인자를 표현식 변수로 참조할 수 있다. 스프링 EL의 모든 기능을 사용할 수 있기 때문에 인자의 속성에도 접근할 수 있다. 따라서 특정 사용자의 이름이 contact의 이름과 대응할 경우로 제한하고 싶을 때 다음과 같은 표현식을 사용할 수도 있다.

@PreAuthorize("#contact.name == principal.name)")
public void doSomething(Contact contact);

여기서는 내장된 표현식 principal을 사용했다. 이 것은 현재 스프링 시큐리티의 Authentication 객체를 기반한 것으로 시큐리티 컨텍스트에서 가져온 것이다. Authenticatino 객체에 직접 접근하려면 authentication 표현식이름을 사용할 수도 있다. 메서드 호출 후에 권한 작업을 수행할 수 있는데, 이 때는 @PostAuthotize 애노테이션을 사용하고, 반환값은 "returnObject"로 참조할 수 있다.

필터링

스프링 시큐리티는 컬렉션과 배열 필터링을 이미 제공하고 있었는데, 이제는 표현식을 사용할 수도 있다.

@PreAuthorize("hasRole('ROLE_USER')")
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
public List getAll();

여기서 filterObject는 반환하는 컬렉션에 들어있는 각각의 요소들을 지칭하고, 해당 요소에 대한 사용자의 권한이 read 이거나 admin이 아닌 것은 컬렉션에서 빼낸다. @PreFilter를 사용해서 메서드 호출 전에 필터링을 할 수도 있지만, 거의 사용하지 않는듯 하다. 문법은 같은데, 인자에 두 개 이상의 컬렉션이 있을 때 filterTarget 속성을 사용하여 어떤것을 사용하는지 지칭한다.

코드기반 재구성

3.0에서 대부분의 코드는 spring-security-core.jar로 들어갔다. 몇 년에 걸쳐 여러 기능이 추가되다보니 의존성간에 CR(circular reference)도 생기고 복잡한 의존성 구조가 되어버렸다. 또한 여러 jar에 나눠져서 들어간 패키지가 OSGi에서 말썽을 일으킨다는 이슈도 있었다. 이로인해 유지보수 오버헤드가 발생했고, 그 걸과 3.0에서 코드기반을 재구성하기로 결정했다.

프로젝트 JAR 파일

- 이 부분은 별도로 포스팅. 여기서는 생략.

이로인해 코드를 순회하며 참조하거나 이해하기 쉬워졌다.

스프링 시큐리티 3.0 JAR 의존성

패키지 구조

더이상 CR도 없고 훨씬 깔끔해졌다.


기타 변경사항

클래스 이름 변경: 이름들이 훨씬 명시적으로 바꼈군요.
AbstractProcessingFilter -> AbstractAuthenticationProcessingFilter
AuthenticationProcessingFilter -> UsernamePasswordAuthenticationProcessingFilter
AuthenticationEntryPoint -> LoginUrlAuthenticationEntryPoint
ObjectDefinitionSource -> SecurityMetadataSource
HttpSessionContextIntegrationFilter -> SecurityContextPersistenceFilter

인증 성공 또는 실패시 리다이렉션/포워딩: 인증 성공 또는 실패시에 브라우저가 이동할 목적지를 제어하는 방법 제공.
AuthenticationSuccessHandler
AuthenticationFailureHandler
http://jira.springsource.org/browse/SEC-745

레퍼런스 매뉴얼과 웹 사이트 업데이트: 아직 작업 중이지만 몇 개 챕터(네임스페이스, 기술 개요)는 업데이트 했다. 프로젝트 사이트의 FAQ도 업데이트 해서 몇몇 발표 비디오와 온라인 기사를 참조할 수 있다.

결론

스프링 EL을 사용하여 기능이 좀 더 풍부해졌고, 코드기반을 깔끔하게 정리했다.
JIRA 변경로그
커뮤니티 포럼
JIRA 이슈
top

  1. Favicon of http://ryys1993.tistory.com BlogIcon 윤성철 2009.06.08 17:47 PERM. MOD/DEL REPLY

    으아 언제나 느끼는거지만 정말 대단하셔요~~

    도데체 저런 그림은 어떻게 그리시는건지~ ^^

    머리에 쏘옥 쏙 들어오네요 ^^.

    저런 그림은 뭘로 그리시는지요? ^^..

    그림판은 아닐텐데 ^^.. 혹시 이클립스 플러긴이 있는건가 흐헉..

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2009.06.08 18:17 신고 PERM MOD/DEL

    절대로 제가 그린게 아니구요.
    원문에 있던거 퍼온거에요.
    오해를 불러일으켜 죄송합니다~

    아마도 이클립스에서 무슨 플러긴으로 자동 생성한 그림이겠거니 추측해 봅니다.

  2. Favicon of http://ryys1993.tistory.com BlogIcon 윤성철 2009.06.09 12:44 PERM. MOD/DEL REPLY

    직접 그리시지 않으셨다 하여도.. 위 기사를 쉽게 접할수 있게 해주시는것에 대해

    매우 감사합니다.

    사실 영어 울렁증때문에 --;;; ㅋ....

    앞으로 영어 공부좀 해야할거같아요 ^^.

    오늘 날 무지 꿀꿀스럽지만

    즐거운 날 되세요~...

    Favicon of http://whiteship.me BlogIcon 기선 2009.06.09 14:03 PERM MOD/DEL

    넵 ㅎㅎㅎ
    시원하고 좋네요. 좋은 하루 되세요~

Write a comment.


스프링 시큐리티 맞춤확장(customization) - 파트 1. UserDetail 또는 GrantedAuthority 맞추기



참조 및 번역: http://blog.springsource.com/2009/01/02/spring-security-customization-part-1-customizing-userdetails-or-extending-grantedauthority/

이번 글은 스프링 시큐리티 맞춤확장과 관련된 실용적인 예제 중심의 여러 작은 글들의 시리즈 중 첫 번째 글이다. 이번 맞춤확장 요구 사항은 상상에서 온 것이 아니라 전부 현장에서 요구한 것이다.

다음과 같은 요구사항이 있다고 가정해보자. 역할(role) 목록이 있고 각각의 역할은 비즈니스 기능(business function) 목록을 가지고 있다.(아래를 참조하라.)

ROLE_ADMIN
  BF_QUOTE_CREATE
  BF_POLICY_CREATE
  BF_POLICY_DELETE

ROLE_AGENT
  BF_QUOTE_CREATE
  BF_POLICY_CREATE

ROLE_USER
  BF_QUOTE_CREATE

필요한 기술은 권한 결정을 ROLE과 BF 모두를 가지고 결정할 수 있어야 한다는 것이다.

예를 들어:

ROLE_ADMIN이라는 역할을 가진 사용자는 해당 역할로 보호하고 있는 모든 리소스에 접근할 수 있어야 한다.

<sec:authorize ifAllGranted="ROLE_ADMIN">
    <p><a href="http://www.google.com">Google</a>
</sec:authorize>

또는

@Secured("ROLE_ADMIN")
public void foo()
    . . .
}

또한 해당 사용자는 해당 역할이 가지고 있는 비즈니스 기능으로 제한하고 있는 모든 리소스에도 접근할 수 있어야 한다.

<sec:authorize ifAllGranted="BF_POLICY_DELETE">
    <p><a href="http://www.google.com">Google</a>
</sec:authorize>

또는

@Secured("BF_POLICY_DELETE")
public void foo()
    . . .
}

이 요구사항을 다루는 방법은 몇 가지가 있다. 그 중 하나는 RoleHierarchy를 만들고 RoleHierarchyVoter를 사용하여 역할의 계층 구조를 순회하는 것이다. 이 접근 방법의 단점은 현재 스프링 시큐리티 2.0.4 구현체의 태그 라이브러리(security: authority ...)가 AccessDecisionManager를 통해서 의사 결정을 하고 있지 않으며 게다가 어떤 Voter도 제한하고 있는 HTML 엘리먼트에 대한 결정을 할 때 Role을 신경쓰지 않는다. 하지만 스프링 시큐리티의 놀라운 유연함과 맞춤확장 힘으로 인해 이 요구사항을 매우 간단하게 해결할 수 있다.
스프링 시큐리티의 가장 큰 잇점 중 하나는 어떻게 Principal(UserDetail 객체)을 생성하는지 맞춤확장 할 수 있다는 것이다. UserDetail 객체를 만들 때 GrantedAutorities 목록을 생성한다. 이 목록은 나중에 리소스를 제한하고 있는 GrantedAutority와 비교해볼 때 사용된다.
맞춤확장을 하는 또 한 가지 방법은 UserDetail 객체를 생성할 때 GrantedAuthorities 목록을 수정하는 것이다.

아래에서 제공하고 있는 예제에는 두 개의 프로퍼티 파일이 있다.(간단하게 하려고 프로퍼티 파일을 사용했지만, 여러분은 쉽게 그것을 DB나 LDAP으로 바꿀 수 있을 것이다.)

파일 하나는 users.properties로 사용자를 role에 맵핑한다.

oleg=powder,ROLE_ADMIN

다른 파일 하나는 role-to-db.properties로 각각의 role에 비즈니스 기능 목록을 맵핑한다.

ROLE_ADMIN=BF_QUOTE_CREATE,BF_POLICY_CREATE,BF_POLICY_DELETE

이제 필요한 작업은 UserDetailsService 구현체를 정의하여 위 두 개의 프로퍼티 파일을 사용하여 GrantedAUthorities 목록을 만들고 그것을 UserDetails 객체에 주입하는 것이다. 이 작업은 GrantedAuthorityImpl같은 GrantedAuthority 인터페이스 구현체를 재사용할 수 있으며 매우 간단하다. 하지만, 우리는 이때 (디버깅 또는 다른 의도로) 비즈니스 기능을 표현하는 GrantedAuthority의 상위(parent) GrantedAuthority를 추적할 수 있도록 하고 싶다.
이 두 가지 목적을 달성하기위해 GrantedAuthorityImpl을 확장하는 BusinessFunctionGrantedAuthority 클래스를 정의하고 모든 상위 GrantedAuthority 객체에 대한 목록을 담고 있게 했다.

public class BusinessFunctionGrantedAuthority extends GrantedAuthorityImpl {
    private List<GrantedAuthority> parentAuthorities;
        . . .
}

그런 다음 UserDetailsService 구현체를 만들었고 loadUserByNames(..) 메소드를 구현하여 다음 작업을 수행하도록 했다.

1. users.properties 파일 내용을 기반하여 UserAttribute 객체를 만든다. UserAttribute는 role을 나타내는 GrantedAuthority 목록을 담고 있다.
2. role-GrantedAuthorities 목록을 순회하면서 각각의 role-GrantedAuthorities 마다 BusinessFunctionGrantedAuthority를 만들고 그것을 미리 만들어둔 GrantedAuthority 목록에 추가한다.
  2-1. 각각의 BusinessFunctionGrantedAuthority에 parent GrantedAuthority를 추가한다.
3. 전체 GrantedAuthority 목록을 가지고 있는 최종 UserDetail 객체를 만든다.

그런 다음 AuthenticationProvider를 스프링 시큐리티 설정 파일에 정의한다.

사용자 삽입 이미지

노트: AuthenticationProvider에 커스텀 UserDetailService 구현체 ComplexAuthorityUserDetailsService 클래스(더 자세한 내용은 샘플 코드를 살펴보라.)를 주입했다.

리소스를 보안하고 배포한 다음 http://localhost:8080/spring-security-sample-grantedAuthority/index.jsp에 접속하라.

로그인한 뒤 여러분은 GrantedAuthorities 목록을 볼 수 있을 것이다.

사용자 삽입 이미지

여기서 여러분은 비즈니스 기능을 나타내는 GrantedAuthority가 해당 비즈니스 기능을 가지는 상위 GrantedAuthorities 목록도 보여주고 있다는 것을 확인할 수 있을 것이다.
index.jsp를 살펴보고 어떻게 security:authorize 태그를 사용ㅇ하여 role과 비즈니스 기능 목록을 사용하여 HTML 엘리먼트를 제한하는지 살펴보라
이게 끝이다. 여러분은 최소한의 맞춤확장으로 쉽게 Principal 구조를 확장하고 커스터마이징 할 수 있는지 살펴보았다. 그리고 이것을 비즈니스 코드를 더럽히지 않고 커스텀 GrantedAuthorities에 기반하여 선언적으로 보안을 적용하는지 살펴보았다.

샘플 코드는 여기서 다운로드 할 수 있다. spring-security-sample-grantedauthority
top

Write a comment.


Using Spring Security 2

Spring Security/etc : 2008.09.27 10:32


참조: http://www.parleys.com/display/PARLEYS/Home#slide=1;title=Using%20Spring%20Security%202;talk=19267601

귿. 발표자 말투도 느린편이고, 억양도 알아들을만 합니다. 어제 들은 아리드안 코일러의 AOP 발표에 비하면 훨씬 알아 듣기 쉬운것 같네요.

데모 코드는 스크린캐스팅에 잡히지 않아서 참조할 수 없었지만, 대충 말해주면서 코딩하기 때문에 어떻게 코딩하는지 눈치챌 수 있습니다. 물론 Spring Security 2에 새로 도입한 스키마들을 알고 계셔야게죠.

몇 가지 정리해둡니다.

1. URL 권한 확인으로는 충분하지 않다.
- 리소스랑 URL이랑 1:1로 맵핑되는게 아닌 경우.
/listCustomers.html 과 /print.view?page=listCustomers 이 두 개의 URL이 같은 리소스를 나타낼 경우 권한처리를 어떻게 할 것인가
- URL이 없을 수도 있다.
Web Application이 아닌 경우 권한 처리는?
- 여러 Ajax 요청을 처리하는 하나의 URL
헤더 정보만 조금씩 다른데, 그 정보에 따라 권한 처리해야 할테네 어떻게 할텐가?

=> Method Authonrization!!

2. 메소드 권한처리
- AspectJ 포인트컷 표현식 사용 가능
- @Secured 애노테이션 사용 가능
- JSR 250의 @RoleAllowed 사용 가능

3. 베스트 프랙티스
- URL 체크로 개괄적인(corse grained) 권한 처리를 한다.
- 메소드 체크로 세밀한(fine grained) 권한 처리를 한다.
- Role 사용하지 말고, Right를 사용하라. User <--> Role <--> Riht
@Secured("PERM_DELETE_USER)
public oid deleteUser(User user)

마지막 문구

Spring Security is more powerful than Acegi was
... and now it is also easy ;-)


top

  1. Favicon of http://ecogeo.tistory.com BlogIcon 서영아빠 2008.10.01 21:52 PERM. MOD/DEL REPLY

    귿. ㅎㅎ 실전에서 써보고 싶네요.

    Favicon of http://whiteship.tistory.com BlogIcon 기선 2008.10.01 22:27 PERM MOD/DEL

    넵. Role까진 써봤는데, Right는 안 써봤네요. 이번 KSUG 세미나에서는 과연 어떤걸 볼 수 있을지 기대됩니다.

Write a comment.


Whiteship's Spring Security 총 정리

Spring Security/etc : 2008.05.07 18:16


기본 개념

1.1. What is Acegi Security? : Acegi 정의와 개요.
2.2 Shared Components : 주요 구성 요소
2.3 Authentication (2) : 인증 절차를 도식화 했습니다.
Spring Acegi Tutorial : 가장 중요한 필터들에 대한 설명과 해당 필터들이 물고 있는 빈들을 보여줍니다.
3.2 Filters : 전체 필터들 간단 요약
4. Channel Security : https 사용에 대한 개요
Access Decision Manager : 접근 권한 관리를 하는 핵심 컴포넌트

웃긴 이야기

왜 이름이 Acegi 인가? : AbCdEfGhI, 스프링 서브 프로젝트가 되기 위한 노력.
Acegi 필터 등록할 때 발생할 수 있는 몹쓸 버그 : 필터 체인 사용하던 시절에 발생하던 웃긴 버그
Spring Security 설정 분류 및 커스터마이징 (5) : Acegi 관련 XML이 커져서 어떻게 나눌지 고민했던 시절

Spring Security(Acegi) 2.0 이전

Acegi로 웹 애플리케이션 보안하기 1
Acegi로 웹 애플리케이션 보안하기 2
Acegi로 웹 애플리케이션 보안하기 3
Acegi로 웹 애플리케이션 보안하기 4
Acegi로 웹 애플리케이션 보안하기 5 (2)
Acegi로 웹 애플리케이션 보안하기 6
Acegi로 웹 애플리케이션 보안하기 7

Spring Security 2.0 네임스페이스

Security Namespace Configuration PART 1 (1)
Security Namespace Configuration PART 2

많이 미흡하지만 이 정도면 Spring Security 학습에 어느 정도 도움이 되실 거라고 생각합니다.
Live with Passion!!! Live with Spring!!
top

  1. Favicon of http://theeye.pe.kr BlogIcon 아이 2008.05.10 12:30 PERM. MOD/DEL REPLY

    좋은 자료 정말 감사합니다. 큰 도움될꺼 같습니다.
    항상 감사합니다.

    Favicon of http://whiteship.tistory.com BlogIcon 기선 2008.05.10 23:21 PERM MOD/DEL

    에구 저야말로 아이님의 자바스크립트 강좌 잘 보고 있습니다. 프로토타입 하나도 몰랐는데 아이님 덕분에 도움 많이 받고 있습니다.

  2. Favicon of https://pyukcho.tistory.com BlogIcon 꿈꾸는바위 2011.04.29 15:09 신고 PERM. MOD/DEL REPLY

    좋은 자료 감사합니다.

Write a comment.


Security Namespace Configuration PART 2



2.3. Advanced Web Features

2.3.1. Adding HTTP/HTTPS Channel Security

애플리케이션에서 요청을 HTTP와 HTTPS로 아무거나 셋 중 하나의 채널로 받아들이도록 설정하려면 <intercept-irl> 의 requires-channel 속성을 사용한다.

  <http>
    <intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
    <intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
    ...
  </http>

/secure/** 패턴의 HTTP를 사용해서 접근하면 HTTPS URL로 리다이렉트 된다. 가용한 옵션은 "http", "https", "any"(둘 중 아무거나)가 있음.

위 프로토콜을 기본 포트가 아닌 다른 포트에서 사용할 때는 포트 맵핑을 해준다.

  <http>
    ...
    <port-mappings>
      <port-mapping http="9080" https="9443"/>
    </port-mappings>
  </http>

채널에 대해서는 여기서 자세히

2.3.2. Concurrent Session Control


단일 사용자 계정을 한 명(세션)만 사용하도록 제한할 수 있다.
먼저 web.xml에 다음 리스너를 등록한다.

<listener>
  <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
</listener>

그리고 application context에 다음을 추가한다.

  <http>
    ...
    <concurrent-session-control max-sessions="1" />
  </http>

이렇게 하면, 같은 계정으로 두 번 로그인 하면, 첫 번째 로그인한 유저가 invalid하게 된다. 두 번째 로그인하는 걸 막고 싶으면 다음과 같이 설정한다.

  <http>
    ...
    <concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/>
  </http>

mac-sessions 속성으로 한 계정당 가용한 세션 수를 정할 수 있나봅니다.

2.3.3. OpenID Login

  <http auto-config='true'>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <openid-login />
  </http>

저렇게 설정하면, OpenID 로그인을 사용하게 된다. 그리고 자신의 OpenID 계정을 설정해야 한다. 그리고 사용자 정보를 in-memory <user-service>에 추가한다.(이건 어떻게 하는거지..?)

<user name="http://jimi.hendrix.myopenid.com/" password="notused" authorities="ROLE_USER" />

2.3.4. Adding in Your Own Filters

이전 버전의 Acegi에서는 커스텀 필터를 필터 체인 중에 끼워넣을 수 있었다. 또는 이미 존재하는 필터를 커스터마이징해서 사용하고 싶을 수 있다. 2.0 이후 부터는 필터 체인이 명시적으로 보이지 않는데 어떻게 해야할까?

네임스페이스를 사용할 때 필터의 순서는 항상 고정되어 있다. 각각의 필터들은 스프링의 Ordered 인터페이스를 구현했고 그에 따라서 초기화 과정에서 정렬된다. 각각 필터들은 다음과 같은 이름으로 맵핑되어 있다.

Alias

Filter Class

CHANNEL_FILTER

ChannelProcessingFilter

CONCURRENT_SESSION_FILTER

ConcurrentSessionFilter

SESSION_CONTEXT_INTEGRATION_FILTER

HttpSessionContextIntegrationFilter

LOGOUT_FILTER

LogoutFilter

X509_FILTER

X509PreAuthenticatedProcessigFilter

PRE_AUTH_FILTER

Subclass of AstractPreAuthenticatedProcessingFilter

CAS_PROCESSING_FILTER

CasProcessingFilter

AUTHENTICATION_PROCESSING_FILTER

AuthenticationProcessingFilter

BASIC_PROCESSING_FILTER

BasicProcessingFilter

SERVLET_API_SUPPORT_FILTER

classname

REMEMBER_ME_FILTER

RememberMeProcessingFilter

ANONYMOUS_FILTER

AnonymousProcessingFilter

EXCEPTION_TRANSLATION_FILTER

ExceptionTranslationFilter

NTLM_FILTER

NtlmProcessingFilter

FILTER_SECURITY_INTERCEPTOR

FilterSecurityInterceptor

SWITCH_USER_FILTER

SwitchUserProcessingFilter



커스텀 필터는 <custom-filter> 엘리먼트를 사용해서 체인에 있는 필터를 교체 할 수 있다.

  <beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter">
    <custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
  </beans:bean>

필터 전 후에 끼워넣고 싶을 때는 after나 before 속성을 사용할 수 있으며 필터 이름 앞에 FIRST나 LAST를 붙일 수 있다.

2.3.5. Session Fixation 공격 방어

세션을 만들어서 사이트에 접속하려는 Session Fixation 공격이 있다. Spring Security는 사용자가 로그인 할 때 자동으로 새로운 세션을 만들어서 이 공격을 막는다. <http> 에 있는 session0-fixation-protection 속성에 다음과 같은 옵션을 사용하여 설정할 수 있다.
  • migrateSession - 새 세션을 만들고 기존의 세션 속성을 새 세션으로 복사한다. 이게 기본값이다.
  • none - 아무것도 하지 않음. 원래 세션을 유지한다.
  • newSession - 완전히 비어있는 clean 세션을 생성하고 기존 세션으로부터 아무것도 복사하지 않는다.
2.3.6. Setting a Custom AuthenticationEntryPoint

네임스페이스가 지원하는 인증 방식이 아닌 다른 방법을 사용하고 있어서 새로운 인증 필터와 Entry Point를 사용한다면 이 것들을 네임스페이스에 끼워넣고 싶을 것이다. AuthenticationEntryPoint 구현체를 <http>의 entry-point-ref 속성에 설정하면 된다.

2.4. Method Security

스프링 시큐리티 2.0 부터는 서비스 계층의 메소드에 JSR-250 시큐리티 애노테이션과 프레임워크의 @Secured 애노테이션을 사용할 수 있다. 빈 설정에 intercept-methods 엘리먼트를 추가하거나 AspectJ 스타일 포인트 컷으로 여러 개의 빈에 적용할 수 있다.

2.4.1. The <global-method-security> Element

이 엘리먼트를 등록해서 애노테이션 기반 보안이 가능하도록 설정한다.

<global-method-security secured-annotations="enabled" jsr250-annotations="true"/>


두 가지 타입의 애노테이션을 모두 지원하도록 설정했다.

2.4.1.1. Adding Security Pointcuts using protect-pointcut

<global-method-security>
    <protect-pointcut expression="execution(* com.mycompany.*Service.*(..))" access="ROLE_USER"/>
</global-method-security>

위 설정은 com.mycompany 패키지에 Service 라는 이름이 들어가는 빈들의 모든 메소드를 보안하도록 설정. ROLE_USER인 사용자만 해당 클래스의 메소드를 호출할 수 있다.

2.5. The Default AccessDecisionManager

여기는 기본적인 롤(ROLE) 기반의 접근 권한 관리 말고 좀 더 커스터마이징 하고자하는 분들을 위한 것임.

네임스페이스를 사용하면 기본 AccessDecisionManager 객체를 생성하고 등록해준다. 그리고 이 녀석을 사용해서 메소드 호출과 web URL 접근 가능 여부를 intercept-url와 protect-pointcut 설정을 바탕으로 결정한다.
기존 전략은 RoleVoter와 AuthenticatedVoter를 하나씩 가지고 있는 AffirmativeBased AccessDecisionManager를 사용한다.

2.5.1. Customizing the AccessDecisionManager

좀 더 복잡한 접근 제어 전략을 사용하려면 메소드와 웹 보안 둘에 대한 대체제를 설정하면 ㅕ된다.

메소드 보안을 용도로는 AccessDecisionmanager 빈을 가리키도록 gloval-security 엘리먼트의 acess-decision-manager-ref 속성을 사용한다.

  <global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
    ...
  </global-method-security>

웹 보안 접근 제어 대체제는 <http> 에 설정한다.

  <http access-decision-manager-ref="myAccessDecisionManagerBean">
    ...
  </http>

2.5.2. The Authentication Manager

스프링 시큐리티의 네임스페이스를 사용하면 인증 관리자 객체인 ProviderManager 타입의 객체도 생성해서 등록해준다. 이전 버전을 사용해봤다면 매우 친숙한 객체일 것이다.

추가적인 AuthenticationManager를 추가 등록하고 싶을 때 <custom-authentication0provider> 속성을 사용할 수 있다.

  <bean id="casAuthenticationProvider"
      class="org.springframework.security.providers.cas.CasAuthenticationProvider">
    <security:custom-authentication-provider />
    ...
  </bean>

그리고 이렇게 등록한 빈을 컨텍스트 안에 있는 다른 빈들이 AhtehnticationManager라고 참조하도록 별칭을 등록할 수 있다.

  <security:authentication-manager alias="authenticationManager"/>
  <bean id="casProcessingFilter" class="org.springframework.security.ui.cas.CasProcessingFilter">
     <security:custom-filter position="CAS_PROCESSING_FILTER"/>
     <property name="authenticationManager" ref="authenticationManager"/>
     ...
  </bean>




'Spring Security > Chapter 2' 카테고리의 다른 글

Security Namespace Configuration PART 2  (0) 2008.05.07
Security Namespace Configuration PART 1  (8) 2008.05.07
top

Write a comment.


Security Namespace Configuration PART 1



2.1. Introduction

- 스프링 네임스페이스
- 시큐리티 네임스페이스를 기본 네임스페이스로 사용하기

<beans:beans xmlns="http://www.springframework.org/schema/security"
   xmlns:beans="http://www.springframework.org/schema/beans">
    ...
</beans:beans>

2.1.1 Design of the Namespace

- 가장 흔하게 사용되는 형태를 잡아서 네임스페이스를 설계했다. (네임스페이스 만드는 방법은 KSUG 1회 세미나에서 토비형님께서 발표해주셨었음. 다시 듣고 싶음..) 다음과 같이 나눠져 있다.
  • Web/Http Security - 가장 복잡한 부분이다. 필터들을 등록하고 그와 연관된 서비스 빈들을 등록한다. 인증, URL 보안, 로그인 페이지 보여주기, 에러 페이지 보여주기 등 많은 일을 한다.
  • Business Object (Method) Security - 서비스 계층을 보안(보완이 아니라 보안!!)하기 위한 옵션
  • AuthenticationManager - 프레임워크 내 다른 부분들에서 필요한 인증 요청을 다룬다. 간단하게 인증 담당자.
  • AccessDecisionManager - 해당 리소스에 접근 권한이 있는지 결정하는 곳. 간단하게 권한 담당자. 자동으로 기본값이 세팅 되는데 물론 커스터마이징 수도 있다.
  • AuthenticationProviders - 인증 담당자가 사용할 인증 방법들. 여러 가지 방법이 있겠지만, 기억하기, OpenID, 로그인 페이지가 가장 흔할듯.
  • UserDetailService - 인증 담당자가 사용자 정보를 가져올 때 사용하는 빈.
2.2. Getting Started with Security Namespace Cofiguration

여러분들이 Spring Security를 애플리케이션에 빨리 적용 인증, 권한 기능을 사용하길 원하다는 가정하게 설명한다.

2.2.1. web.xml 설정하기

가장 먼저 할 일은 web.xml에 필터를 등록하는 것이다.

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

특정 URL을 후킹해서 스프링 ApplicationContext에 등록되어 있는 머시기 빈이 그 요청 처리 앞에 끼어들도록 하는 것임. 위 설정은 /* 이렇게 모든 요청을 가로채도록 해놨음.

2.2.2. 최소 <http> 설정


웹 보안을 위해 필요한 최소 설정은 아래와 같다.

  <http auto-config='true'>
    <intercept-url pattern="/**" access="ROLE_USER" />
  </http>

모든 요청을 ROLE_USER 만 접근할 수 있다. 로그인 페이지에는 접근할 수가 있을까??? 없을 것 같은데.. 된다. 왜냐면 auto-config 때문에 설정된 <http-basic> 때문에.. 자세한건 아래에 있음.

<http> 엘리먼트 안에 <intercept-url> 엘리먼트 여러개를 설정할 수 있는데, 이 때 맨위에서 아래 순으로 가장 먼저 걸리는 녀석이 적용된다. 순서에 주의하자.

사용자 추가하기

  <authentication-provider>
    <user-service>
      <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
      <user name="bob" password="bobspassword" authorities="ROLE_USER" />
    </user-service>
  </authentication-provider>

아이디와 비번 권한 정보를 이렇게 직접 줄 수도 있다. 이 정보들을 프로퍼티 파일로 빼낼 수 도 있다. 자세한건 여기 참조. 그다지 안전해 보이지 않는 방법이다. 하지만 간단하게 적용할 수 있다는 것이 장점이다. 매우 작은 웹 애플리케이션에 적용하기엔 저 정도면 충분할 듯 하다. 여기에 정의한 사용자 정보들은 Authentication Manager가 인증 요청을 다룰 때 사용한다.

위에 설정을 10줄 밖에 안 했지만, 암묵적으로 몇개의 빈들이 설정된다. 로그인 처리라던지 "remember-me" 서비스 같은 것들이 자동으로 설정되었다. 이는 <http>에 auto-config 설정이 기본으로 되어있기 때문이다.

이전 버전에서 필터들의 순서가 이슈가 됐었는데 이제는 그런 걱정할 필요가 없다. 필터 등록하고 필터가 필요한 빈등록하는 일을 전부 <http> 엘리먼트가 책임진다. <http>는 옛날의 FilterChainProxy, <authentication-provider>는 옛날의 DaoAuthenticationProvider, <user-service>는 옛날의 InMemoryDaoImpl 라고 생각할 수 있다. 네임스페이스 처리 시스템이 ProviderManager는 자동으로 만들어주고 DaoAuthenticationProvider 얘를 거기에 자동으로 엮어서 등록한다.

이 내용은 Acegi를 아시는 분들만 이해하실 수 있습니다. 몰라도 별 지장은 없습니다.

2.2.2.1. What does auto-config Include?

auto-config 속성은 다음 코드를 압축시킨거다.

  <http>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <form-login />
    <anonymous />
    <http-basic />
    <logout />
    <remember-me />
  </http>

2.2.2.2. Form and Basic Login Options

HTML 파일이나 JSP 파일을 만들지 않아도 Spring Security가 기본 로그인 화면을 만들어 준다. 물론 그걸 그냥 써도 되겠지만, 대부분 그러지는 않을 것이다. 다음과 같이 설정하여 별도의 로그인 폼을 지정할 수 있다.

  <http auto-config='true'>
    <intercept-url pattern="/login.jsp*" filters="none"/>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <form-login login-page='/login.jsp'/>
  </http>

auto-config를 사용하는 상태에서 <form-login>도 설정하고 있는데, 이렇게 하면 기본 세팅값을 오버라이딩한다. /login.jsp 요청은 시큐리티 필터 처리를 하지 않도록 설정했다. 그래야 로그인 페이지에 접근할 수가 있다.

  <http auto-config='true'>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <http-basic />
  </http>

<http-basic /> 이라는 기본 인증은 설정 위치에 상관없이 가장 우선시 된다. 따라서, 제한된 영역에 접근하려고 할 때 로그인창을 띄운다.

2.2.3. Using other Authentication Providers

사용자 인증 방법을 여러가지 사용할 수 있는데, 사용자 정보를 보통은 DB나 LDAP 서버에 저장해 둔다. LDAP 네임스페이스는 LDAP 챕터에 나와있으니 여기서 다루진 않는다. UserDetailSerivce에 대한 구현체가 있다면 다음과 같이 등록할 수 있다.

 <authentication-provider user-service-ref='myUserDetailsService'/>

DB에서 직접 사용자 정보를 끌어올 거라면 다음과 같이 설정할 수 있다.

  <authentication-provider>
    <jdbc-user-service data-source-ref="securityDataSource"/>
  </authentication-provider>

위 설정에서 securityDataSource는 그냥 DataSource 타입의 빈 이름이다. 이 때 해당 데이터소스와 연관을 맺는 데이터베이스에는 Spring Secutiry 표준 사용자 테이블 스키마를 따르고 있어야 하는데, 스키마가 그와 다를 경우에는 JdbcDaoImpl 빈을 만들고 그 빈을 user-service-ref에 설정해줄 수있다.

user-service-ref에는 UserDeteailsService 타입의 빈을 등록할 수 있는데, JdbcDaoImpl은 UserDetailsService를 구현한 클래스이기 때문에 등록할 수 있는것이다.

2.2.3.1. Adding a Password Encoder

<authentication-provider>
  <password-encoder hash="sha"/>
  <user-service>
    <user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f" authorities="ROLE_USER, ROLE_ADMIN" />
    <user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f" authorities="ROLE_USER" />
  </user-service>
</authentication-provider>

위와 같이 <password-encoder has=sha"/>를 사용하여 해싱 알고리즘을 사용해서 암호화 할 수 있다. 사전어 공격을 막기 위해서 salt 값들을 사용할 수 있다.

<password-encoder hash="sha">
  <salt-source user-property="username"/>
</password-encoder>

너무 길어져서 Advanced와 Method Security는 Part 2에서 요약 하겠습니다.

'Spring Security > Chapter 2' 카테고리의 다른 글

Security Namespace Configuration PART 2  (0) 2008.05.07
Security Namespace Configuration PART 1  (8) 2008.05.07
top

  1. 선영욱 2008.05.07 12:51 PERM. MOD/DEL REPLY

    우왕~굳~!!!
    너무 멋지세요 ^0^ 얼렁 내공으로 만들어야 겠습니다. 스읍 =3=)

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2008.05.07 15:59 신고 PERM MOD/DEL

    정말로 멋진건 오늘 저녁 6시 반쯤에 포스팅 됩니다. 캬캬

  2. 존재이유 2009.01.27 16:00 PERM. MOD/DEL REPLY

    기선님 질문이 있습니다!.
    스프링 시큐리티를 학습하고 있는데 <intercept-url /> 에서
    access의 값은 스프링에서 정해진값만 사용 가능한 값인가요?
    아니면 사용자가 임의값을 넣을 수 있는 것인가요?
    전자라면 사용가능한값 리스트라도 알려주시면 감사하겠습니다!!

    Favicon of http://whiteship.me BlogIcon 기선 2009.01.28 09:28 PERM MOD/DEL

    후자입니다. 시스템에서 사용하는 권한명을 적어주시면 됩니다.

  3. Favicon of https://slothink.tistory.com BlogIcon 편현장 2010.08.19 19:46 신고 PERM. MOD/DEL REPLY

    왜 권한값에는 "ROLE_" 이 앞에 붙어야할까요?
    제가 가진 userDetail 은 굉장히 많은 종류의 권한이 있는데,
    <security:authorize ifAnyGranted="G:ADMIN"> 이런게 안된다 말이죠.. 결국 제가 그런티에다가 모두 "ROLE_" 를 붙여서 억지로 <security:authorize ifAnyGranted="ROLE_G:ADMIN"> 를 만들고 있는 상황입니다만. 레퍼런스를 아무리 읽어도 모르겠군요. 내가 못 찾는건지.ㅠㅠ

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2010.08.19 20:14 신고 PERM MOD/DEL

    스프링 시큐리티를 어떻게 적용하셨는지 몰겠는데요. 봄싹 경우에는 UserDetails 확장 클래스에서 List<GrantedAuthority>를 설정해 줄 때 prefix를 설정해 주고 있습니다. 거기서 ROLE_ 이나 RIGHT_ 같은걸 붙여줘서 권한 목록에 넣고 있죠.

    그 부분을 잘 바꾸시면 될 듯 합니다.

  4. Favicon of https://slothink.tistory.com BlogIcon 편현장 2010.08.19 23:33 신고 PERM. MOD/DEL REPLY

    예,,, 그러니깐 기선님처럼 저도 하고 있는데요. 굳이 ROLE_ 이나 RIGHT_ 같은 값을 강제하는 걸 어떻게 푸냐는 것이죠. AccessDecisionManager 를 별도로 구현하는 방법밖에 없을까요?ㅎ

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2010.08.20 10:16 신고 PERM MOD/DEL

    AccessDecisionManager를 별도로 구현할 수도 있겠는데요.. 그보단 userDetails 확장 클래스에서 List<GrantedAuthority> 목록 만들 때 prefix를 안붙이면 간단히 해결되지 않을까요.

Write a comment.


Spring Security 2.0.1 Released

Spring Security/etc : 2008.05.03 09:54


참조 : http://www.springframework.org/node/648

빠르네요 빨라. 이번에는 버그 수정과 몇 가지 개선사항들이 있었습니다.
- Remember me 버그 수정
- JPA 붙인거에 전역 메소드 시큐리티 필터 버그 수정
- ...
top

  1. 선영욱 2008.05.06 08:54 PERM. MOD/DEL REPLY

    Spring Security 너무 어려워요 >.<

    Favicon of http://whiteship.tistory.com BlogIcon 기선 2008.05.06 14:05 PERM MOD/DEL

    Spring In Action 2판 7장을 읽어보세요. 전 거기서 많이 도움을 받았습니다.

Write a comment.


드디어 Spring Security 2.0 Released!!



http://www.springframework.org/node/627

아 이 녀석의 POM 때문에 어제 고생한 걸 생각하면...OTL 이번 배포판에서는 스프링 2.5.0 이상의 버전을 사용하도록 명시했군요. 대체 왜 [2.0, 2.5]라고 한건지.. 그냥 2.0 이라고 하면 알아서 2.0 이상의 버전을 쓸텐데 말이죠. petclinic 예제도 봐야겠습니다.

2.0에 추가된 기능들 요약
- OpenID 지원
- NTLM
- JSR 250 애노테이션
- AspectJ 포인트컷 표현식
- 도메인 ACL 기능강화
- RESTful URI 권한
- 그룹
- 계층적인 권한
- user 관리 API
- 데이터베이스 기반 "remember me"
- portlet 인증(로그인)
- 언어 추가
- Web Flow 2.0 지원
- Spring IDE 시각화와 자동완성
- 스프링 웹 서비스 1.5를 사용하여 WSS 기능 지원 강황

우왕.. 몇 개 빼고 다 해보고 싶네요.

참조 할 것
http://www.jroller.com/habuma/entry/method_level_security_in_spring <-- 메소드 레벨 Security 모든 방법 소개. SIA 저자. 굳.
top

  1. Favicon of https://jjaeko.tistory.com BlogIcon 째코 2008.04.16 00:59 신고 PERM. MOD/DEL REPLY

    스프링 시큐리티는 또 언제 공부하나... 어휴

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2008.04.16 08:11 신고 PERM MOD/DEL

    걍 천천히~ 느긋하게.. 즐기시면 됩니다. 전 어서 하이버를 마무리해야 할텐데 말이죠.ㅋㅋ

Write a comment.


Spring Security 2.0 Milestone 1 드디어 나옴.



스프링 포럼에서 젤 먼저 알려주는 군요.

다운로드 받기.
변경사항 보기.


위 XML 파일을 보시면 Spring Secutiry 2.0 이전의 설정 방법은 전부 주석처리를 해두었기 때문에, 비교하면서 볼 수 있습니다.

근데 왜 필요한 네임스페이스는 등록도 안 해둔거지..-_-;; 어떡하라고.. 벤 알렉스!

레퍼런스도 별로 바뀐게 없는 듯 합니다.
top

  1. Favicon of http://riosung.tistory.com BlogIcon 리오 2008.01.04 14:12 PERM. MOD/DEL REPLY

    그러게요. 희한하네요~ ㅋㅋ 그래도 무지 반갑네요 ^^

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2008.01.04 14:34 신고 PERM MOD/DEL

    네. XML 코드 줄어든 걸 보면 정말 기분이 좋아져요.ㅋㅋ

Write a comment.


Spring Security 2 조만간 볼 수 있을 듯



참조 : http://blog.interface21.com/main/2007/12/06/whats-new-in-spring-security-2/

다음 주 쯤에 배포가 될 것 같습니다. 벌써부터 기다려지네요. Ben Alext가 올린 글을 보면, 설정이 상당히 간결해 진것 같은데, 너무 간결해져서 다시 공부해야 할 것 같습니다. 수 많은 필터들을 직관적인 엘리먼트와 속성이름을 사용해서 감춰주길 기대하고 있습니다.

대강 보니, 사용법은 일단 web.xml에 Filter To Chain Proxy를 등록하던 저번과 비슷한데, 대신 등록하는  클레스가 Filter To Chain Proxyr가 아니라 org.springframework.web.filter.DelegatingFilterProxy 로 바뀐 것 같습니다. 그리고 수 많은 필터를 빈으로 등록해야 했던 부분이 다음과 같은 한 덩어리로 뭉쳐진 것 같습니다.

    <http autoConfig="true">
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_REMEMBER" />
    </http>

    <repository>
        <user-service hash="md5:hex">
            <user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR,ROLE_USER" />
        </user-service>
    </repository>

TSE 2007에서 Spring Security와 관련된 세션이 세 개나 된다고 하는데, 내년에도 올해처럼 재밌는 발표들이 가득한 TSE가 되면 좋겠습니다.
top

  1. Favicon of http://toby.epril.com BlogIcon 토비 2007.12.08 06:24 PERM. MOD/DEL REPLY

    Ben Alex는 참 느리기도 하지. 호주 사람이라서 그런지... 코알라 벤이라고 불러줘야겠다. 2.0 소개한지 1년만에 M1나오네, 정식 릴리즈는 한 일년은 더 기다려야 할 듯

    Favicon of http://whiteship.tistory.com BlogIcon 기선 2007.12.08 07:52 PERM MOD/DEL

    ㅋㅋㅋ그래도 좋은거 만들어 줬자나요.

Write a comment.


Acegi 사용시 사용자 정보 접근하기



Acegi를 사용하여 인증을 거치면, 사용자 아이디(principal)가 session에 ACEGI_SECURITY_LAST_USERNAME 라는 속성으로 저장됩니다.

따라서, 뷰에서는 EL을 사용하여 ${ACEGI_SECURITY_LAST_USERNAME} 이런식으로 접근할 수 있으며, 컨트롤러 계층에서는

String loginId = (String) request.getSession().getAttribute("ACEGI_SECURITY_LAST_USERNAME");
이런식으로 접근할 수 있습니다.

HttpServletRequest 변수에 직접 전근할 수 없는 계층에서도 현재 로그인 되어 있는 사용자 정보에 접근할 수 있습니다.

String username = SecurityContextHolder.getContext().getAuthentication().getName();
이런 식으로 SecurityContextHolder를 통해서 현재 로그인 되어 있는 사용자의 정보를 가져올 수 있습니다.


top

Write a comment.


Acegi Security in one hour



시기적절하게 좋은 글 하나가 올라왔네요.
Acegi Security in one hour

Spring 2, Acegi, Sitemesh를 사용한 예제를 코드 중심으로 설명한 아티클입니다. 자세하기 보진 않았지만, 빠르게 Acegi를 사용해 보고 싶으신 분들에게 매우 유용할 듯 싶습니다. 제목은 한 시간이지만, 영어권이 아니기 때문에 한 두 시간정도가 되지 않을까 싶네요.ㅎㅎ

top

Write a comment.


4. Channel Security



jsessionid를 오직 안전한 채널을 통해서만 전송할 수 있는 HTTPS를 사용하기 위해서는 필터들의 가장 상위에 있었던 ChannelProcessingFilter를 사용하면 됩니다.

web.xml에 FilterToBeanProxy 사용해서 등록한 뒤에 애플리케이션 컨텍스트에 다음과 같이 등록합니다.

<bean id="channelProcessingFilter" class="org.acegisecurity.securechannel.ChannelProcessingFilter">
<property name="channelDecisionManager"><ref bean="channelDecisionManager"/></property>
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
\A/secure/.*\Z=REQUIRES_SECURE_CHANNEL
\A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL
\A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL
\A.*\Z=REQUIRES_INSECURE_CHANNEL
</value>
</property>
</bean>

<bean id="channelDecisionManager" class="org.acegisecurity.securechannel.ChannelDecisionManagerImpl">
<property name="channelProcessors">
<list>
<ref bean="secureChannelProcessor"/>
<ref bean="insecureChannelProcessor"/>
</list>
</property>
</bean>

<bean id="secureChannelProcessor" class="org.acegisecurity.securechannel.SecureChannelProcessor"/>
<bean id="insecureChannelProcessor" class="org.acegisecurity.securechannel.InsecureChannelProcessor"/>

이런 이런... 이러니까 'XML 지옥'이라는 말이 나오면서 XML을 기피하게 되는 것 같습니다. 저 중에서 거~의 대부분의 상황에서 기본으로 .. 그냥 저렇게만 붙여 넣어서 사용하면 되는 부분을 빼면 색칠한 부분이 됩니다. Spring Security 2.0에서 태그 한방으로 모두 처리가 되리라 예상해 봅니다.

그림으로 그려보면 다음과 같은 관계에 있습니다.

사용자 삽입 이미지
헥헥헥;;;

'Spring Security > I. Overall Architecture' 카테고리의 다른 글

4. Channel Security  (0) 2007.08.21
3.2 Filters  (0) 2007.08.14
2.3 Authentication  (2) 2007.08.13
2.2 Shared Components  (0) 2007.08.13
1.1. What is Acegi Security?  (0) 2007.08.08
top

Write a comment.


3.2 Filters



위의 필터들을 등록하는 방법은 크게 두 가지로 web.xml에 FilterToBeanProxy 를 사용하여 등록하는 방법과 Application Context에 FiterChainProxy를 사용하는 방법이 있습니다.

web.xml에 모든 필터를 등록할 때는 다음의 순서를 꼭 지켜야 합니다.
  1. ChannelProcessingFilter, 다른 프로토콜로 redirect할 필요가 있을 수도 있기 때문에...
  2. ConcurrentSessionFilter, 주체에 의한 요청을 반영하여 SessionRegistry를 갱신해야 할 필요에 의해서..
  3. HttpSessionContextIntegrationFilter, 웹 요청이 시작될 때 SecurityContextHolder에 SecurityContext가 설정될 수 있고, 요청이 끝날 때SecurityContext에 변경이 생기면 HttpSession에 복사할 수 있도록...
  4. Authentication processing mechanisms - AuthenticationProcessingFilter, CasProcessingFilter, BasicProcessingFilter, HttpRequestIntegrationFilter, JbossIntegrationFilter etc - SecurityContextHolder가 유효한 Authentication 요청 토큰을 갖도록 수정할 수 있도록...
  5. The SecurityContextHolderAwareRequestFilter, if you are using it to install an Acegi Security aware HttpServletRequestWrapper into your servlet container
  6. RememberMeProcessingFilter, 이전 인증 절치 매커니즘에 의해 SecurityContextHolder가 변경되지 않았고, 쿠키등을 사용하여 'remember-me' 서비스를 사용할 수 있다면, 기억해 둔 Authentication 객체를 채워넣는다.
  7. AnonymousProcessingFilter, 이전 인증 절치 매커니즘에 의해 SecurityContextHolder가 변경되지 않았다면, 익명 Authentication 객체를 채워 넣는다.
  8. ExceptionTranslationFilter, Acegi Security 예외를 잡아서 HTTP 에러 응답을 반환하거나 적당한 AuthenticationEntryPoint가 실행되도록 한다.
  9. FilterSecurityInterceptor, 웹 URI를 보호하기 위해..
그럼 web.xml이 너무 복잡해지고 커지기 때문에...권장하고 있는 방법은 Application Context에 FilterChainProxy를 사용하여 모든 필터를 등록하는 방법입니다. 근데 FiterChainProxy를 사용하려면 어차피 web.xml에서 FilterToBeanProxy로 FilterChainProxy를 등록해야 하기 때문에..(어지러우시죠??ㅋㅋ)...네 그렇답니다.ㅋ

즉..web.xml에는 다음과 같이 FiterToBeanProxy를 등록하고(FilterChainProxy를 사용하도록 등록)
    <filter>
        <filter-name>Acegi Filter Chain Proxy</filter-name>
        <filter-class>
            org.acegisecurity.util.FilterToBeanProxy
        </filter-class>
        <init-param>
            <param-name>targetBean</param-name>
            <param-value>filterChainProxy</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>Acegi Filter Chain Proxy</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Application Context에 FilterChainProxy를 등록합니다.
    <!--  if you wish to use channel security, add "channelProcessingFilter," in front
        of "httpSessionContextIntegrationFilter" in the list below -->
    <bean id="filterChainProxy"
        class="org.acegisecurity.util.FilterChainProxy">
        <property name="filterInvocationDefinitionSource">
            <value>
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                PATTERN_TYPE_APACHE_ANT
                /**=httpSessionContextIntegrationFilter,formAuthenticationProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
            </value>
        </property>
    </bean>

여기서 참조하는 필터들은 모두 Application Context에 bean으로 등록되어 있고 그 bean의 이름으로 FilterChainProxy에서 참조하고 있습니다.


'Spring Security > I. Overall Architecture' 카테고리의 다른 글

4. Channel Security  (0) 2007.08.21
3.2 Filters  (0) 2007.08.14
2.3 Authentication  (2) 2007.08.13
2.2 Shared Components  (0) 2007.08.13
1.1. What is Acegi Security?  (0) 2007.08.08
top

Write a comment.


2.3 Authentication



간단한 인증과 권한 확인 절차를 그림으로 그려봤습니다.
사용자 삽입 이미지

'Spring Security > I. Overall Architecture' 카테고리의 다른 글

4. Channel Security  (0) 2007.08.21
3.2 Filters  (0) 2007.08.14
2.3 Authentication  (2) 2007.08.13
2.2 Shared Components  (0) 2007.08.13
1.1. What is Acegi Security?  (0) 2007.08.08
top

  1. Favicon of https://epro.tistory.com BlogIcon epro 2007.08.15 01:18 신고 PERM. MOD/DEL REPLY

    이 그림은 뭘로 그리셨어요?
    인증 절차보단 이쁜 그림에 더 관심이 많은 1인 ㅡ_ㅡ;;

    Favicon of http://whiteship.tistory.com BlogIcon 기선 2007.08.15 07:26 PERM MOD/DEL

    PPT요.ㅋㅋ;;
    아주 간단하게 네모를 여러개 그린것 뿐입니다.

Write a comment.


2.2 Shared Components



사용자 삽입 이미지

파란색은 클래스 하늘색은 인터페이스 입니다. 모든 선은 dependency를 나타내고 있으며 Authentication 과 UserDetails의 사이가 점선인 관계는 직접적인 종속성은 없지만 Authentication 클래스의 getPrincipal() 메소드를 통해서 반환되는 Object 타입의 객체를 UserDetails 로 변환하여 사용할 수 있기 때문입니다.


'Spring Security > I. Overall Architecture' 카테고리의 다른 글

4. Channel Security  (0) 2007.08.21
3.2 Filters  (0) 2007.08.14
2.3 Authentication  (2) 2007.08.13
2.2 Shared Components  (0) 2007.08.13
1.1. What is Acegi Security?  (0) 2007.08.08
top

Write a comment.


왜 이름이 Acegi 인가?



Acegi Security의 이름이 왜 Acegi인가에 대해 Acegi를 만든 Ben Alex가 2007년 1월에 작성했던 글이 있습니다.

정말 영어 알파벳 홀수 1, 3, 5, 7, 9를 따서 만든거라고 합니다. 다만 처음 부터 지금의 Acegi Sicurity용으로 만든 이름을 아니였고 다른 시스템을 일컷는 것 같은데 BBS라고 하는데 뭔지 모르겠군요.

Anyway, 2003년 11월에 만들어서 ZIP 파일로 들고가서 로드 존슨과 융겐 휄러에게 보여주며 Spring Security로 제안을 했지만... 둘 다 너무 바쁜 나머지 제대로 검토할 시간이 없어서 Spring Security라고 하지 못하고 XXX Security System for Spring으로 이름을 지어야 했는데.. 그 때 바로 위에서 사용했었던 Acegi를 사용한 것이라고 합니다.

지금은 당당히 Spring Security라는 새 이름을 가지게 되었고, 단순한 이름의 변경이외에도 다양한 의미가 내포된 것 같군요.

Acegi의 엄청난 설정 내용을 보면서 전부 새로운 태그를 만들어서 확 줄이고 싶다는 생각이 들었는데.. 아마도 만들고 있겠죠?? Spring 2.1에 추가된 <context:annotation-config/> 이런 태그 처럼 여러개의 bean을 등록해야 할 때 묶어서 한방에 등록해주고 자주 설정하는 부분은 속성으로 설정할 수 있도록 해주면 훨씬 간편해 질 거라는 생각만 해봤습니다. 태그 만드는 방법은 토비님의 예전 포스팅에도 있었고 KSUG 1회 때의 약간 어려웠던 발표도 있었으며, Ben Hale의 Creating a Spring 2.0 namespace? Use Spring's AbstractBeanDefintionParser hierarchy. 이런 글도 있지만.. 아직 해보진 못했습니다. 해봐야겠네요. 앗. 갑자기 삼천포;;


top

Write a comment.


Spring Acegi 예제 애플리케이션



어제 올렸던 Spring Acegi Tutorial 아티클에서 사용한 예제 애플리케이션입니다. Acegi의 핵심 기능인 인증과 권한을 테스트 해보기 위한 매우 간단한 예제 애플리케이션입니다.



Spring 1.2 rc1, Acegi 1.0.0 rc2 를 사용한 코드입니다.
JDK 5.0 이상, Tomcat 5.5 이상에서 동작합니다.

사용법은 간단합니다. 톰캣으로 돌리면 다음과 같은 화면을 볼 수 있습니다.
사용자 삽입 이미지
여기서 위쪽 링크는 일반 user만 들어갈 수 있고 아랫 쪽 링크는 admin만 들어갈 수 있습니다. dispatcher-servlet.xml의 userDetailsService 빈을 살펴 보시면 해당 메모리 DB로 id, 비번, role 을 설정 해 둔 것을 볼 수 있습니다.
사용자 삽입 이미지
위 쪽 링크를 클릭하시면 인증 화면이 뜹니다. 여기서 user, userpass 라고 입력하시면 일반 user로 로그인 할 수 있습니다.
사용자 삽입 이미지
로그인에 성공하면 다음과 같은 일반 폼 화면이 뜨고 여기서 아무 값이나 입력하면 결과를 확인할 수 있습니다. 그리고 로그아웃도 할 수 있죠. 만약 위의 로그인 화면에서 로그인이 실패하면 다음과 같은 페이지를 볼 수 있습니다.
사용자 삽입 이미지
이번에는 admin만 접근할 수 있는 첫 번쨰 화면의 두 번째 링크로 들어가겠습니다. admin의 id와 비번은 admin, adminpass입니다.
사용자 삽입 이미지
자 이제 거의 다 테스트를 해봤습니다. 한 가지만 해보면 끝입니다. admin 로그인 화면 또는 user 로그인 화면에서 해당 권한이 없는 id와 비번으로 로그인을 시도합니다. 즉 admin 로그인 창에서 user/userpass를 입력합니다. 그럼 다음과 같은 화면을 볼 수 있습니다.
사용자 삽입 이미지
누가 이런 일을 했을까요? ExceptionTranslationFilter 이겠죠? 물론 보여준건 브라우져지만, 브라우져에게 403 에러를 보낸 건 ExceptionTranslationFilter의 일 중 하나입니다.



top

Write a comment.


1.1. What is Acegi Security?



Acegi Security는 J2EE 기반 엔터프라이즈 애플리케이션에 폭넓은 보안 서비스를 제공한다. 특히 Spring을 사용하고 있다면 보다 쉽게 Acegi에 접근할 수 있을 것이다.

기존 Servlet이나 EJB 스펙의 보안은 WAR나 EAR단위로 이식을 할 수 없었기 때문에, 서버 환경이 바뀌면 새 환경에 맞게 여러 설정을 변경해야했다. Acegi는 이러한 불편을 극복함은 물론이고, 이밖에도 여러 유용한 기능을 포함하고 있다.

두 가지 주요 기능을 제공한다.
  • Authentication(인증) : principal[각주:1]을 인식
  • Authorization(권한) : principal이 애플리케이션에서 해당 행위를 할 수 있는지 결정
인증 차원에서 Acegi는 다양한 인증 모델을 지원한다.
위와 같이 다양한 인증 모델을 지원하기 때문에 많은 곳에서 사용하고 있지만, 혹여나 Acegi에서 지원하고 있지 않은 인증 모델들 중에 맘에 드는 것이 없을 수도 있다. Acegi는 오픈 프레임임웤이기 때문에 알아서 구현하면 된다. 표준을 사용하지 않는 별도의 인증 시스템을 구현하여 사용하고 있는 기존 시스템에 적용하고 싶을 수도 있다. 이 때도 Acegi는 잘~ 적용될 수 있다.

어떻게 인증을 거치느냐에 따라 세 종류의 권한 기능을 제공한다. authorizing web requests, authorizing methods can be invoked, authorizing access to individual domain object instances 이 녀석들을 이해 하려면 Servlet 스팩의 웹 패턴 보안, EJB 컨테이너가 관리하는 보안(CMS)과 파일 시스템 보안에 대해 살펴보라. Acegi는 이들 모두에 대해 고려했으며, 차후에 자세히 설명하겠다.

'Spring Security > I. Overall Architecture' 카테고리의 다른 글

4. Channel Security  (0) 2007.08.21
3.2 Filters  (0) 2007.08.14
2.3 Authentication  (2) 2007.08.13
2.2 Shared Components  (0) 2007.08.13
1.1. What is Acegi Security?  (0) 2007.08.08
top

Write a comment.


Spring Acegi Tutorial



참조 :  Spring Acegi Tutorial

Spring Security(Acegi Security)에 대한 맛보기용 아티클로 매우 적당한 것 같습니다. 먼저 Acegi에서 흔히 사용하는 용어에 대해 설명을 하고, 간단한 애플리케이션을 통해 실제 Acegi를 적용하여 구동하고 있는 녀석을 살펴본 뒤에, 해당 샘플에서 사용한 필터들과 각각의 필터들의 종속성을 살펴보고 있습니다. 개인적으로는 이러한 구성이 어렵고 생소한 프레임워크를 공부하는데 가장 좋은 것 같습니다.

Acegi에서 사용하는 용어
- Authentication(인증) : "너는 누구냐?"
    - principal(주체) : username
    - credentials(신용) : password
- Authorization(권한) : "뭐 할려고?"
    - object definitions : secured resources, 관계자외 출입 금지인 자원

샘플 애플리케이션  
사용자 삽입 이미지
- 두 링크 모두 로그인으로 인증을 하며, 이때 validation을 해서 에러페이지로 이동시킬 수 있습니다.
- 특정 url과 role을 맵핑한 정보를 사용하여 권한 체크를 합니다.

샘플에서 사용한 필터들과 그들의 종속성
사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지
예전에 토비님께서 작성하셨던 "나의 Spring Acegi Security Framework 학습기"에 보면 더 많은 필터들이 있지만 일단 여기서는 위의 예제에서 사용한 httpSessionContextIntegrationFilter, authenticationProcessingFilter, exceptionTranslationFilter, filterInvocationInterceptor 네 개만 살펴보겠습니다.

1. AuthenticationProcessingFilter(위 그림에서 formAuthenticationProcessingFilter)
Http Request가 지나가는 첫 번째 필터로 인증과 관련된 요청을 처리하는데 특화된 필터 입니다. 즉, 로그인과 관련된 요청에 특화 되었기 때문에 폼 서브밋 URL 값(filterProcessUrl 속성)이나 로그인 실패시 URL 값(authenticationFailureUrl 속성)들을 설정합니다.

2. HttpSessionContextIntegrationFilter
위에서 살펴보았던 AuthenticationProcessingFilter가 사용하고 있는 AuthenticationManager에 의해 만들어지고 관리되는 Authentication 객체를 Thread Local을 사용하여(servlet이 thread기반이라..) 감싸서(wrap) 해당 쓰레드 내의 여러 request에서 같은 Authentication 객체를 공유할 수 있도록 하는 역할을 합니다.

3. ExceptionTranslationFilter
security 시스템의 중추적인 역할을 하는 두 개의 필터 중에 하나이며(다른 하나는 FilterSecurityInterceptor), 인증과 권한에 관련되어 발생하는 예외(AcegiSecurityException)를 잡아서 다음의 두 가지 중 하나로 처리 합니다.
- Authentication 객체 부재로 인한 예외 일 경우 : AuthenticationEntryPoint 를 사용하여 사용자에게 로그인을 요구함.
- FilterSecurityInterceptor에 의해 던져진 권한이 없어서 발생한 예외 일 경우 : 브라우저에게 SC_FORBIDDEN (HTTP 403) 에러를 던집니다.

4. FilterSecurityInterceptor
secured resources에 대한 정의를 담고 있습니다. 이곳에서 실제 특정 URL과 role을 맵핑하는 정보인 objectDefinitionSource 속성을 설정하고 있습니다. 이 속성을 설정할 때는 두 개의 dialect를 지정해 줍니다. 이름만 봐도 대강 짐작이 가는 dialect기 때문에 설정 내용을 살펴보시면 됩니다.
사용자 삽입 이미지




top

Write a comment.