Spring Interceptor란?
컨트롤러(Controller)의 '핸들러(Handler)'를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 일종의 필터
intercept라는 단어는 '낚아채다'라는 의미입니다.
해당 단어의 의미와 같이 사용자 요청에 의해 서버에 들어온 Request 객체를 컨트롤러의 핸들러(사용자가 요청한 url에 따라 실행되어야 할 메서드, 이하 핸들러)로 도달하기 전에 낚아채서 개발자가 원하는 추가적인 작업을 한 후 핸들러로 보낼 수 있도록 해주는 것이 인터셉터(Interceptor)입니다.
환경 설정
1. Pom.xml에서 spring dependency를 설정합니다.
<!-- security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${security.version}</version>
</dependency>
2. resource-> spring 폴더에 context파일(security) 작성합니다.
<bean>파일을 등록합니다.
총 beans, context, security, egov-security를 설정합니다.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:egov-security="http://www.egovframe.go.kr/schema/egov-security"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.egovframe.go.kr/schema/egov-security">
13번째 줄 : db의 정보를 따로 만들어 불어옴
16번째 줄 : auto-config를 true로 설정하게 된다면, 가장 기본적인 로그인 화면창이 생성됩니다.
18~ 25번째 줄 : 로그인 화면설정으로,
로그인 성공시, successHandler를 타게 되고, 실패할 땐 FailHandler를 탑니다.
28~32번째 줄 : 로그아웃할 때 불러오는 url을 설정하고,
invalidate-session= true는 세선을 삭제하는 구간입니다.
34~41번쨰 줄: 암호화하는 구간으로 어떤 단어로 salt할 것인지 설정하는 구간입니다.
3. Spring Interceptor을 구현하기 위해서는 'HandlerInterceptorAdapter'를 구현합니다.
이 부분은 사용자가 url을 통해 들어왔을 때, controller단에 들어가기 전에 낚아 채는 구간입니다.
권한이 있는 자는 들어갈 수 있는지 대조하는 부분으로써, 권한이 있으면 들어가고, 관리자, 사용자, 익명 총 3개로 나뉘어 각각 들어갈 수 있는 구간을 나누어 관리하였습니다. 관리는 DB를 사용하여 각각 권한을 주었습니다.
request와 response, handler를 매개변수로 받아왔습니다.
request에서 정보를 받아 사용자 권한과 url이 db에 설정된 권한과 url과 맞다면 그 url과 매핑하고, 다르다면 매핑에 실패합니다.
if 문을 사용하여 다르면 denied 페이지로 넘깁니다.
package co.kr.security;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections.MapUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import co.kr.security.service.impl.UserLoginMapper;
public class AuthInterc extends HandlerInterceptorAdapter {
@Resource(name="userLoginMapper")
public UserLoginMapper userLoginMapper;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println(" ");
System.out.println("인터셉터");
SecurityContext context = SecurityContextHolder.getContext();
HashMap<String, Object> params = new HashMap<String, Object>();
Authentication authentication = context.getAuthentication();
params.put("authenties", context.getAuthentication().getAuthorities().toArray()[0].toString());
params.put("requestUri", request.getRequestURI().toString());
Map<String, Object> dbInter = new HashMap<String, Object>();
dbInter = userLoginMapper.securityInterc(params);
//db 정보 담기
String dbUri = MapUtils.isEmpty(dbInter) ? "" : dbInter.get("uri").toString();
String dbAuth = MapUtils.isEmpty(dbInter) ? "" : dbInter.get("authorities").toString();
System.out.println("db 사용자 : "+dbAuth + " db 사용자 uri : " + dbUri);
//실질 사용자 정보
String requestAuth = params.get("authenties").toString();
String requestUri = params.get("requestUri").toString();
System.out.println("사용자권한 : " + requestAuth +" 실질 사용자 uri : " + requestUri);
//비교 실질 사용자 권한과 db의 권한을 비교 또는 실질 사용자가 admin일떄
if(requestAuth.equals(dbAuth) || requestAuth.equals("ROLE_ADMIN")){
//db권한이 어나니머스 또는 우저가 실질 사용자가 요청을 하였을떄 user가 아닐때
if(dbAuth.equals("ROLE_ANONYMOUS") && !requestAuth.equals("ROLE_ANONYMOUS")){
response.sendRedirect("/main.do");
System.out.println("already login");
}else{
System.out.println("권한이 있어서 사용이 가능함 ( " + requestAuth+" )");
}
//실질 정보가 관리자 또는 user일때.
}else if(requestAuth.equals("ROLE_ADMIN") || requestAuth.equals("ROLE_USER")){
if (requestUri.equals("/login.do")){
response.sendRedirect("/main.do");
}else if(!requestUri.equals(dbUri)){
System.out.println("uri 틀림");
response.sendRedirect("/main.do");
}
}else if(requestAuth.equals("ROLE_ANONYMOUS")){
response.sendRedirect("/login.do");
}else{
//접근이 없을 땐
response.sendRedirect("/accessDenied.do");
System.out.println("사용자인증과 db인증이 맞지 않음");
System.out.println("db인증 :"+ dbAuth +" 사용자 인증 : " + requestAuth);
}
return super.preHandle(request, response, handler);
}
}
4. dispatcher-survlet<mvc:interceptors>를 설정합니다.
저는 이 설정을 권한이 없는 사람들이 들어갈 수 있는 웹사이트는 interceptor를 거치지 않기 위함으로 작성하였습니다.
권한이 없는 사람들은 exclude-mapping을 통하여 설정하였으며, 이 웹사이트 url을 갈 경우에는 interceptor가 아니라 바로 controller단을 탈 수 있게 합니다.
76~80번 째줄 : interceptor를 안거치고 바로 controller단을 넘기는 부분입니다.
'언어 > Spring' 카테고리의 다른 글
[Spring] 파일 업로드하기 (0) | 2023.02.13 |
---|---|
[Spring Security] 로그인 구현하기 (2) | 2022.09.21 |
[spring] spring security (0) | 2022.09.06 |
[Spring] chapter3. 스프링과 Oracle DB 연동 [Oracle DB] (0) | 2022.03.12 |
[Spring] Chapter2. 스프링 특징과 의존성 주입 (0) | 2022.02.16 |