Preface
이번 장에선 JSP와 OracleDB를 사용해 간단한 로그인 폼을 만들었다.
지난번 Python과 php, MySQL을 이용해 게시판을 제작했을 땐 솔직히 php 코드를 이해하지 못한 체 다른 블로그에 있는 코드를 복사해서 사용했을 뿐이었다.
그러나 DB의 연동부터 서버 사이드 스크립트 언어인 JSP의 코드까지 모두 직접 작성하며 제작을 하다보니 작동 방식과 연결 방식을 쉽게 이해할 수 있었다.
물론 이해만 했을 뿐이지, 혼자 힘으로 모든 코드를 작성할 수 있으려면 작성해둔 코드를 여러 번 읽어보며 복습하는 시간이 꼭 필요할 것 같다.
1. 세션이란?
- 세션(Session): 클라이언트가 웹 브라우저를 통해 서버에 접속한 후 용무를 처리하고 웹 브라우저를 닫아 서버와의 접속을 종료하는 하나의 단위
→ 클라이언트가 서버에 접속해 있는 동안 상태를 유지하는 것이 목적이다.
2. 세션 설정, 확인, 삭제
- 세션의 특징
1) 세션은 웹 브라우저를 실행할 때마다 새롭게 생성된다.
2) 세션은 설정된 유지 시간동안 유지된다.
→ 유지 시간이 만료되기 전에 새로운 요청이 들어오면 수명이 연장된다.
- 세션의 유지 시간을 설정하는 방법
1) web.xml에서 설정
→ web.xml에선 유지 시간을 분 단위로 설정한다.
<session-config>
<session-timeout>20</session-timeout>
</session-config>
2) JSP 파일에서 session 내장 객체가 제공하는 메서드를 사용
→ 해당 메서드의 시간 단위는 초이다.
<%
session.setMaxInactiveInterval(1800);
%>
- 세션의 속성
1) 유지 시간
2) 아이디: 웹 브라우저를 새롭게 열 때마다 다른 값으로 설정된다.
3) 최초 요청 시각
4) 최종 요청 시각
<%@ page import="java.util.Date"%>
<%@ page import="java.text.SimpleDateFormat"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
long creationTime = session.getCreationTime();
String creationTimeStr = dateFormat.format(new Date(creationTime));
long lastTime = session.getLastAccessedTime();
String lastTimeStr = dateFormat.format(new Date(lastTime));
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Session</title>
</head>
<body>
<h2>Session 설정 확인</h2>
<ul>
<li>세션 유지 시간: <%=session.getMaxInactiveInterval()%></li>
<li>세션 아이디: <%=session.getId()%></li>
<li>최초 요청 시각: <%=creationTimeStr%></li>
<li>마지막 요청 시각: <%=lastTimeStr%></li>
</ul>
</body>
</html>
- JSESSIONID: 요청을 보낸 웹 브라우저가 현재 연결되어 있는지 확인하는 데 사용한다.
→ 즉, 웹 브라우저로부터 전달받은 JSESSIONID를 통해 서버는 동일한 세션인지 확인할 수 있다.
3. 세션과 DB를 이용한 로그인 구현
- 로그인 폼
1) validateForm( ): JS로 작성한 유효성 검사 함수로, ID와 PW 중 빈 값이 있다면 경고창을 띄운다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Session</title>
</head>
<body>
<jsp:include page="../Common/Link.jsp" />
<h2>로그인 페이지</h2>
<span style="color: red; font-size: 1.2em;">
<%=request.getAttribute("LoginErrMsg") == null ? "" : request.getAttribute("LoginErrMsg")%>
</span>
<%
if (session.getAttribute("UserId") == null) { // 로그아웃 상태
%>
<script>
function validateForm(form) {
if (!form.user_id.value) {
alert("아이디를 입력하세요.");
return false;
}
if (form.user_pw.value == "") {
alert("패스워드를 입력하세요.");
return false;
}
}
</script>
<form action="LoginProcess.jsp" method="post" name="loginFrm"
onsubmit="return validateForm(this);">
아이디: <input type="text" name="user_id" /><br /> 패스워드: <input
type="password" name="user_pw" /><br /> <input type="submit"
value="로그인하기" />
</form>
<%
} else { //로그인 상태
%>
<%=session.getAttribute("UserName")%>
회원님, 로그인하셨습니다.
<br />
<a href="Logout.jsp">[로그아웃]</a>
<%
}
%>
</body>
</html>
- DTO(Data Transfer Object): 계층 사이에서 데이터를 교환하기 위해 생성하는 객체
→ DTO 클래스는 일반적으로 테이블당 하나씩 생성하며, 테이블의 컬럼과 동일한 멤버 변수를 갖는다.
package membership;
public class MemberDTO {
private String id;
private String pass;
private String name;
private String regidate;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRegidate() {
return regidate;
}
public void setRegidate(String regidate) {
this.regidate = regidate;
}
}
- DAO(Data Access Object): DB의 데이터에 접근하기 위한 객체
1) 보통 JDBC를 통해 구현하며, 하나의 테이블에서 수행할 수 있는 CRUD를 전담한다.
2) CRUD에 해당하는 쿼리문을 실행한 후, 얻어온 결과를 DTO 객체에 담아 반환한다.
package membership;
import common.JDBConnect;
public class MemberDAO extends JDBConnect {
// 명시한 DB로의 연결이 완료된 MemberDAO 객체를 생성합니다.
public MemberDAO(String driver, String url, String id, String pw) {
super(driver, url, id, pw);
}
// 명시한 아이디/패스워드와 일치하는 회원 정보를 반환합니다.
public MemberDTO getMemberDTO(String uid, String upass) {
MemberDTO dto = new MemberDTO();
String query = "SELECT * FROM member WHERE id=? AND pass=?";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, uid);
psmt.setString(2, upass);
rs = psmt.executeQuery();
if (rs.next()) {
dto.setId(rs.getString("id"));
dto.setPass(rs.getString("pass"));
dto.setName(rs.getString(3));
dto.setRegidate(rs.getString(4));
}
} catch (Exception e) {
e.printStackTrace();
}
return dto;
}
}
→ 상속한 Java 클래스
package common;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.servlet.ServletContext;
public class JDBConnect {
public Connection con;
public Statement stmt;
public PreparedStatement psmt;
public ResultSet rs;
public JDBConnect() {
try {
Class.forName("oracle.jdbc.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:xe";
String id = "musthave";
String pwd = "1234";
con = DriverManager.getConnection(url, id, pwd);
System.out.println("DB 연결 성공(기본 생성자)");
} catch (Exception e) {
e.printStackTrace();
}
}
public JDBConnect(String driver, String url, String id, String pwd) {
try {
Class.forName(driver);
con = DriverManager.getConnection(url, id, pwd);
System.out.println("DB 연결 성공(인수 생성자 1)");
} catch (Exception e) {
e.printStackTrace();
}
}
public JDBConnect(ServletContext application) {
try {
String driver = application.getInitParameter("OracleDriver");
Class.forName(driver);
String url = application.getInitParameter("OracleURL");
String id = application.getInitParameter("OracleId");
String pwd = application.getInitParameter("OraclePwd");
con = DriverManager.getConnection(url, id, pwd);
System.out.println("DB 연결 성공(인수 생성자 2)");
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
try {
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
if (psmt != null)
psmt.close();
if (con != null)
con.close();
System.out.println("JDBC 자원 해제");
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 로그인 처리
<%@ page import="membership.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String userId = request.getParameter("user_id");
String userPwd = request.getParameter("user_pw");
String oracleDriver = application.getInitParameter("OracleDriver");
String oracleURL = application.getInitParameter("OracleURL");
String oracleId = application.getInitParameter("OracleId");
String oraclePwd = application.getInitParameter("OraclePwd");
MemberDAO dao = new MemberDAO(oracleDriver, oracleURL, oracleId, oraclePwd);
MemberDTO memberDTO = dao.getMemberDTO(userId, userPwd);
dao.close();
if (memberDTO.getId() != null) {
session.setAttribute("UserId", memberDTO.getId());
session.setAttribute("UserName", memberDTO.getName());
response.sendRedirect("LoginForm.jsp");
} else {
request.setAttribute("LoginErrMsg", "로그인 오류입니다.");
request.getRequestDispatcher("LoginForm.jsp").forward(request, response);
}
%>
- 로그아웃 처리
1) removeAttribute( ): 인수로 지정한 속성을 삭제한다.
2) invalidate( ): 세션 자체를 무효화한다.
→ session 영역의 모든 속성을 한번에 삭제하므로, 로그아웃 시에는 해당 메서드를 사용하는 것이 좋다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//방법 1: 회원인증정보 속성 삭제
/* session.removeAttribute("UserId");
session.removeAttribute("UserName"); */
//방법 2: 모든 속성 한번에 삭제
session.invalidate();
//속성 삭제 후 페이지 이동
response.sendRedirect("LoginForm.jsp");
%>
- 앞으로 사용할 공통 링크
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<table border="1" width="90%">
<tr>
<td align="center">
<% if(session.getAttribute("UserId") == null){ %>
<a href="../ch6/LoginForm.jsp">로그인</a>
<% } else { %>
<a href="../ch6/Logout.jsp">로그아웃</a>
<% } %>
<!-- 메뉴 사이의 공백 확보용 특수 문자 -->
<a href="../ch8/List.jsp">게시판(페이징X)</a>
<a href="../ch9/List.jsp">게시판(페이징O)</a>
</td>
</tr>
</table>
4. 쿠키 vs 세션
- 로그인은 쿠키보다는 세션을 이용해 구현하는 것이 좋다.
- 쿠키와 세션의 차이
쿠키 | 세션 | |
저장 위치 / 형식 | 클라이언트 PC에 text로 저장된다. | 웹 서버에 Object 타입으로 저장된다. |
보안 | 클라이언트에 저장되므로 보안에 취약하다. | 서버에 저장되므로 보안에 안전하다. |
자원 / 속도 | 서버 자원을 사용하지 않으므로 세션보다 빠르다. | 서버 자원을 사용하므로 쿠키보다 느리다. |
용량 | 용량의 제한이 있다. | 서버가 허용하는 한 제한이 없다. |
유지 시간 | 쿠키 생성 시 설정한다. → 설정된 시간이 경과되면 무조건 삭제된다. |
서버의 web.xml에서 설정한다. → 설정된 시간 내라도 동작이 있다면 삭제되지 않고 유지된다. |
'JSP > 성낙현의 JSP 자바 웹 프로그래밍' 카테고리의 다른 글
JSP, Oracle을 사용한 회원제 게시판(페이징 X) (0) | 2023.06.16 |
---|---|
액션 태그(Action Tag) (0) | 2023.06.13 |
데이터베이스(DB) (2) | 2023.06.07 |
쿠키(Cookie) (0) | 2023.06.04 |
내장 객체의 영역(Scope) (0) | 2023.05.30 |
댓글