9:15 경 학원 도착
<9:30 1교시>
javascript 의 배열에 점 찍어서 사용하는 메소드 (함수를 전달하는 함수)
배열.forEach((item, index)=>{ });
배열.map(item=>{
return newItem
}); 기존 배열에 저장된 아이템을 이용해서 새로운 배열을 얻어낼 때 사용
배열.map(item => newItem); 이라는 람다식으로도 쓸 수 있다.
배열.concat( ) : 배열에, 전달된 새로운 아이템을 추가한 새로운 배열을 얻음
마찬가지로 ...names로 배열을 spread 해놓고 추가할 수도 있음
배열.filter(); : 아이템을 조건에 따라 필터해서 리턴된 값이 true면 아이템을 남기고 리턴된 값이 false 면 제거해서 새로운 배열을 만듦
이 또한 람다식으로 쓸 수 있다고 한다.
람다식을 쓸 수 있는 조건이 궁금해졌다. 알것 같기도 한데, 나중에 질문해봐야지.
정규표현식을 사용해서 filter를 사용할 수도 있다.
정규표현식을 제대로 쓰는게 중요하다. 처음에 ^시작과 $끝 안넣고 했음
배열.sort() : 새로운 배열을 만들지 않고 바로 그 배열의 아이템을 오름차순/내림차순 정렬하기
<10:30 2교시>
로그인 폼 만들기
login-form.jsp
<%@ 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>
</head>
<body>
<div class="container">
<h1>로그인 폼</h1>
<form action="login.jsp" method="post">
<div>
<label for="userName">아이디</label>
<input type="text" name="userName" id="userName"/>
</div>
<div>
<label for="password">비밀번호</label>
<input type="password" name="password" id="password"/>
</div>
<button type="submit">로그인</button>
</form>
</div>
</body>
</html>
getData 메소드가 여러번 정의되어 있다 오버로딩 되어 있다.
코딩 팁 : 코딩하다가 잘 안되면 주석으로 논리부터 작성한 다음에 논리에 맞게 코딩을 작성한다.
로그인된 user 정보를 session 영역에 담는데 이외에도 프라이머리키, userName, role 정도를 담아두는 편이다.
그래서 SessionDto를 하나 더 만든다.
package test.user.dto;
public class SessionDto {
private long num;
private String userName;
private String role;
public SessionDto() {}
public SessionDto(long num, String userName, String role) {
super();
this.num = num;
this.userName = userName;
this.role = role;
}
public long getNum() {
return num;
}
public void setNum(long num) {
this.num = num;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
};
}
상태가 2가지니까 불리언으로 상태값을 관리하려고 상태를 관리할 변수를 선언을 해줌.
login.jsp
<%@page import="test.user.dto.SessionDto"%>
<%@page import="test.user.dao.UserDao"%>
<%@page import="test.user.dto.UserDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
// 1. 폼 전송되는 userName, password 를 읽어와서
String userName=request.getParameter("userName");
String password=request.getParameter("password");
//2. 아이디에 해당하는 회원정보를 userdao 객체를 이용해서 얻어와서
UserDto dto = UserDao.getInstance().getData(userName);
//3. 실제로 존재하는 아이디이고, 존재한다면 비밀번호도 일치하는지 비교해서
boolean isLoginSuccess=false;
if(dto!=null){
//비밀 번호 확인 해서
if(dto.getPassword().equals(password)){//비밀번호까지 일치한다면
//로그인 처리를 한다(로그인된 user 정보를 session 영역에 담는다 * 이외에도 프라이머리키, userName, role 정도를 담아두는 편이다.)
SessionDto sessionDto=new SessionDto();
sessionDto.setNum(dto.getNum());
sessionDto.setUserName(dto.getUserName());
sessionDto.setRole(dto.getRole());
//로그인 처리 해주기
session.setAttribute("sessionDto", sessionDto);
isLoginSuccess=true;
}
}
//일치하면 로그인 처리 후 응답, 일치하지 않으면 일치하지 않는다고 응답
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="container">
<%if(isLoginSuccess){%>
<p><strong><%=dto.getUserName() %></strong>님 로그인 되었습니다.</p>
<a href="${pageContext.request.contextPath}/">확인</a>
<%}else{ %>
<p>아이디 또는 비밀번호가 일치하지 않습니다.</p>
<a href="${pageContext.request.contextPath}/user/login-form.jsp">다시 입력</a>
<%} %>
</div>
</body>
</html>
login-form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//Get 방식 파라미터 url 이라는 이름으로 전달되는 값이 있는지 읽어와 보기
String url=request.getParameter("url");
//만일 넘어오는 값이 없다면
if(url==null){
//로그인 후에는 인덱스 페이지로 갈 수 있도록 한다.
String cPath=request.getContextPath();
url=cPath+"/index.jsp";
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="container">
<h1>로그인 폼</h1>
<form action="login.jsp" method="post">
<input type="hidden" name=url value=<%=url %> />
<div>
<label for="userName">아이디</label>
<input type="text" name="userName" id="userName"/>
</div>
<div>
<label for="password">비밀번호</label>
<input type="password" name="password" id="password"/>
</div>
<button type="submit">로그인</button>
</form>
</div>
</body>
</html>
로그아웃 페이지까지
logout.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//1. 세션 초기화
session.invalidate();
//2. 응답
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<script>
alert("로그아웃되었습니다");
//자바스크립트로 페이지 이동시키기
location.href="${pageContext.request.contextPath}/";
</script>
</body>
</html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="class">
<c:choose>
<c:when test="${empty sessionScope.sessionDto}">
<p>
<a href="${pageContext.request.contextPath}/user/login-form.jsp">로그인</a>
<a href="${pageContext.request.contextPath}/user/signup-form.jsp">회원가입</a>
</p>
</c:when>
<c:otherwise>
<p>
<strong>${sessionDto.userName}</strong>님 로그인 중...
<a href="${pageContext.request.contextPath}/user/logout.jsp">로그아웃</a>
</p>
</c:otherwise>
</c:choose>
<h1>인덱스 페이지입니다.</h1>
<ul>
<li><a href="${pageContext.request.contextPath}/jstl/hello.jsp">jstl 테스트</a></li>
<li><a href="${pageContext.request.contextPath}/user/signup-form.jsp">회원가입</a></li>
<li><a href="${pageContext.request.contextPath}/user/login-form.jsp">로그인</a></li>
</ul>
</div>
</body>
</html>
<11:30 3교시>
로그인 된 사람만 사용할 수 있는 페이지 만들기
1. 일단 그 페이지 만드는데, 이 아래 같은 페이지면 로그인 안 한 사람도 사용할 수 있는 상태임
2. 해야할 것 : 로그인 안 한 사람은 로그인 필터링으로 로그인폼 페이지를 리다이렉트 해야 함 -> jsp로 요청하기 전에 필터로 확인해서 그 다음에 리다이렉트 하기
jakarta.servlet 의 필터 인터페이스를 구현하기
override
memberonly 하위의 경로의 모든 요청에 대해 응답하는 필터.
저 이외에도 staff만 접근할 수 있는 페이지나 admin만 참고할 수 있는 페이지도 있을 수 있다.
session은 request를 통해서 세션객체를 직접 코딩해서 얻는다.
리다이렉트 : 클라이언트로 하여금 특정 경로로 요청을 다시 하라고 응답을 줌 -> 웹브라우저가 응답을 다시 클라이언트에게 보여줘서 클라이언트로 하여금 다시 특정 경로로 요청을 하게 함
포워드 : 응답을 위임
아 3교시부터 엄청 졸았다... 일단 위에 올렸던거 다 조금씩 고치는 거 같았어서 일단 최종으로 된 거 코드 백업...
<12:30 4교시>
기능 추가한거까지 일단 코드 업로드....ㅠㅠ 야자해야할듯? ㅠㅠ
login-form.jsp
package test.filter;
import java.io.IOException;
import java.net.URLEncoder;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import test.user.dto.SessionDto;
@WebFilter({"/member-only/*"})
public class LoginFilter implements Filter{
//@WebFilter()에 명시한 패턴의 요청을 하면 아래의 메소드가 호출된다
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//매개변수에 전달된 객체를 이용해서 부모타입을 자식타입으로 캐스팅하여 객체의 참조값을 얻어낸다.
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
//session 영역에서 로그인된 정보를 얻어내기 위한 객체
HttpSession session = req.getSession();
//세션 영역에 sessionDto 라는 키값으로 저장된 세션 값이 있으면 얻어내서 원래 type으로 캐스팅
SessionDto dto = (SessionDto) session.getAttribute("sessionDto");
//만일 로그인하지 않았다면
if (dto == null) {
//로그인 페이지로 리다이렉트 시키는 메소드를 호출해서 리다이렉트 시킴
redirectToLogin(req, res);
//메소드를 여기서 끝내기
return;
}
// Role-based authorization : role을 확인해서 /admin/*, /staff/* 요청도 필터링 해주는 역할
String role = dto.getRole();
String requestURI = req.getRequestURI();
if (requestURI.startsWith(req.getContextPath() + "/admin") && !"ADMIN".equals(role)) {
//금지된 요청이라고 응답한다(관리자만 쓰는거니까 에러페이지를 굳이 쓸 필요는 없음)
res.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied.");
return;
}
if (requestURI.startsWith(req.getContextPath() + "/staff") && !"STAFF".equals(role) && !"ADMIN".equals(role)) {
//금지된 요청이라고 응답한다(직원이 쓸 수 있는거)
res.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied.");
return;
}
// 여기까지 실행의 흐름이 넘어오면 요청의 흐름을 계속 이어간다(필터를 하지 않겠다는 것)Allow access for USER, STAFF, ADMIN
chain.doFilter(request, response);
}
//리다이렉트로 응답하는 메소드(요청을 새로운 경로로 다시 하라는 응답)
private void redirectToLogin(HttpServletRequest req, HttpServletResponse res) throws IOException {
//원래 요청 url을 읽어온다
String url = req.getRequestURI();
//혹시 뒤에 query parameter가 있다면 걔 역시 읽어온다. ?num=xxx&count=ccc
String query = req.getQueryString();
String encodedUrl = query == null ? URLEncoder.encode(url, "UTF-8") : URLEncoder.encode(url + "?" + query, "UTF-8");
//로그인 페이지로 리다이렉트 이동하면서 원래 가려던 목적지 정보도 같이 넘겨줌.
res.sendRedirect(req.getContextPath() + "/user/login-form.jsp?url=" + encodedUrl);
}
}
login.jsp
<%@page import="java.net.URLEncoder"%>
<%@page import="test.user.dto.SessionDto"%>
<%@page import="test.user.dao.UserDao"%>
<%@page import="test.user.dto.UserDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
// 1. 폼 전송되는 userName, password 를 읽어와서
String userName=request.getParameter("userName");
String password=request.getParameter("password");
//2. 아이디에 해당하는 회원정보를 userdao 객체를 이용해서 얻어와서
UserDto dto = UserDao.getInstance().getData(userName);
//3. 실제로 존재하는 아이디이고, 존재한다면 비밀번호도 일치하는지 비교해서
boolean isLoginSuccess=false;
if(dto!=null){
//비밀 번호 확인 해서
if(dto.getPassword().equals(password)){//비밀번호까지 일치한다면
//로그인 처리를 한다(로그인된 user 정보를 session 영역에 담는다 * 이외에도 프라이머리키, userName, role 정도를 담아두는 편이다.)
SessionDto sessionDto=new SessionDto();
sessionDto.setNum(dto.getNum());
sessionDto.setUserName(dto.getUserName());
sessionDto.setRole(dto.getRole());
//로그인 처리 해주기
session.setAttribute("sessionDto", sessionDto);
isLoginSuccess=true;
}
}
//로그인 후 가야할 목적지 정보
String url=request.getParameter("url");
//로그인 실패를 대비해서 목적지 정보를 인코딩한 결과도 준비한다
String encodedUrl=URLEncoder.encode(url, "UTF-8");
//일치하면 로그인 처리 후 응답, 일치하지 않으면 일치하지 않는다고 응답
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="container">
<%if(isLoginSuccess){%>
<p><strong><%=dto.getUserName() %></strong>님 로그인 되었습니다.</p>
<a href="<%=url%>">확인</a>
<%}else{ %>
<p>아이디 또는 비밀번호가 일치하지 않습니다.</p>
<a href="${pageContext.request.contextPath}/user/login-form.jsp?url=<%=encodedUrl%>">다시 입력</a>
<%} %>
</div>
</body>
</html>
UserDao.java
package test.user.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import test.user.dto.UserDto;
import test.util.DbcpBean;
public class UserDao {
//자신의 참조값을 저장할 static 필드
private static UserDao dao;
//static 초기화 블럭 (이클래스가 최초로 사용될때 오직 한번만 수행된다)
static {
//객체를 생성해서 static 필드에 담는다.
dao=new UserDao();
}
//외부에서 객체 생성하지 못하도록 생성자의 접근 지정자를 private 로 설정
private UserDao() {}
//static 필드에 저장된 GuestDao 의 참조값을 리턴해주는 static 메소드
public static UserDao getInstance() {
return dao;
}
public UserDto getData(String userName) {
UserDto dto=null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//Connection Pool 로 부터 Connection 객체 하나 가져오기
conn = new DbcpBean().getConn();
//실행할 sql 문 작성
String sql = """
SELECT num, password, email, role, profileImage, createdAt, updatedAt
FROM users
WHERE userName=?
""";
pstmt = conn.prepareStatement(sql);
// ? 에 값 바인딩할게 있으면 여기서 하기
pstmt.setString(1, userName);
//sql 문 실행하고 결과를 ResultSet 객체로 리턴받기
rs = pstmt.executeQuery();
if (rs.next()) {
dto=new UserDto();
dto.setNum(rs.getLong("num"));
dto.setUserName(userName);
dto.setPassword(rs.getString("password"));
dto.setEmail(rs.getString("email"));
dto.setRole(rs.getString("role"));
dto.setProfileImage(rs.getString("profileImage"));
dto.setCreatedAt(rs.getString("createdAt"));
dto.setUpdatedAt(rs.getString("updatedAt"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (conn != null)
conn.close();
} catch (Exception e) {
}
}
return dto;
}
public UserDto getData(long num) {
UserDto dto=null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//Connection Pool 로 부터 Connection 객체 하나 가져오기
conn = new DbcpBean().getConn();
//실행할 sql 문 작성
String sql = """
SELECT userName, password, email, role, profileImage, createdAt, updatedAt
FROM users
WHERE num=?
""";
pstmt = conn.prepareStatement(sql);
// ? 에 값 바인딩할게 있으면 여기서 하기
pstmt.setLong(1, num);
//sql 문 실행하고 결과를 ResultSet 객체로 리턴받기
rs = pstmt.executeQuery();
if (rs.next()) {
dto=new UserDto();
dto.setNum(num);
dto.setUserName(rs.getString("userName"));
dto.setPassword(rs.getString("password"));
dto.setEmail(rs.getString("email"));
dto.setRole(rs.getString("role"));
dto.setProfileImage(rs.getString("profileImage"));
dto.setCreatedAt(rs.getString("createdAt"));
dto.setUpdatedAt(rs.getString("updatedAt"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (conn != null)
conn.close();
} catch (Exception e) {
}
}
return dto;
}
public boolean insert(UserDto dto) {
Connection conn = null;
PreparedStatement pstmt = null;
int rowCount = 0;
try {
conn = new DbcpBean().getConn();
// 실행할 SQL 문 작성
String sql = """
INSERT INTO users
(num, userName, password, email)
VALUES (users_seq.NEXTVAL, ?, ?, ?)
""";
pstmt = conn.prepareStatement(sql);
// ? 에 값을 여기서 바인딩한다.
pstmt.setString(1, dto.getUserName());
pstmt.setString(2, dto.getPassword());
pstmt.setString(3, dto.getEmail());
// sql 문 실행하고 변화된 row 의 갯수 리턴받기
rowCount = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null)
conn.close();
if (pstmt != null)
pstmt.close();
} catch (Exception e) {
}
}
if (rowCount > 0) {
return true;
} else {
return false;
}
}
public boolean update(UserDto dto) {
Connection conn = null;
PreparedStatement pstmt = null;
int rowCount = 0;
try {
conn = new DbcpBean().getConn();
//실행할 미완성의 sql 문
String sql = """
UPDATE users
SET email=?, profileImage=?, updatedAt=SYSDATE
WHERE num=?
""";
pstmt = conn.prepareStatement(sql);
// ? 에 값을 여기서 바인딩한다.
pstmt.setString(1, dto.getEmail());
pstmt.setString(2, dto.getProfileImage());
pstmt.setLong(3, dto.getNum());
// sql 문 실행하고 변화된 row 의 갯수 리턴받기
rowCount = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null)
conn.close();
if (pstmt != null)
pstmt.close();
} catch (Exception e) {
}
}
if (rowCount > 0) {
return true;
} else {
return false;
}
}
public boolean updatePassword(UserDto dto) {
Connection conn = null;
PreparedStatement pstmt = null;
int rowCount = 0;
try {
conn = new DbcpBean().getConn();
//실행할 미완성의 sql 문
String sql = """
UPDATE users
SET password=?, updatedAt=SYSDATE
WHERE num=?
""";
pstmt = conn.prepareStatement(sql);
// ? 에 값을 여기서 바인딩한다.
pstmt.setString(1, dto.getPassword());
pstmt.setLong(2, dto.getNum());
// sql 문 실행하고 변화된 row 의 갯수 리턴받기
rowCount = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null)
conn.close();
if (pstmt != null)
pstmt.close();
} catch (Exception e) {
}
}
if (rowCount > 0) {
return true;
} else {
return false;
}
}
public boolean updateRole(UserDto dto) {
Connection conn = null;
PreparedStatement pstmt = null;
int rowCount = 0;
try {
conn = new DbcpBean().getConn();
//실행할 미완성의 sql 문
String sql = """
UPDATE users
SET role=?, updatedAt=SYSDATE
WHERE num=?
""";
pstmt = conn.prepareStatement(sql);
// ? 에 값을 여기서 바인딩한다.
pstmt.setString(1, dto.getRole());
pstmt.setLong(2, dto.getNum());
// sql 문 실행하고 변화된 row 의 갯수 리턴받기
rowCount = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null)
conn.close();
if (pstmt != null)
pstmt.close();
} catch (Exception e) {
}
}
if (rowCount > 0) {
return true;
} else {
return false;
}
}
public boolean delete(long num) {
Connection conn = null;
PreparedStatement pstmt = null;
int rowCount = 0;
try {
conn = new DbcpBean().getConn();
//실행할 미완성의 sql 문
String sql = """
DELETE FROM users
WHERE num=?
""";
pstmt = conn.prepareStatement(sql);
// ? 에 값을 여기서 바인딩한다.
pstmt.setLong(1, num);
// sql 문 실행하고 변화된 row 의 갯수 리턴받기
rowCount = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null)
conn.close();
if (pstmt != null)
pstmt.close();
} catch (Exception e) {
}
}
if (rowCount > 0) {
return true;
} else {
return false;
}
}
}
SessionDto.java
package test.user.dto;
public class SessionDto {
private long num;
private String userName;
private String role;
public SessionDto() {}
public SessionDto(long num, String userName, String role) {
super();
this.num = num;
this.userName = userName;
this.role = role;
}
public long getNum() {
return num;
}
public void setNum(long num) {
this.num = num;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
};
}
logout.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//1. 세션 초기화
session.invalidate();
//2. 응답
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<script>
alert("로그아웃되었습니다");
//자바스크립트로 페이지 이동시키기
location.href="${pageContext.request.contextPath}/";
</script>
</body>
</html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="class">
<c:choose>
<c:when test="${empty sessionScope.sessionDto}">
<p>
<a href="${pageContext.request.contextPath}/user/login-form.jsp">로그인</a>
<a href="${pageContext.request.contextPath}/user/signup-form.jsp">회원가입</a>
</p>
</c:when>
<c:otherwise>
<p>
<a href="${pageContext.request.contextPath}/user/protected/info.jsp"><strong>${sessionDto.userName}</strong>님 로그인 중...</a>
<a href="${pageContext.request.contextPath}/user/logout.jsp">로그아웃</a>
</p>
</c:otherwise>
</c:choose>
<h1>인덱스 페이지입니다.</h1>
<ul>
<li><a href="${pageContext.request.contextPath}/jstl/hello.jsp">jstl 테스트</a></li>
<li><a href="${pageContext.request.contextPath}/user/signup-form.jsp">회원가입</a></li>
<li><a href="${pageContext.request.contextPath}/user/login-form.jsp">로그인</a></li>
<li><a href="${pageContext.request.contextPath}/member-only/play.jsp">놀러가기</a></li>
</ul>
</div>
</body>
</html>
play.jsp
<%@ 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>
</head>
<body>
<div class="container">
<h1>로그인된 회원 전용 공간</h1>
<p>
<strong>${sessionDto.userName }</strong>님의 로그인 페이지 입니다.
<a href="${pageContext.request.contextPath}/">인덱스로 돌아가기</a>
</p>
</div>
</body>
</html>
LoginFilter.java
package test.filter;
import java.io.IOException;
import java.net.URLEncoder;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import test.user.dto.SessionDto;
@WebFilter({"/member-only/*", "/staff/*", "/admin/*","/user/protected.jsp"})
public class LoginFilter implements Filter{
//@WebFilter()에 명시한 패턴의 요청을 하면 아래의 메소드가 호출된다
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//매개변수에 전달된 객체를 이용해서 부모타입을 자식타입으로 캐스팅하여 객체의 참조값을 얻어낸다.
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
//session 영역에서 로그인된 정보를 얻어내기 위한 객체
HttpSession session = req.getSession();
//세션 영역에 sessionDto 라는 키값으로 저장된 세션 값이 있으면 얻어내서 원래 type으로 캐스팅
SessionDto dto = (SessionDto) session.getAttribute("sessionDto");
//만일 로그인하지 않았다면
if (dto == null) {
//로그인 페이지로 리다이렉트 시키는 메소드를 호출해서 리다이렉트 시킴
redirectToLogin(req, res);
//메소드를 여기서 끝내기
return;
}
// Role-based authorization : role을 확인해서 /admin/*, /staff/* 요청도 필터링 해주는 역할
String role = dto.getRole();
String requestURI = req.getRequestURI();
if (requestURI.startsWith(req.getContextPath() + "/admin") && !"ADMIN".equals(role)) {
//금지된 요청이라고 응답한다(관리자만 쓰는거니까 에러페이지를 굳이 쓸 필요는 없음)
res.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied.");
return;
}
if (requestURI.startsWith(req.getContextPath() + "/staff") && !"STAFF".equals(role) && !"ADMIN".equals(role)) {
//금지된 요청이라고 응답한다(직원이 쓸 수 있는거)
res.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied.");
return;
}
// 여기까지 실행의 흐름이 넘어오면 요청의 흐름을 계속 이어간다(필터를 하지 않겠다는 것)Allow access for USER, STAFF, ADMIN
chain.doFilter(request, response);
}
//리다이렉트로 응답하는 메소드(요청을 새로운 경로로 다시 하라는 응답)
private void redirectToLogin(HttpServletRequest req, HttpServletResponse res) throws IOException {
//원래 요청 url을 읽어온다
String url = req.getRequestURI();
//혹시 뒤에 query parameter가 있다면 걔 역시 읽어온다. ?num=xxx&count=ccc
String query = req.getQueryString();
String encodedUrl = query == null ? URLEncoder.encode(url, "UTF-8") : URLEncoder.encode(url + "?" + query, "UTF-8");
//로그인 페이지로 리다이렉트 이동하면서 원래 가려던 목적지 정보도 같이 넘겨줌.
res.sendRedirect(req.getContextPath() + "/user/login-form.jsp?url=" + encodedUrl);
}
}
info.jsp
<%@page import="test.user.dao.UserDao"%>
<%@page import="test.user.dto.UserDto"%>
<%@page import="test.user.dto.SessionDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
//session 영역에서 SessionDto 객체를 얻어낸다.
SessionDto sessionDto=(SessionDto)session.getAttribute("sessionDto");
//회원 번호를 이용해서 UserDto 정보 얻어내기
UserDto dto=UserDao.getInstance().getData(sessionDto.getNum());
//el 에서 dto 를 사용가능하게 request 영역에 담는다.
request.setAttribute("dto", dto);
//아래에서 가입정보를 응답한다
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/user/protected/info.jsp</title>
<style>
#profileImage{
width: 100px;
height: 100px;
border: 1px solid #cecece;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="container">
<h1>가입 정보 입니다</h1>
<table>
<tr>
<th>아이디</th>
<td>${dto.userName }</td>
</tr>
<tr>
<th>비밀번호</th>
<td>
<a href="pwd-update-form.jsp">수정하기</a>
</td>
</tr>
<tr>
<th>프로필 이미지</th>
<td>
<c:choose>
<c:when test="${empty dto.profileImage }">
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill="currentColor" class="bi bi-person-circle" viewBox="0 0 16 16">
<path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
<path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1z"/>
</svg>
</c:when>
<c:otherwise>
<img id="profileImage" src="${pageContext.request.contextPath }/upload/${dto.profileImage}" alt="프로필 이미지">
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th>이메일</th>
<td>${dto.email }</td>
</tr>
<tr>
<th>가입일</th>
<td>${dto.createdAt }</td>
</tr>
<tr>
<th>수정일</th>
<td>${dto.updatedAt }</td>
</tr>
</table>
</div>
</body>
</html>
'공부의 기록 > 자바 풀 스택 : 수업내용정리' 카테고리의 다른 글
자바 풀 스택 1/22 오후 기록 043-2 (1) | 2025.01.22 |
---|---|
자바 풀 스택 1/21 오후 기록 042-2 (1) | 2025.01.21 |
자바 풀 스택 1/20 오후 기록 041-2 (2) | 2025.01.20 |
자바 풀 스택 1/20 오전 기록 041-1 (0) | 2025.01.20 |
자바 풀 스택 1/17 오후 기록 040-2 (1) | 2025.01.17 |