모의해킹에 사용할 게시판 로그인 구현
로그인을 요청하면 login.js의 form.addEventlistener()
함수가 호출된다.
fetch 함수로 loginprocess
컨트롤러에 계정 정보를 전달한다.
const form = document.getElementById("login-form");
form.addEventListener("submit", (event) => {
event.preventDefault();
const formData = new FormData(form);
const username = formData.get("user_id");
const password = formData.get("user_pw");
fetch("/hackthebox/loginprocess", {
method: "POST",
headers: [["Content-Type", "application/json; charset=utf-8"]],
body: JSON.stringify({
user_id: username,
user_pw: password,
}),
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((result) => {
if (result.login === "success") {
alert("로그인에 성공했습니다.");
location.href = "/hackthebox/community";
} else if (result.login === "fail") {
alert("로그인에 실패했습니다. 아이디 또는 패스워드를 확인해주세요.");
location.href = "/hackthebox/api/login.jsp";
}
})
.catch((error) => {
console.error(error);
alert("로그인 중 오류가 발생했습니다. 다시 시도해주세요.");
});
});
회원가입하면 로그인도 함께 요청한다. singupDTO
값이 null
이면 로그인 파라미터 데이터를 userId, userPwd 변수에 저장한다. 그렇지 않다면 회원가입 파라미터 데이터를 저장한다.
@WebServlet("/loginprocess")
public class UserLoginController extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userId;
String userPwd;
JSONObject json;
UserDTO singupDTO = (UserDTO) req.getAttribute("vo"); // 회원가입 DTO
if (singupDTO != null) {
// 회원가입 요청 시 받는 파라미터
userId = singupDTO.getUser_id();
userPwd = singupDTO.getPassword();
} else {
// JSON parsing
BufferedReader br = req.getReader();
StringBuilder sb = new StringBuilder(); // append 하기위해 StringBuilder 사용
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
// 로그인 요청 시 받는 파라미터
json = new JSONObject(sb.toString());
userId = json.getString("user_id");
userPwd = json.getString("user_pw");
}
UserDTO loginDTO = new UserDTO();
loginDTO.setUser_id(userId);
loginDTO.setPassword(userPwd);
UserDAO의 UserSelect 메서드로 아이디와 패스워드를 인증 후, 인증에 성공하면 세션을 생성한다.
// TODO: username과 password를 검증하는 코드 작성
UserDAO dao = new UserDAO();
UserDTO dto = dao.UserSelect(loginDTO);
if (dto.getUser_id() != null) {
if (singupDTO != null) {
// 회원가입 성공
json = new JSONObject();
json.put("signup", "success");
// 세션 생성
HttpSession session = req.getSession();
session.setAttribute("UserId", dto.getUser_id());
session.setAttribute("UserName", dto.getName());
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
// JSON
PrintWriter out = resp.getWriter();
out.print(json.toString());
out.flush();
} else {
// 로그인 성공
json = new JSONObject();
json.put("login", "success");
// 세션 생성
HttpSession session = req.getSession();
session.setAttribute("UserId", dto.getUser_id());
session.setAttribute("UserName", dto.getName());
// response
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
// JSON
PrintWriter out = resp.getWriter();
out.print(json.toString());
out.flush();
}
} else {
// 로그인 실패
json = new JSONObject();
json.put("login", "fail");
// JSON response
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
out.print(json.toString());
out.flush();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/hackthebox/login");
}
}
UserDAO의 UserSelect 메소드에서 로그인을 처리한다. SQL 인젝션을 대응하기 위해 prepareStatement
를 적용했다.
public UserDTO UserSelect(UserDTO dto) {
UserDTO result = new UserDTO();
String query = "SELECT * FROM users WHERE user_id=? AND password=?";
conn = driver.getConnect();
try {
psmt = conn.prepareStatement(query);
psmt.setString(1, dto.getUser_id());
psmt.setString(2, dto.getPassword());
rs = psmt.executeQuery();
if (rs.next()) {
result.setUser_id(rs.getString("user_id"));
result.setName(rs.getString("name"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
driver.dbClose(rs, stmt, conn);
}
return result;
}
로그아웃을 요청하면 세션의 모든 속성을 삭제한 뒤, 인덱스 페이지로 이동한다.
@WebServlet("/logout")
public class UserLogoutController extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
// 모든 속성 한꺼번에 삭제
session.invalidate();
// 속성 삭제 후 페이지 이동
RequestDispatcher requestDispatcher = req.getRequestDispatcher("index.jsp");
requestDispatcher.forward(req, resp);
}
}