로그인 기능 코드
login.jsp
<form action="/user/login" method="post">
<div class="d-flex flex-column justify-content-center align-items-center">
<div class="col-lg-6 col-md-6">
<input type="text" name="email" placeholder="이메일을 입력해주세요.">
</div>
<div class="col-lg-6 col-md-6">
<input type="password" name="password" placeholder="비밀번호를 입력해주세요.">
</div>
<div class="col-lg-12 text-center">
<button type="submit" class="site-btn">로그인</button>
</div>
</div>
</form>
UserController.java
package controller;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import model.User;
import service.UserService;
import java.io.IOException;
@WebServlet("/user/*")
public class UserController extends HttpServlet {
private UserService userService;
public UserController() {
userService = new UserService();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getPathInfo();
if ("/login".equals(action)) {
req.getRequestDispatcher("/view/user/login.jsp").forward(req, resp);
} else if ("/signup".equals(action)) {
req.getRequestDispatcher("/view/user/signup.jsp").forward(req, resp);
} else if ("/profile".equals(action)) {
User user = userService.getProfile(req.getParameter("username"));
req.setAttribute("user", user);
req.getRequestDispatcher("/view/user/profile.jsp").forward(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getPathInfo();
if ("/signup".equals(action)) {
User user = new User(
req.getParameter("email").replaceAll("/", ""),
req.getParameter("password"),
req.getParameter("name")
);
userService.signup(user);
resp.sendRedirect("/user/login");
} else if ("/login".equals(action)) {
User user = new User(
req.getParameter("email"),
req.getParameter("password")
);
boolean result = userService.login(user);
if (result) {
resp.sendRedirect("/");
req.getSession().setAttribute("isLogin", true);
req.getSession().setAttribute("userName", user.getEmail());
return;
}
resp.sendRedirect("/user/login");
}
}
}
SQL Injection
이메일을 입력하는 창에 이렇게 입력하면 비밀번호를 아무렇게나 입력해도 로그인이 된다.
'abcd' OR '1'='1' --
SELECT * FROM user WHERE email = 'abcd' OR '1'='1' -- AND password='qwer';
뒤의 조건 ('1'='1')이 무조건 참이기 때문에 이메일을 어떤 걸 입력해도 참이 된다.
-- 는 SQL 코드를 주석 처리 해주기 때문에 뒤의 AND password ~ 가 주석처리 된다.
이메일을 위에처럼 입력하게 되면 sql문 결과는 "SELECT * FROM USER" 와 같은 결과값이 나온다. = 모든 행이 조회된다.
조회된 결과가 있으니까 로그인 성공이라고 판단해서 로그인이 성공 처리가 된다.
ResultSet rs = conn.createStatement().executeQuery(sql);
if (rs.next()) {
return true;
}
return false;
SQL Injection 막는 법
1. 입력값 검증
사용자가 입력한 값에서 사용하면 안 되는 값이 있나 확인한다.
사용자 요청 받는 부분에 replace로 특수 문자들을 공백으로 바꾼다.
req.getParameter("email").replaceAll("[/\\\\\";:'*#-]", "");
2. 검증 로직 변경
사용자가 입력한 부분에서 이메일만 갖고온 다음에 if 문으로 비밀번호가 맞는지 확인
String sql = "SELECT * FROM user WHERE " + "email = '" + user.getEmail() + "'";
ResultSet rs = conn.createStatement().executeQuery(sql);
if(rs.getString("password").equals(user.getPassword())) {}
3. PreparedStatement로 SQL 실행 ⭐
sql을 문자열로 직접 편집하지 말고, 쓰고 싶은 sql이 있으면 빈 칸(물음표)으로 뚫어놓고 빈 칸에 값을 집어넣음
ResultSet을 바로 반환하는 게 아니라 PrepareStatement로 반환하고, 여기서 값을 넣고 세팅하기
String sql = "SELECT * FROM user WHERE email = ? AND password = ?";
try {
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, user.getEmail());
pstmt.setString(2, user.getPassword());
ResultSet rs = pstmt.executeQuery();
if(rs.next()) {
return true;
}
return false;
} catch {
//..
}
Statement vs PreparedStatment
Statement로 SQL 실행
- SQL을 실행할 때마다 SQL을 실행 과정을 거쳐서 실행
- 실행과정 : 파싱 -> 최적화 -> Row 소스 생성 -> 실행
- 간단한 쿼리에 적합
PreparedStatment로 SQL 실행
- 실행 과정을 미리 수행해두고 빈 칸에 값을 넣어서 실행
- 작업할 때 리소스를 더 많이 잡아먹고, Statement 보다 더 오래 걸린다.
- 실행 과정 : 파싱 -> 최적화 -> 미완성의 Row 소스 생성 -> Row 소스에 값 넣어서 완성 -> 실행
728x90
'BE > Java' 카테고리의 다른 글
[Java] DTO 설계 시 고려사항 (0) | 2025.01.10 |
---|---|
[Java] multipart/form-data란? / form 태그로 서버에 파일 전달하기 (0) | 2025.01.09 |
[Java] Servlet 프로젝트 구조 / 로그인, 회원가입 기능 구현 (0) | 2025.01.08 |
[Java] IntelliJ + MariaDB 연동, SQL 실행 (0) | 2025.01.08 |
[Java] IntelliJ + Tomcat 연동, Servlet 설정 (파라미터) (0) | 2025.01.08 |