일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Bcrypt
- 스프링 쇼핑몰
- 정규표현식
- spring 쇼핑몰
- 스프링 업로드
- 스프링 쇼핑몰 프로젝트
- 파일 업로드
- 인증번호 전송
- 스프링 메일 전송
- 스프링 게시판
- ResponseEntity
- 스프링 이미지
- 삭제 구현
- arraylist
- 쇼핑몰 프로젝트
- 회원가입 기능
- 스프링 HikariCP
- BCrypt 적용
- 이미지 출력
- 스프링 게시판 구현
- 스프링 프로젝트
- spring 프로젝트
- 스프링 프로젝트 기본 설정
- 로그아웃 기능 구현
- 로그인 기능
- 스프링 포트폴리오
- 쇼핑몰 포트폴리오
- 스프링 파일 삭제
- oracle 설치방법
- 스프링 프로젝트 설정
- Today
- Total
Kim VamPa
[Spring][쇼핑몰 프로젝트][12] 인터셉터 적용 본문
프로젝트 Github : https://github.com/sjinjin7/Blog_Project
프로젝트 포스팅 색인(index) : https://kimvampa.tistory.com/188
목표
로그인, 관리자 메서드 인터셉터 적용
저번 포스팅에서 관리자 페이지를 만들었습니다. 메인 페이지에서 관리자 계정으로만 로그인하였을 때만 관리자 페이지로 이동할 수 있는 링크가 보이도록 하였습니다. 하지만 일반 계정 혹은 로그인하지 않더라도 관리자 페이지 url만 알고 있다면 접속을 할 수 있게 됩니다. 따라서 AdminController.java에 있는 관리자 페이지 접속 메서드에 세션 체크를 통해 권한이 없는 관리자가 접근 시 메서드 실행이 되지 않도록 로직을 작성해야 합니다.
문제는 해당 몇몇 개의 메서드만 적용해야 한다면 문제가 없습니다. 하지만 AdminController.java 에서 작성된 메서드 들은 관리자가 사용할 메서드 들이기 때문에, 작성될 메서드 전체에 사용자 권한을 확인하는 코드를 중복하여 작성해야 합니다.
이러한 (권한을 체크하는) 세션 체크 로직처럼 웹을 실행하기 위한 핵심 로직은 아니지만 반드시 필요한 로직들을 한 번의 작성으로 일괄적으로 관리해 줄 수 있도록 해주는 수단으로써 Interceptor가 있습니다. 이 Interceptor는 Controller를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 일종의 필터입니다. 이번 포스팅에선 현재의 프로젝트에 Interceptor를 적용하는 것이 목표입니다.
인터셉터(Interceptor) 적용 대상은 2개입니다.
1. AdminController.java 전체
2. MemberController.java의 로그인 메서드
(인터셉터(Interceptor)에 자세한 사항은 아래의 포스팅에서 정리하였습니다)
[spring] Spring Interceptor 란?
순서
0. 변경사항
1. Interceptor 기본 설정
2. LoginInterceptor.java 구현
3. AdminInterceptor.java 구현
4. 테스트
0. 변경사항
0.1 관리자 페이지
다음 포스팅부터 관리자 페이지를 진행하기위해 관리자 페이지의 기본적인 틀을 만들었습니다. 저번 포스텡이서 만든 admin 폴더 경로에 있는 main.jsp를 아래의 코드로 변경하였습니다.
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="../resources/css/admin/main.css">
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
</head>
</head>
<body>
<div class="wrapper">
<div class="wrap">
<!-- gnv_area -->
<div class="top_gnb_area">
<ul class="list">
<li><a href="/main">메인 페이지</a></li>
<li><a href="/member/logout.do">로그아웃</a></li>
<li>고객센터</li>
</ul>
</div>
<!-- top_subject_area -->
<div class="admin_top_wrap">
<span>관리자 페이지</span>
</div>
<!-- contents-area -->
<div class="admin_wrap">
<!-- 네비영역 -->
<div class="admin_navi_wrap">
<ul>
<li >
<a class="admin_list_01">상품 등록</a>
</li>
<li>
<a class="admin_list_02">상품 목록</a>
</li>
<lI>
<a class="admin_list_03">작가 등록</a>
</lI>
<lI>
<a class="admin_list_04">작가 관리</a>
</lI>
<lI>
<a class="admin_list_05">회원 관리</a>
</lI>
</ul>
<!--
<div class="admin_list_01">
<a>상품 관리</a>
</div>
-->
</div>
<div class="admin_content_wrap">
<div>관리자 페이지 입니다.</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</body>
</html>
|
아래의 main.css 파일을 생성하였고 경로를 css/admin/ 폴더 아래에 두었습니다.
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
@charset "UTF-8";
*{
margin: 0;
padding:0;
}
a{
text-decoration: none;
}
ul{
list-style: none;
}
/* 화면 전체 렙 */
.wrapper{
width: 100%;
}
/* content 랩 */
.wrap{
width : 1080px;
margin: auto;
}
/* 홈페이지 기능 네비 */
.top_gnb_area{
width: 100%;
height: 50px;
background-color: #f0f0f1;
position:relative;
}
.top_gnb_area .list{
position: absolute;
top: 0px;
right: 0;
}
.top_gnb_area .list li{
list-style: none;
float : left;
padding: 13px 15px 0 10px;
font-weight: 900;
cursor: pointer;
}
/* 관리제 페이지 상단 현페이지 정보 */
.admin_top_wrap{
height:110px;
line-height: 110px;
background-color: #5080bd;
}
.admin_top_wrap>span{
margin-left: 30px;
display:inline-block;
color: white;
font-size: 50px;
font-weight: bolder;
}
/* 관리자 wrap(네비+컨텐츠) */
.admin_wrap{
}
/* 관리자페이지 네비 영역 */
.admin_navi_wrap{
width: 20%;
height: 300px;
float:left;
height: 100%;
}
.admin_navi_wrap li{
display: block;
height: 80px;
line-height: 80px;
text-align: center;
}
.admin_navi_wrap li a{
display: block;
height: 100%;
width: 95%;
margin: 0 auto;
cursor: pointer;
font-size: 30px;
font-weight: bolder;
}
/*
.admin_list_01{
background-color: #c8c8c8;
} */
/* 관리자페이지 컨텐츠 영역 */
.admin_content_wrap{
width: 80%;
float:left;
height: 100%;
height: 700px;
}
.admin_content_wrap div{
margin-top: 280px;
text-align: center;
font-size: 50px;
font-weight: bolder;
}
/* float 속성 해제 */
.clearfix{
clear: both;
}
|
"/admin/main.jsp"의 gnb영역에 있는 로그아웃은 <script> 태그를 통해 post방식의 "/member/logout"을 요청하는 것이 아니라 GET 방식의 "/member/logout"으로 변경하였습니다. 관리자 페이지에서 화면 이동 없이 로그아웃 해도 크게 문제는 생기지 않습니다. 왜냐하면 로그아웃 후 "/admin"경로의 url을 요청하더라도 이번 포스팅에서 적용할 Intreceptor에 의해 main 페이지로 강제 이동될 것이기 때문입니다. 그렇지만 관리자 페이지에 있는 상황에서 로그아웃이 되었음을 좀 더 명확히 하기 위해서 로그아웃 후 메인 페이지로 이동시키는 GET방식의 "/member/logout.do" url을 사용하였습니다.
0.2 로그인 url 변경
기존 로그인 url을 쓰는데 전혀 문제가 없지만, 이번 포스팅에서 사용할 인터셉터의 적용 대상을 정확히 타겟팅 하기 위해서 로그인 url을 약간 수정하겠습니다. POST방식의 로그인 url을 기존 "login"에서 "login.do"로 변경하겠습니다. 변경할 곳은 두 곳입니다. MemberController.java에 RequestMapping 어노테이션 부분, login.jsp에 있는 <script> 태그 내에 서버에 로그인을 요청하는 부분을 변경합니다.
1. Interceptor 기본설정
Interceptor를 사용하기 위해서 전체적으로 두 가지의 작업이 필요합니다.
첫 번째, spring-web 라이브러리를 pom.xml에 추가합니다.
두 번째, 적용할 Interceptor 클래스(class)를 작성하고, 이를 적용하기 위해 servlet-context.xml 에 적용시킬 경로와 적용할 클래스를 설정합니다.
1.1 spring-mvc 라이브러리 추가
spring-web 라이브러리를 추가해줍니다. 하지만 이미 spring-web 라이브러리를 포함하고 있는 spring-webmvc 추가해놓았기 때문에 따로 추가할 필요는 없습니다.
1.2 Interceptor 클래스 작성
Interceptor 클래스를 따로 관리하기 위해서 com.vam.interceptor 패키지를 새로 만들었습니다.
새로 만든 패키지에 LoginInterceptor.java, AdminInterceptor.java 클래스를 생성합니다. 클래스에 세부 작성은 다음 순서에서 살펴봅니다.
1.3 servlet-context.xml 설정
우리가 적용할 대상은 "/admin"경로가 붙는 모든 url, 로그인을 수행하는 "login.do" url입니다. 따라서 servlet-context.xml에 해당 url에 적용되도록 코드를 추가합니다. 추가적으로 우리가 생성한 Interceptor 클래스가 Spring에서 인식하여 적용이 될 수 있도록 bean 코드도 추가해줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!-- 인터셉터 적용 -->
<interceptors>
<interceptor>
<mapping path="/member/login.do"></mapping>
<beans:bean id="loginIntreceptor" class="com.vam.interceptor.LoginInterceptor"></beans:bean>
</interceptor>
<interceptor>
<mapping path="/admin/**"></mapping>
<beans:bean id="AdminIntreceptor" class="com.vam.interceptor.AdminInterceptor"></beans:bean>
</interceptor>
</interceptors>
|
2. LoginInterceptor.java 구현
일어날 확률은 매우 낮지만 이전 작업 중 세션이 완전히 제거되지 않아 로그인을 위해 새로운 세션을 저장할 때 발생할 수 있는 에러를 방지하기 위해서 로그인 메서드가 있는 MemberController.java에 진입하기 전 세션을 제거하는 작업을 해주고자 합니다.
먼저 해당 클래스를 Interceptor로 사용하기 위해서 클래스 선언부에 HandlerInterceptor 상속을 선언합니다.
1
2
3
|
implements HandlerInterceptor
|
우리가 하고자 하는 작업은 Controller에 진입하기 전에 작업을 원하기 때문에 preHandle() 메서드를 오버 라이딩합니다.
1
2
3
4
5
6
7
8
|
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
|
preHandle() 메서드 구현부에 세션을 제거해주는 코드를 추가합니다. preHandle이 정상적으로 작동했는지 확인하기 위해서 println() 메서드를 호출하였습니다. println() 메서드는 정상적으로 실행이 되는지 확인 후 주석 처리하거나 삭제합니다.
1
2
3
4
5
6
7
|
System.out.println("LoginInterceptor preHandle 작동");
HttpSession session = request.getSession();
session.invalidate();
|
3. AdminInterceptor.java 구현
관리자 메서드("/admin/**")에 접근하는 사용자의 admiCk 1인지 확인하는 작업이 핵심입니다. 따라서 "member"session정보를 MemberVO타입의 변수에 담은 후, 해당 변수를 통해 admiCk의 값을 호출하여 비교하는 로직을 작성해주어야 합니다.
LoginInterceptor.java와 동일하게 HandlerInterceptor 클래스를 상속시키고 preHandle() 메서드를 오버 라이딩합니다.
먼저 "member" session을 호출하여 MemberVO타입의 lvo 변수에 저장합니다. ( MemberVO 타입으로 형 변환(Casting) 해주어야 합니다.)
1
2
3
4
5
|
HttpSession session = request.getSession();
MemberVO lvo = (MemberVO)session.getAttribute("member");
|
if문을 통해서 lvo가 null이거나 getAdminCk() 메서드 반환 값이 0이면 main 페이지로 리다이렉트 되도록 코드를 추가 후 false를 반환하도록 로직을 작성합니다. 아닐 경우 AdminController.java 에 접근할 수 있도록 true를 반환하도록 작성합니다.
1
2
3
4
5
6
7
8
9
10
11
|
if(lvo == null || lvo.getAdminCk() == 0) { // 관리자 계정 아닌 경우
response.sendRedirect("/main"); // 메인페이지로 리다이렉트
return false;
}
return true; // 관리자 계정 로그인 경우(lvo != null && lvo.getAdminCk() == 1)
|
4. 테스트
4.1 LoginInterceptor 테스트
로그인을 진행하여 console창에 문구가 뜨는지를 통해 테스트를 합니다.
4.2 AdminInterceptor 테스트
로그인하지 않은 상태에서 url("/admin/main") 접근을 해봅니다. 결과는 메인 페이지로 들어가집니다.
일반 계정으로 로그인한 상태에서 위와 동일하게 url을 통해서 접근합니다. 위와 동일하게 관리자 페이지 이동이 되지 않고 메인 페이지로 이동합니다.
REFERENCE
DATE
- 2020.02.01
'스프링 프레임워크 > 쇼핑몰 프로젝트' 카테고리의 다른 글
[Spring][쇼핑몰 프로젝트][13] 작가 테이블 구성 & 기타 작업(로고,footer영역, 관리자 페이지) - 2 (10) | 2021.02.05 |
---|---|
[Spring][쇼핑몰 프로젝트][13] 작가 테이블 구성 & 기타 작업(로고,footer영역, 관리자 페이지) - 1 (11) | 2021.02.05 |
[Spring][쇼핑몰 프로젝트][11] gnb(비동기 로그아웃 버튼) (1) | 2021.01.29 |
[Spring][쇼핑몰 프로젝트][11] gnb 영역(로그인,비로그인,관리자) (11) | 2021.01.28 |
[Spring][쇼핑몰 프로젝트][10] 로그아웃 기능 구현(메인페이지) (2) | 2021.01.28 |