index
- 서론
- 기획 및 명세
- 패키지 트리
- 프로젝트 환경
- 메시지와 국제화
- 예외 다루기
- 검증
- 계정 관련
- 권한 인터셉터
- 도서 관련
- 대여 관련
- 오프라인 관련
- about ajax
- 지식 공유 - ajax
- DTO, Form, VO, Entity
- 후기
머나먼 여정을 지나 드디어 권한 인터셉터로 왔다.
시큐리티를 등한시한 내게 이 인터셉터는 차선책이었다.
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
public class AuthInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler
)
throws Exception {
String uri = request.getRequestURI();
String path = request.getServletContext().getContextPath();
HttpSession session = request.getSession(false);
Member user = (Member)session.getAttribute(SessionConst.USER);
if(session == null || user == null) {
response.sendRedirect(path+"/sign/in?redirectURL="+uri);
return false;
}
int right = user.getRights();
String area = uri.substring(path.length());
boolean memberPath = area.startsWith(PathConst.MEMBERS);
boolean staffPath = area.startsWith(PathConst.STAFF);
boolean adminPath = area.startsWith(PathConst.ADMIN);
boolean offlinePath = area.startsWith(PathConst.OFFLINE);
boolean isMember = (right == 0);
boolean isStaff = (right == 2);
boolean isAdmin = (right == 3);
if(offlinePath || memberPath && isMember) {
String pathVariable = uri.split("/")[3];
if(!user.equalsId(pathVariable)) {
request.setAttribute("message", "요청 실패");
response.sendRedirect(path);
return false;
}
}
if(memberPath && !isMember) {
request.setAttribute("message", "일반회원만 접근할 수 있습니다.");
response.sendRedirect(path);
return false;
} else if (staffPath && !isStaff) {
request.setAttribute("message", "직원회원만 접근할 수 있습니다.");
response.sendRedirect(path);
return false;
} else if(offlinePath && !isMember) {
request.setAttribute("message", "일반회원만 접근할 수 있습니다.");
response.sendRedirect(path);
return false;
} else if(adminPath && !isAdmin) {
request.setAttribute("message", "관리자만 접근할 수 있습니다.");
response.sendRedirect(path);
return false;
}
request.setAttribute("nav", uri.split("/")[2]);
return true;
}
}
경로에 따라, 권한에 따라 boolean 을 많이도 생성했다.
분명 훨씬 나은 방법이 존재하겠지만 현재까지도 떠오르지 않는다.
권한에 따른 접근을 제어하기 위한 인터셉터다.
만드는 데 큰 어려움은 없었다.
애초에 경로를 나눠 놓을 때 권한 별 제어를 할 수 있도록 구성했었다.
uri 와 contextPath 를 활용하는 부분은
JSP & 서블릿 구조에서 프론트 컨트롤러의 작업과 비슷하다.
우선 권한 별 접근 제한이기에 세션 자체가 없거나 (로그인을 안 했거나)
세션이 존재하더라도 세션 Member 객체가 null 일 때 로그인 화면으로 보낸다.
이때 이전의 요청 경로를 쿼리파라미터에 함께 넘겨서
로그인 성공했을 때 돌아갈 수 있도록 지정했다.
이 부분에서 한 가지 궁금증이 생길 수 있는데,
악의적으로 admin 경로로 진입한 뒤 일반 회원으로 로그인 한다면?
걱정하지말자.
“권한에 따른 접근 제어” 이게 본질이다.
접근 제어가 필요한 경로엔 이 인터셉터가 매번 적용되어
위와 같은 상황은 로그인 성공 시 Home 화면으로 이동된다.
Betty 의 member 영역에 대한 경로는 아래와 같다.
"http://localhost:8080/betty/members"
members, staff, admin, offline 중 해당하는 경로가 있을 때 검증이 시작된다.
맨 마지막에 있는 “nav”는 좌측 네비게이터를 동적으로 구성하기 위한 장치다.
인증, 인가 검사를 거치고 나면
request 영역 객체에 해당 카테고리의 nav 정보를 담는다.
jsp:include 태그를 이용하여 contextPath 와 Session Member 객체를 넘긴다.
동적 include 를 사용할 때 변수를 그대로 이용할 수 없어 param 태그로 넘겨줘야 된다.
include file 은 동일한 Servlet 내에서 렌더링되지만
경로 내에 el 을 사용할 수 없다.
jsp include 는 각자 독립된 Servlet 에서 렌더링된 뒤 포함되는 형식이고, el 을 사용할 수 있다.