페이지 접근 관리
IndexController
현재 로그인을 해야 main을 갈 수 있게 하도록 하겠습니다
@RequestMapping("/mainPage.do")
public String mainPage() {
return "main";
}
IndexController에 간단하네 mainPage를 가는 메서드를 만들어 줍니다
현재는 mainPage.do를 하면 바로 main페이지가 보이는데요 이걸 로그인을 안하면 접속을 못하게 바꾸어 보겠습니다
로그인 여부는 어떻게 알까요?
로그인을 하면 session이 생기기에 session을 활용해 로그인 여부를 체그해줍니다
@RequestMapping("/mainPage.do")
public String mainPage(HttpServletRequest request) {
HttpSession session = request.getSession();
if(!ObjectUtils.isEmpty(session.getAttribute("memberId"))) {
return "main";
}
return "login";
}
실행해보면 이렇게 로그인을 안하면 로그인 페이지로 보내줍니다 하지만 주소창을 보면 mainPage.do로 페이지랑 따로 놀게됩니다
@RequestMapping("/mainPage.do")
public String mainPage(
HttpServletRequest request,
HttpServletResponse response) throws IOException{
HttpSession session = request.getSession();
if(ObjectUtils.isEmpty(session.getAttribute("memberId"))) {
response.sendRedirect(request.getContextPath() + "loginPage.do");
}
return "main";
}
이걸 해결하기 위해 HttpServletResponse를 파라미터에 추가하고 sendRedirect를 이용해 loginPage.do로 보내줍니다
여기서 단점은 request가 아닌 response를 사용하면 값을 못뽑아와서 알림 메시지를 띄울 수 없습니다
그렇기에 response.sendRedirect
바로 처리할때(리다이렉트 할때)는 이렇게 쓰지만 무조건 Get
방식
request
는 페이지를 다룰때 주로 사용 (레거시에서는request
많이 사용)()response
는 페이지 자체를Redirect
하거나request에 대한 응답
으로만 사용 (text를 실어 보낼 수 있음 -Rest API
나response
)- 처음 코드에서
request
를 사용할 경우 mainPage.do가 안바뀐이유는request
가 갔지만 다시response
가 온게 아니어서 그렇습니다 반대로response
의 경우에는request
의 응답 자체를redirect
시킨 것 입니다 (request
가 끝나고(끊어지고)response
로 보내는 것 입니다)
Tip.
response.sendRedirect()
: ()안에 있는 해당 경로로 이동하라는 의미
서블릿에서 처리한 데이터를 별도로 넘기지 않고 페이지만 이동 (session 객체와는 별개, 무조건Get
방식)request.getContextPath()
: 프로젝트 Path만 가져옵니다
(ex.http://localhost:8080/05/mainPage.do
->/05
만 가져옵니다)request.getRequestURI()
: 프로젝트 + 파일경로 가져옵니다
(http://localhost:8080/05/mainPage.do
->/05/mainPage.do
까지 가져옵니다)request.getRequestURL()
: 전체 경로를 가져옵니다
(ex.http://localhost:8080/05/mainPage.do
->http://localhost:8080/05/mainPage.do
전체 가져옵니다)request.ServletPath()
: 파일명만 가져옵니다
(ex.http://localhost:8080/05/mainPage.do
->/mainPage.do
만 가져옵니다)request.getRealPath()
: 서버 or 로컬 웹 애플리케이션 절대경로 가져옵니다
(ex.http://localhost:8080/05/mainPage.do
->C:\dev\workspace\05_springJdbc_Self\
가져옵니다)
Filter
filter 생성 - LoginFilter
하지만 하나바꾸는데 이렇게했는데 여러개일 경우에는 어떻게 해결할까요?
바로 filter를 사용해 해결해 볼 수 있습니다
먼저 com.portfolio.www.filter 패키지를 만들고 그안에 filter만들기를 선택후
이름을 LoginFilter하고 next를 누르면 아래 Filter Mappings
을 눌러 URL pattern -> Servlet으로 변경 -> dispatcher
request 선택 -> finish
@WebFilter(dispatcherTypes = {DispatcherType.REQUEST }
, servletNames = { "pf" })
public class LoginFilter extends HttpFilter implements Filter {
//생성자
public LoginFilter() {
super();
}
//죽을 때
public void destroy() {
}
//Filter 작동할 때
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
이렇게 만든 LoginFilter는 Filter를 구현하고 HttpFilter를 확장합니다
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String uri = req.getRequestURI();
System.out.println("----------------uri : " + uri);
chain.doFilter(request, response);
}
uri값을 찍어보겠습니다 그전에 web.xml으로 가줍니다
web.xml
<!-- 필터 등록 -->
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.portfolio.www.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<servlet-name>pf</servlet-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
filter를 등록해줍니다
LoginFilter.java
@WebFilter(dispatcherTypes = {DispatcherType.REQUEST }
, servletNames = { "pf" })
public class LoginFilter extends HttpFilter implements Filter {
//생성자
public LoginFilter() {
super();
System.out.println("--------LoginFilter constructor--------");
}
//필터 죽으면
public void destroy() {
}
//필터 동작하면
public void doFilter(HttpServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String uri = request.getRequestURI();
System.out.println("----------------" + uri);
chain.doFilter(request, response);
}
//필터 등록되면
public void init(FilterConfig fConfig) throws ServletException {
System.out.println("--------LoginFilter init--------");
}
}
console창을 확인하여 작동을 확인합니다
그러고 .do 페이지에 들어가보면
이렇게 uri가 찍히는 것을 확인할 수 있습니다
그럼 이 uri값을 활용하여 페이지를 처리할 수 있겠지요?
먼저 방법은 아래 3가지 있습니다
if(StringUtils.pathEquals(uri, "/05/mainPage.do")) {
}
if(uri.contains("/05/mainPage.do")) {
}
if(uri.indexOf("/05/mainPage.do") > 1) {
}
여기서 첫번째껀 context-root가 붙어있으니 사용이 불편할꺼 같으니 패스
세번째껀 숫자비교이기 때문에 패스
그렇게 이번에는 두번째 방법을 사용하겠습니다
Tip. String 값 확인
- `StringUtils` : 자바의 문자열에 관련된 작업에 유용한 라이브러리(null값을 주더라고 NullPointException이 발생X - 기본 결과값 반환) - `StringUtils.pathEquals( , )` : 두 경로를 비교하여 같은지 확인 - `uri.contains` : 문자열이 지정된 부분 문자열을 포함했는지 확인 - `uri.indexOf` : 주어진 부분 문자열이 처음으로 발견된 인덱스를 반환, 없으면 -1 반환public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String uri = req.getRequestURI();
System.out.println("----------------uri : " + uri);
if(uri.contains("/mainPage.do")) {
HttpSession session = req.getSession();
if(ObjectUtils.isEmpty(session.getAttribute("memberId"))) {
resp.sendRedirect(req.getContextPath() + "/loginPage.do");
return ;
}
}
chain.doFilter(request, response);
}
getAttribute를 활용해 "memberId"값을 가져옵니다 값이 있는지 확인하고 값이 비어있으면 loginPage.do로 redirect시킵니다
IndexController
IndexController가서 위에서 redirect한 코드를 삭제합니다
@RequestMapping("/mainPage.do")
public String mainPage(
HttpServletRequest request,
HttpServletResponse response) throws IOException{
return "main";
}
그리고 서버를 재시작해 mainPage.do를 실행해보면 로그인이 안되있으니 loginPage.do로 가는 것을 확인 할 수 있습니다
doFilter 마지막에 있는
chain.doFilter(request, response);
를 지우면 어떻게 될까요?
바로 filter에 chain이 넘어와야하는데 넘어오지 않아 더이상의 filter를 실행시키지 않아 하얀 화면만 나오게됩니다
추가로 sendRedirect시킬때 html도 가능하고, 이미지만 보여주기 등이 가능합니다(response는 get방식이라 이렇게해서 사용)
여러 페이지 필터링 - LoginFilter
/mainPage.do
/develop.do
/support.do
/sales.do
/fresh.do
/stage.do
/prod.do
/qa.do
전부 로그인 테스트하려면 어떻게 할까요?
정답은 배열을 활용하면 됩니다
실습을 해보면
private final String[] LOGIN_REQUIRED_URI = {
"/mainPage.do", //보통 무슨 페이지인지 주석 달아줌
"/develop.do",
"/support.do",
"/sales.do",
"/fresh.do",
"/stage.do",
"/prod.do",
"/qa.do"
};
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String uri = req.getRequestURI();
System.out.println("----------------uri : " + uri);
if(Arrays.asList(LOGIN_REQUIRED_URI).contains(uri.replace("/05", ""))) {
HttpSession session = req.getSession();
if(ObjectUtils.isEmpty(session.getAttribute("memberId"))) {
resp.sendRedirect(req.getContextPath() + "/loginPage.do");
return ;
}
}
chain.doFilter(request, response);
}
위처럼 LOGIN_REQUIRED_URI
배열에 값을 담고 Arrays.asList(LOGIN_REQUIRED_URI)
해서 배열 값을 List로 변환 contains(uri.replace("/05", ""))
로 앞에 있는 값인 "/05"를 제거하고 문자열을 포함하는지 확인합니다
(List에도 contains가 있다는걸 기억하세요)
(처음부터 List객체르 만들려면 손이 많이가니 배열로 만들어 List로 변환해 사용합니다)
Tip.
Arrays.asList()
: ()안의 값을List
로 변환contains(uri.replace( , ))
: 괄호 앞에 있는걸 삭제후 뒤에 조건과 같은지 확인
한글 인코딩 필터 추가
web.xml
항상 기본으로 달아주는 필터를 추가해 보겠습니다
바로 인코딩 필터인데요
기본적으로 한글이 깨지니 꼭 추가해주세요
<!-- 한글 처리를 위한 필터 설정 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern> <!-- 모든 url에 적용 -->
</filter-mapping>
코드를 보시면 param이 2개 필요합니다
forceEncoding도 매서드 이름입니다
'공부 > 그룹 스터디' 카테고리의 다른 글
[6회차 01] 게시판 리스트 만들기 - DB값 넣기, 의존성 주입 (0) | 2024.05.10 |
---|---|
[5회차 과제 01] 기존 Dao SQL문 prepared statement 형식으로 변경 (0) | 2024.05.10 |
[5회차 04] Enum - 메시지 처리 (0) | 2024.05.06 |
[5회차 03] 로그인 - 예외처리 (0) | 2024.05.05 |
[5회차 02] 로그아웃 (0) | 2024.05.05 |