[Spring]Spring Web Security 기초

스프링 MVC 프로젝트에서 별도의 보안이 필요한 경우 Spring Security를 이용하며, 필터(Filter)와 인터셉터(Interceptor) 가 특정 서블릿이나 컨트롤러에 접근하여 보안에 따른 동작을 수행하며, 필터는 Servlet 의 자원으로, 인터셉터는 Spring의 Bean 객체로 관리되어 Spring Context 내에 속한다. 


※ Spring Security 구성
- Security Context는 단독 설정울 위해 별도의 xml 파일로 만들어 관리한다.



pom.xml : 사용 mavan repository - Spring security

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
<!-- 스프링 시큐리티를 사용하기 위한 mavan repository -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>5.0.7.RELEASE</version>
</dependency>
 
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>5.0.7.RELEASE</version>
</dependency>
 
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>5.0.7.RELEASE</version>
</dependency>
 
 
<!-- 스프링 시큐리티 관련 태그 라이브러리  위한 mavan repository -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>5.0.7.RELEASE</version>
</dependency>
cs


※ Security-Context.xml 생성

※Spring Bean Configuration File 생성


※Bean 설정


※ New Spring Bean Definition 설정은 아래와 같이 설정
- beans : "http://www.springframework.org/schema/beans"
- security : "http://www.springframework.org/schema/security"

web.xml

- context-param 값에 생성한 security-context.xml(설정 파일) 로딩


1
2
3
4
5
6
7
8
9
10
11
12
    
    <!--sevlet-mapping 생략-->    
 
    <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>
cs

- 스프링 동작에 필터가 관여할 수 있도록 'springSecurityFilterChain' 필터 적용 




※ 접근 제한 설정(페이지 접근 및 접근에 대한 권한 설정)

<security:intercept-url pattern="1.적용 url" access="2. 권한 설정"/>
 1. 적용 url : 적용 될 url의 기입
 2. 권한 설정
- permitAll : 모두 접근 가능
- hasRole('사용자 설정 권한') : 사용자가 설정한 권한에 따라 접근 가능
ex) hadRole('ROLE_MEMBER') : 'ROLE_MEMBER' 라는 권한을 가진 사용자만 접근 가능


<security:form-login/> 
- 권한이 요구되는 url 로 이동 시 Spring-Security 에서 기본으로 제공하는 로그인 form 제공
- 사용자 지정 login form 사용가능

<security:form-login login-page="사용할 form url" authentication-success-handler-ref="설정 id 명"/>
※ 상단에 Bean 객체 생성 필요
(<bean id="설정 id 명" class="처리를 위한 class 패키지 명"/>
)


로그인 페이지(사용자 지정) 처리용 클래스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package org.zerock.security;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
 
import lombok.extern.log4j.Log4j;
 
@Log4j
//AuthenticationSuccessHandler : sprint-security 에서 로그인 성공시 처리할 url 로의 동작
//사용자 지정 및 동작을 위해서는 해당 인터페이스를 상속 받아 override가 요구됨
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler{
 
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        // TODO Auto-generated method stub
        log.warn("Login Success");
        
        List<String> roleNames = new ArrayList<String>(); 
        authentication.getAuthorities().forEach(authority -> {
            roleNames.add(authority.getAuthority());
        });
        
        log.warn("Role names : "+roleNames);
        
        if(roleNames.contains("ROLE_ADMIN")) {
            response.sendRedirect("/sample/admin");
            return;
        }
        
        if(roleNames.contains("ROLE_MEMBER")) {
            response.sendRedirect("/sample/member");
            return;
        }
        
        response.sendRedirect("/");
        
    }
 
}
 
cs



권한 설정
※security:user 태그 내부에서 설정

접근 유저 설정
<security:user name="접근 유저 id(name)" password="{noop}패스워드" authorities="적용 권한"/> 
- {noop} : PasswordEncoder를 이용한 패스워드 포맷팅
- 다중 권한 : authorities = "권한1, 권한2" 방식으로 지정
ex) <security:user name="admin" password="{noop}admin" authorities="ROLE_MEMBER, ROLE_ADMIN"/> 
- ROLE_MEMBER, ROLE_ADMIN : 두 가지 권한을 가지고 있음


접근 제한 메시지 처리
※ security:access-denied-handler 설정

- 접근 오류 발생 시 사용자에게 보여줄 페이지에 대한 설정
- <security:access-denied-handler ref="설정 id"/>
※사전 설정
<bean id="사용할 form url" class="처리를 위한 class 패키지 명"/>


권한 없이 접근 시 발생하는 오류 페이지 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package org.zerock.security;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
 
import lombok.extern.log4j.Log4j;
 
@Log4j
//AccessDeniedHandler: sprint-security 에서 권한 없이 특정 페이지  처리할 url 로의 동작
//사용자 지정 및 동작을 위해서는 해당 인터페이스를 상속 받아 override가 요구됨
public class CustomAccessDeniedHandler implements AccessDeniedHandler{
 
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException accessDeniedException) throws IOException, ServletException {
        // TODO Auto-generated method stub
        log.error("Access Denied Handler");
        
        log.error("Redirect....");
        
        response.sendRedirect("/accessError");
    }
 
}
 
cs


로그아웃 처리
※ security:logout 설정

<security:logout logout-url="로그아웃 처리를 위한 url" invalidate-session="true"/>

- invalidate-session : 사용자 정보(id, password)의 삭제 여부
※사전 설정
<bean id="사용할 form url" class="처리를 위한 class 패키지 명"/>

댓글