쉱이
article thumbnail
Published 2022. 10. 27. 11:49
[Spring] Security Interceptor 언어/Spring
728x90
반응형

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를 설정합니다.

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단을 넘기는 부분입니다. 

728x90
반응형
profile

쉱이

@ILV_쉱이

감사합니다:)