
login.html페이지에 DB를 연동하여
DB에 저장된 정보이면 로그인 성공,
DB에 저장되지 않은 정보이면 로그인 실패
- 로그인 폼을
login.php에 POST방식으로 전송!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Page</title>
<script src="https://kit.fontawesome.com/242c7614be.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="./css/login.css">
</head>
<body>
<div class="login">
<div class="login__forms">
<!-- login form -->
<form action="./php/login.php" method="POST" class="login__register block" id="login-in">
<h1 class="login__title">Sign In</h1>
<div class="login__box">
<i class="fas fa-user login__icon"></i>
<input type="text" placeholder="Username" class="login__input" name="username" required>
</div>
<div class="login__box">
<i class="fas fa-lock login__icon"></i>
<input type="password" placeholder="Password" class="login__input" name="password" required>
</div>
<a href="#" class="login__forgot">Forgot Password?</a>
<button type="submit" class="login__button">Sign In</button>
<div>
<span class="login__account login__account--account">Don't Have an Account?</span>
<span class="login__signin login__signin--signup" id="sign-up">Sign Up</span>
</div>
</form>
<!-- create account form -->
<form action="./php/signUp2.php" method="POST" class="login__create none" id="login-up"> <h1 class="login__title">Create Account</h1>
<div class="login__box">
<i class="fas fa-user login__icon"></i>
<input type="text" placeholder="Username" class="login__input" name="username" required>
</div>
<div class="login__box">
<i class="fa-solid fa-at login__icon"></i>
<input type="email" placeholder="Email" class="login__input" name="email" required>
</div>
<div class="login__box">
<i class="fas fa-lock login__icon"></i>
<input type="password" placeholder="Password" class="login__input" name="password" required>
</div>
<button type="submit" class="login__button">Sign Up</button>
<div>
<span class="login__account login__account--account">Already have an Account?</span>
<span class="login__signup login__signup--signup" id="sign-in">Sign In</span>
</div>
<div class="login__social">
<a href="#" class="login__social--icon"><i class="fab fa-facebook-f"></i></a>
<a href="#" class="login__social--icon"><i class="fab fa-x-twitter"></i></a>
<a href="#" class="login__social--icon"><i class="fab fa-google"></i></a>
<a href="#" class="login__social--icon"><i class="fab fa-github"></i></a>
</div>
</form>
</div>
</div>
<script src="./js/login.js"></script>
</body>
</html>
( 1 ) DB 접속
( 2 )login.html의 로그인 폼으로터 데이터 받아오기
( 3 )Prepared Statment를 사용하여 쿼리 틀을 DB에 전달하여 준비// 사용자가 입력한 id를 기준으로 user_info 테이블에서 해당 유저 정보 찾음 $sql = "SELECT * FROM user_info WHERE id = ?"; $stmt = mysqli_prepare($db_conn, $sql);( 4 ) 값을 바인딩 (사용자가 입력한 username을
?자리에 바인딩)mysqli_stmt_bind_param($stmt,"s", $username);( 5 ) 바인딩한 쿼리를 실행 (
?자리에 유저가 입력한 username을 넣어서 쿼리를 실행)mysqli_stmt_execute($stmt);( 6 ) DB 서버로부터 위의 쿼리 조건에 부합되는 결과 테이블 받아오기
(위의 쿼리 조건에 부합되는 데이터만 DB서버에서 가져옴)$result = mysqli_stmt_get_result($stmt);( 7 ) 사용자가
login.html에서 입력한 username과 비밀번호를 검사해서,
→ 맞으면loginSuccess.php로 이동
→ 틀리면 로그인 실패 메시지를 띄우기
➡️while을 사용한 경우// 사용자가 입력한 username을 가진 row를 찾기 위해 while문을 통해 반복 // (위의 쿼리 조건에 부합한) 결과테이블의 모든 row를 읽어서 // 사용자가 입력한 username과 일치한 row 찾는다! ///쿼리 조건에 해당되는 데이터들(레코드들) 중 위부터 순차적으로 꺼냄 while($row=mysqli_fetch_assoc($result)){ if(password_verify($pw,$row['pw'])){ //각 레코드(row)마다 사용자가 입력한 pw와 레코드의 pw가 일치한지 확인 //로그인 성공시 -> username 포함해서 success.php로 이동 header("Location: loginSuccess.php?username=" . urlencode($row['username'])); exit(); //스크립트 종료 } } // 로그인 실패 알림창 띄우고 login.html로 리다이렉션 echo "<script>alert('로그인 정보가 일치하지 않습니다.'); window.location.href='login.html';</script>"; }➡️
if를 사용한 경우 (✔️)// 나는 db에서 username을 unique로 설정해서 결과가 0개 또는 1개임. // 즉, username이 중복 되지 않는다. // 그래서 while문 보다는 if문을 쓰는게 더 효율적이라고 생각했다. // 👉 username이 DB에 존재하면 → row 1개만 반환됨 // 👉 그 1개 row에서 password 확인 // 👉 맞으면 → 로그인 성공 // 👉 틀리면 → 실패 메시지 출력 $row = mysqli_fetch_assoc($result); // 10. 사용자 존재 + 비밀번호 일치하는지 확인 if($row && password_verify($pw, $row['pw'])){ header("Location: loginSuccess.php?username=" . urlencode($row['username'])); exit(); }else{ // 로그인 실패 echo "<script>alert('로그인 정보가 일치하지 않습니다.'); window.location.href='/project-folder/login.html';</script>"; } // 11. sql 쿼리 종료 mysqli_stmt_close($stmt);
( 8 ) DB 연결 종료//DB 연결 종료 mysqli_close($db_conn);💡
mysqli_stmt_get_result()
- 이 함수는 결과 테이블을 가져옴
result = mysqli_stmt_get_result(stmt);에서
stmt는 execute()한 후의 Prepared Statement 객체.- 이 함수는 $stmt로부터 결과를 가져와서
→ mysqli_fetch_assoc() 같은 함수로 다룰 수 있는 일반적인 결과 객체로 바꿔줌
💡mysqli_fetch_assoc()- 결과에서 한 행(row)을 연관 배열(associative array)로 가져옴
$user['id'],$user['pw'],$user['username']처럼 사용할 수 있음
한 번 실행하면 다음 행으로 넘어감 (루프에서 여러 행 읽을 수 있음)
⬇️ login.php 전체 코드
<?php
// 1. DB 접속하기
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'admin');
define('DB_PASSWORD', 'student1234');
define('DB_NAME', 'mywebsite');
$db_conn = mysqli_connect(DB_SERVER, DB_USERNAME,DB_PASSWORD, DB_NAME);
// 2. DB접속 확인하기
if(!$db_conn){
echo "DB Connect Fail!<br>";
echo "에러 원인: " . mysqli_connect_error();
exit();
}
// 3. 로그인 폼의 각 데이터를 받아오기
$username = $_POST['username'];
$pw = $_POST['password'];
// < Prepared Statment 사용>
// 4. sql 쿼리 준비하기
$sql = "select * from user_info where username = ?";
$stmt = mysqli_prepare($db_conn, $sql);
if($stmt){
// 6. 값 바인딩하기
mysqli_stmt_bind_param($stmt, "s", $username);
//7. 바인딩 마친 sql쿼리를 실제로 실행하기
mysqli_stmt_execute($stmt);
// 8. DB로부터 sql쿼리조건에 부합한 결과 테이블 받아오기
$result = mysqli_stmt_get_result($stmt);
//9. 받아온 결과 테이블에서 하나의 행을 가져옴.
//나는 db에서 username을 unique로 설정해서 결과가 0개 또는 1개임.
//즉, username이 중복 X
$row = mysqli_fetch_assoc($result);
// 10. 사용자 존재 + 비밀번호 일치하는지 확인
if($row && password_verify($pw, $row['pw'])){
header("Location: loginSuccess.php?username=" . urlencode($row['username']));
exit();
}else{
// 로그인 실패
echo "<script>alert('로그인 정보가 일치하지 않습니다.'); window.location.href='/project-folder/login.html';</script>";
}
// 11. sql 쿼리 종료
mysqli_stmt_close($stmt);
}
else{
//쿼리 준비 실패 시, 출력됨.
echo "쿼리 준비 실패: " . mysqli_error($db_conn);
}
// 12. DB 연결 종료
mysqli_close($db_conn);
?>
💡 SELECT * FROM user_info WHERE username = ?에서
where 조건에 id만 적은 이유
id를UNIQUE,NOT NULL로 설정했기 때문에
WHERE id = ?하나만 써도 로그인 조건으로 충분하다
(id는 중복되지 않아서 고유하고, NULL값이 아니므로 해당되는 레코드를 찾는데 적합하다 )
GET방식으로 받은 username을 화면을 출력!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Success!</title>
<style>
.container{
display:grid;
place-items:center;
height: 100vh;
padding: 1.5rem;
}
.contents{
width:100%;
max-width:348px;
background-color:#f2f2f2;
padding:2rem 1rem;
border-radius:1rem;
text-align:center;
box-shadow: 0 8px 20px rgba(35, 0, 77, 0.2);
}
.welcome,.username{
font-weight: 600;
font-size:1.5rem;
}
</style>
</head>
<body>
<div class="container">
<div class="contents">
<div class="welcome">Welcome !</div>
<div class="username"><?php echo $_GET['username'];?></div>
</div>
</div>
</body>
</html>
- 현재
user_info테이블
① ID는
user01, PW는user01user01로 로그인 시도
② 로그인 성공 →
user01이라는 username으로 출력됨
①
user_info테이블에 존재하지 않는 ID와 PW로 로그인 시도
② 로그인 실패
→ 로그인 정보가 일치하지 않습니다 라는 알림창 뜸
→login.html로 리다이렉트