스프링 시큐리티의 기본 동작 방식은 서블릿의 여러 종류의 필터와 인터셉터를 이용해서 처리된다.
필터는 서블릿에서 말하는 단순한 필터를 의미하고, 인터셉터는 스프링에서 필터와 유사한 역할을 한다.
필터와 인터셉터는 특정한 서블릿이나 컨트롤러의 접근에 관여한다는 점에서는 유사하지만 결정적인 차이를 구분하자면 필터는 스프링과 무관하게 서블릿 자원이고, 인터셉터는 스프링의 빈으로 관리되면서 스프링의 컨텍스트 내에 속한다는 차이이다.
스프링 시큐리티를 이용하게되면 인터셉터와 필터를 이용하면서 별도의 컨텍스트를 생성해서 처리된다.
스프링 시큐리티는 현재 동작하는 스프링 컨텍스트 내에서 동작하기 때문에 이미 컨텍스트에 포함된 여러 빈들을 같이 이용해서 다양한 방식의 인증 처리가 가능하도록 설계할 수 있다.
1. Spring Web Security의 설정
1) ex06 프로젝트를 만들고 (spring regacy project -> spring mvc project -> org.zerock.controller) pom.xml을 기본 구성과 똑같이 복사붙여넣기 한다! (일단 복붙해놓고 고치도록 할 것임)
스프링 시큐리티는 스프링의 여러 하위 프로젝트 중에 하나이므로, http://projects.spring.io/spring-security/와 같은 페이지를 이용해서 필요한 버전을 추가한다! ( 스프링 공식 문서에는 spring-security-web 만이 존재하지만, 다양한 처리를 위해서는 아래와 같이 3개의 파일을 받도록 한다. - 이는 동일한 버전으로 맞추어야함!)
2) jsp에서는 스프링 시큐리티 관련된 태그 라이브러리를 활용할 수 있도록 spring-security-taglib를 추가한다.
- pom.xml
<!-- spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
1-1. security-context.xml 생성
스프링 시큐리티는 단독으로 설정할 수 있기 때문에 기존의 root-context.xml이나 servlet-context.xml과는 별도로 security-context.xml을 따로 작성하는 것이 좋다.
1) 메뉴에서 'Spring Bean Configuration File' 를 통해서 생성하거나 일반 xml 파일로 생성할 수 있다.
2) 작성한 security-context.xml은 네임스페이스에서 security 항목을 체크한다.
스프링 시큐리티 5버전에서 주의해야 하는 사항은 네임스페이스에 추가된 버전이 5.0의 xml 네임스페이스라는 점이다.
3) security-context.xml 을 아래와 같이 고친다. (5.0을 지우면 됨)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
XML을 이용해서 스프링 시큐리티를 설정할 때에는 5.0 네임스페이스에서 문제가 발생하기 때문에 security-context.xml은 위와 같이 수정한다. (4.2 버전까지는 허용이 되지만 5.0은 에러가 발생하는 버그가 있단다......)
1-2. web.xml 설정
스프링 시큐리티가 스프링 MVC에서 사용되기 위해서는 필터를 이용해서 스프링 동작에 관여하도록 설정한다.
- 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>
web.xml에 필터를 적용한 후 프로젝트를 실행해 보면 아래와 같이 에러가 발생하는 것을 확인할 수 있다.
에러의 원인은 'springSecurityFilterChain'이라는 빈이 제대로 설정되지 않아서 발생한다고 나오는데, 이는 스프링 시큐리티의 설정 파일을 찾을 수 없기 때문이다... 이에 대한 처리는 작성된 security-context.xml을 로딩하도록 설정하는 작업과 security-context.xml에 최소한의 설정이 필요하다.
- web.xml (security-context.xml 를 찾을 수 있도록)
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml
/WEB-INF/spring/security-context.xml
</param-value>
</context-param>
- security-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<security:http>
<security:form-login />
</security:http>
<security:authentication-manager>
</security:authentication-manager>
</beans>
스프링 시큐리티가 동작하기 위해서는 Authentication Manager라는 존재와 스프링 시큐리티의 시작 지점이 필요하기 때문에 위와 같이 최소한의 설정을 지정한 후에 실행한다.
서버를 실행해서 기존과 달리 에러가 발생하지는 않는 것을 확인한다.
2. 시큐리티가 필요한 URI 설계
스프링 시큐리티의 최소한의 설정이 완료되었다면 시큐리티에 의해 제어가 필요한 URI를 설계하고 적용하도록 한다. 예제는 다음과 같은 URI를 설계한다.
- /sample/all -> 로그인을 하지 않은 사용자도 접근 가능한 URI
- /sample/member -> 로그인 한 사용자들만이 접근할 수 있는 URI
- /sample/admin -> 로그인 한 사용자들 중에서 관리자 권한을 가진 사용자만이 접근할 수 있는 URI
org.zerock.controller 패키지 내에 SampleController를 작성하고 해당 URI에 맞는 메서드를 작성한다.
- SampleController.java
package org.zerock.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.log4j.Log4j;
@Log4j
@RequestMapping("/sample/*")
@Controller
public class SampleController {
@GetMapping("/all")
public void doAll() {
log.info("do all can access everybody");
}
@GetMapping("/member")
public void doMember() {
log.info("logined member");
}
@GetMapping("/admin")
public void doAdmin() {
log.info("admin only");
}
}
views 폴더에는 sample 폴더를 작성하고 해당 URI에 맞는 화면을 작성한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- ALL OR MEMBER OR ADMIN -->
<h1>/sample/all page</h1>
</body>
</html>
member.jsp나 admin.jsp 역시 동일하게 구성하고 <h1> 태그의 내용만을 구분할 수 있도록 작성한다.
3. 인증과 권한부여 (Authentication, Authorization)
스프링 시큐리티의 동작을 이해하기 위해서는 가장 중요한 용어인 인증과 권한에 대한 이해가 필요하다. 인증과 권한에 대한 두 단어의 의미에 대해서는 정확히 정리할 필요가 있다.
'인증'은 쉽게말해서, 자신을 증명하는 것이다. 다시 말해서 자기 스스로가 무언가 자신을 증명할 만한 자료를 제시하는 것이다. 반면에 '권한 부여'는 남에 의해서 자격이 부여된다는 점에서 차이가 있다.
스프링 시큐리티에서 가장 중요한 역할을 하는 존재가 인증을 담당하는 AuthenticationManager(인증매니저)라는 존재이다. AuthenticationManager는 다양한 방식의 인증을 처리할 수 있도록 아래와 같은 구조로 설계되어 있다.
ProviderManager는 인증에 대한 처리를 AuthenticationProvider라는 타입의 객체를 이용해서 처리를 위임한다.
AuthenticationProvider는 실제 인증 작업을 진행한다. 이때 인증된 정보에는 권한에 대한 정보를 같이 전달하게 되는데 이 처리는 UserDetailsService라는 존재와 관련 있다. UserDetailsService 인터페이스의 구현체는 실제로 사용자의 정보와 사용자가 가진 권한의 정보를 처리해서 반환하게 된다.
개발자가 스프링 시큐리티를 커스터마이징 하는 방식은 크게 AuthenticationProvider 를 직접 구현하는 방식과 실제 처리를 담당하는 UserDetailsService를 구현하는 방식으로 나누어진다. 대부분의 경우에는 UserDetailsService를 구현하는 형태를 사용하는 것만으로도 충분하지만 새로운 프로토콜이나 인증 구현 방식을 직접 구현하는 경우에는 AuthenticationProvider 인터페이스를 직접 구현해서 사용한다.
'Spring' 카테고리의 다른 글
[40] spring web security를 이용한 로그인 처리 - 로그인과 로그아웃 처리 (0) | 2020.01.28 |
---|---|
[38] 파일 업로드 처리 - 잘못 업로드된 파일 삭제 (Quartz 라이브러리) (0) | 2020.01.20 |
[37] 파일 업로드 처리 - 게시물의 수정과 첨부파일 (0) | 2020.01.16 |
org.springframework.jdbc.UncategorizedSQLException: ### Error updating database. Cause: java.sql.SQLException: 해당 위치에 지원되지 않는 SQL92 토큰: 31 (0) | 2020.01.10 |
[35] 파일 업로드 처리 - 게시물의 조회와 첨부파일 (0) | 2020.01.10 |