2023.04.03 - [웹 모의해킹 공부/과제] - [Web] 로그인 기능 구현 001 (회원가입 페이지 구현)
2023.04.03 - [웹 모의해킹 공부/과제] - [Web] 로그인 기능 구현 002 (로그인 & 로그아웃 구현)
[Web] 로그인 기능 구현 001 (회원가입 페이지 구현)
리눅스 웹서버에 로그인 페이지 구현!! - 사용 OS Ubuntu-22.04.2-desktop-amd64.iso LTS - 사용 프로그램 Apache2 : Apache/2.4.52 (Ubuntu) PHP : PHP 8.1.2-1ubuntu2.11(cli) MySQL : mysql Ver 8.0.32-0ubuntu0.22.04.2 for Linux on x86_64 ((Ubu
jisu069.tistory.com
과제가 나오기 전에 연습으로 구현해 본 회원가입 페이지와 로그인 페이지를 수정하여 다시 구현해 봤습니다!!
구현에 사용된 프로그램
- Ubuntu-22.04.2
- Apache2 : Apache/2.4.52 (Ubuntu)
- PHP : PHP 8.1.2-1ubuntu2.11(cli)
- MySQL : mysql Ver 8.0.32-0ubuntu0.22.04.2 for Linux on x86_64 ((Ubuntu))
- phpmyadmin
- Visual Code(Widnows11)
00. MySQL을 이용하여 사용자 정보 DB 구현
00-1) 프로젝트에 사용될 Database 구현(DB : WebDB)
# mysql -u admin -p
mysql> create database WebDB;
Query Ok, 1 row affected (0.00 sec)
mysql> use WebDB;
Database changed
- CREATE DATABASE DB_이름; : 데이터 베이스 생성
- USE DB_명; : DB_명 데이터 베이스를 사용
00-2) 사용자의 정보를 저장할 테이블을 구현(Table : userTB)
- 사용자의 회원번호, ID, PW, 이름, 주소, 전화번호, 이메일, 회원가입일을 저장할 테이블 생성
- 사용자의 회원번호는 관리자가 관리하기 위한 기본키로 작성한다
- 모든 정보는 작성이 되어야 하므로 NOT NULL로 정의
create table userTB(
userIdx int primary key auto_increment, <- 사용자 고유 회원번호
userId varchar(100) unique not null,
userPw varchar(200) not null,
userName varchar(100) not null,
userAddress varchar(200) not null
userPhone varchar(20) not null,
userEmail varchar(100) not null,
userDate date not null <- 사용자 회원 가입일
);
- CREATE TABLE TABLE_명( 컬럼명 데이터타입 조건, ... ); : 테이블 생성
- PRIMARY KEY : 기본키 설정(고유한 키값)
- UNIQUE : 유일한 컬럼명을 가진다(중복X)
01. URL을 입력했을 때 나올 기본 페이지 구현(로그인 페이지)
01-1) 로그인 기능을 구현하기 때문에 index.html을 로그인 페이지로 구현
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Page</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="./css/shared.css">
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<header>
<a href="index.html" id="logo">Wlkate</a>
<nav>
<ul>
<li><a href="#">Board</a></li>
<li><a href="index.html">Login</a></li>
</ul>
</nav>
</header>
<main class="wrap" id="login_wrap">
<h1>Login</h1>
<section>
<form action="login_ok.php" name="login_form" method="POST" class="form" id="login_form">
<p>
<input type="text" name="userId" id="user_id" placeholder="ID"/>
</p>
<p>
<input type="password" name="userPw" id="user_pw" placeholder="Passwrod"/>
</p>
<p id="forget_pw"><a href="#"> Forget Password?</a></p>
<p>
<input type="submit" value="Sing in" id="login_btn" class="form_btn">
</p>
</form>
<p id="join_btn"> Not a Member? <a href="join.html">Sing up!</a></p>
</section>
</main>
<footer></footer>
</body>
</html>
이 전에 작성한 index.html와 다른 점은 html 구조, css 정도만 수정했습니다
- 해더 바에는 index.html로 돌아오는 로고와, 추 후 작성할 게시판으로 가는 버튼을 구현했습니다
- 비밀번호 찾는 기능은 사용자의 인증을 어떻게 해야 할지 몰라서 아직 구현하지 않았습니다
02. 회원가입 페이지 구현
02-1) 로그인 기능을 구현하기 위해서는 계정이 필요하고 계정을 생성하는 페이지 구현
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sing Up Page</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="./css/shared.css">
<link rel="stylesheet" href="./css/join.css">
</head>
<body>
<header>
<a href="join.html" id="logo">Wlkate</a>
<nav>
<ul>
<li><a href="#">Board</a></li>
<li><a href="index.html">Login</a></li>
</ul>
</nav>
</header>
<main class="wrap" id="join_wrap">
<h1>Sing Up</h1>
<section>
<form action="join_ok.php" name="joinForm" method="POST" class="form" id="login_form" onsubmit="return sendIt()">
<p>
<input type="text" name="userName" id="user_name" placeholder="Name">
</p>
<p>
<input type="text" name="userId" id="user_id" placeholder="ID">
<input type="button" id="check_id_btn" value="check" onclick="checkId()">
<p id="result"> </p>
</p>
<p>
<input type="password" name="userPw" id="user_pw" placeholder="Password">
</p>
<p>
<input type="password" name="userPwCheck" id="userpw_ch" placeholder="Password Check">
</p>
<p>
<input type="text" name="userAddress" id="user_address" placeholder="Address" >
<input type="button" id="addr_search_btn" value="Search" onclick="addrSearch()">
</p>
<p>
<input type="text" name="userPhone" id="user_phone" placeholder="Phone Number 000-0000-0000">
</p>
<p>
<input type="text" name="userEmail" id="usere_mail" placeholder="E-mail">
</p>
<p>
<input type="submit" value="Sin Up" class="form_btn">
</p>
<p class="pre_btn">Are you join? <a href="index.html">Login.</a></p>
</form>
</section>
</main>
<footer></footer>
<script src="./js/join.js"></script>
</body>
</html>
- sendIt() : 회원가입 형식을 체크해 주는 함수
- checkId() : 사용자의 아이디 중복을 체크해주는 함수
- addrSearc() : 주소 DB를 통해서 사용자가 주소를 검색을 하는 함수
02-2) 회원가입에 사용될 함수들을 선언할 js파일 생성
let idCheck = 0;
const sendIt = () => { // 회원가입 형식 체크하고 전송하는 함수
const userName = document.joinForm.userName;
const userId = document.joinForm.userId;
const userPw = document.joinForm.userPw;
const userPwCheck = document.joinForm.userpwcheck;
const userAddr = document.joinForm.userAddress;
const userPhone = document.joinForm.userPhone;
const userEmail = document.joinForm.userEmail;
const expNameText = /[가-힣-A-Za-z]+$/;
const expHpText = /^\d{3}-\d{3,4}-\d{4}$/;
const expEmailText = /^[A-Za-z0-9\.\-]+@[A-Za-z0-9\.\-]+\.[A-Za-z0-9\.\-]+$/;
if(userName.value == ''){
alert("Please enter your Name!!!");
userName.focus();
return false;
}
if(!expNameText.test(userName.value)){
alert("The format of the name is incorrect. Please enter in the correct format!!");
userName.focus();
return false;
}
if(idCheck == 0){
alert("Please check ID duplicate!!")
userId.focus();
return false;
}
if(userPw.value == ''){
alert("Please enter your Password!!!");
userPw.focus();
return false;
}
if(userPwCheck.value == '') {
alert('Please enter password confirmation!!!');
userPwCheck.focus();
return false;
}
if(userPw.value.length < 6 || userPw.value.length > 20){
alert("Please enter a password between 6 and 20!!!");
userPw.focus();
return false;
}
if(userPw.value != userPwCheck.value) {
alert('Your password is different. Please enter again!!!');
userPwCheck.focus();
return false;
}
if(!expHpText.test(userPhone.value)) {
alert('The cell phone number format is incorrect. Please enter in the correct format!!');
userPhone.focus();
return false;
}
if(userEmail.value == '') {
alert('Please enter your E-Mail!!!');
userEmail.focus();
return false;
}
if(!expEmailText.test(userEmail.value)) {
alert('Please check the format your E-mail.');
userEmail.focus();
return false;
}
if(userAddr.value == ''){
alert('Please enter your Address!!');
userAddr.focus();
return false;
}
return true;
}
const checkId = () => { // 사용자 아이디 중복 체크
const userId = document.joinForm.userId;
const result = document.querySelector('#result');
if(userId.value == ''){
alert("Please enter your ID!!!");
userId.focus();
return false;
}
if(userId.value.length < 4 || userId.value.length > 12){
alert("Please enter your ID between 4 and 12 characters!!!");
userId.focus();
return false;
}
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () =>{
if(xhr.readyState == XMLHttpRequest.DONE){
if(xhr.status == 200){
let txt = xhr.responseText.trim();
if(txt == "O") {
idCheck = 1;
result.style.display = "block";
result.style.color = "green";
result.innerHTML =" The ID can be used!!";
} else {
result.style.display = "block";
result.style.color = "red";
result.innerHTML = " This is a duplicate ID!!";
userId.focus();
userId.addEventListener("keydown", function(){
result.style.display = "none";
});
}
}
}
}
xhr.open("GET", "checkid_ok.php?userId="+userId.value, true);
xhr.send();
}
const addrSearch = () =>{
// 구현 예정
}
- idCheck : 아이디 중복체크 결과를 저장할 전역변수 (checkId() 함수에서 체크한 결과를 저장하여 sendIt()에서 사용)
- sendIt()
- 회원가입 형식이 다를 경우 경고와 다른 곳의 위치를 포커스
- 아이디 중복체크를 하지 않을 경우 회원가입을 하지 못하게 업데이트
- checkId()
- AJAX를 사용하여 페이지 새로고침하지 않고 checkid_ok.php 화면에 출력될 결과를 가져온다
- WebState(checkid_ok.php)가 성공할 경우 결과를 비교한다
- 계정이 중복되지 않을 경우 전역변수 idCheck를 1로 선언해 주고 회원가입 페이지에 가입가능한 아이디라고 출력
- 계정이 중복되었을 경우 idCheck를 0으로 그대로 두고 아이디가 중복되었다고 출력
- addrSearch()
- 주소를 검색할 수 있는 기능으로 아직 구현하지 못했습니다
02-3) 아이디 중복을 체크할 php 구현
<?php
include('./connect.php');
//if($con) echo "ok\n";
$userId = $_GET['userId'];
$sql = "select * from userTB where userId='$userId'";
$rst = mysqli_query($con, $sql);
$arr = mysqli_fetch_array($rst);
echo isset($arr['userIdx']) ? "X" : "O";
?>
- 사용자가 입력한 userId를 select문으로 DB table에 검색하여 확인한다
- userId를 통해 userIdx가 설정되어 있는지 확인한다
- 설정이 되어 있을 경우 X를 페이지에 출력 (사용자 ID가 중복되었으므로 X 출력)
- 설정이 안 되어 있을 경우 O를 페이지에 출력 (사용자 ID가 설정 안 되어있어서 O 출력)
02-4) 회원가입을 확인할 php 구현
<?php
include('./connect.php');
// if($con) echo "OK\n";
// else echo "Fail\n";
$userName = $_POST['userName'];
$userId = $_POST['userId'];
$userPw = $_POST['userPw'];
$userAddr = $_POST['userAddress'];
$userPhone = $_POST['userPhone'];
$userEmail = $_POST['userEmail'];
$userDate = date('Y-m-d H:i:s');
$salt = '$5$QOPrAVIK'."$userId".'$';
$hashPw = crypt($userPw, $salt);
$sql = " INSERT INTO userTB
(userId, userPw, userName, userAddress, userPhone, userEmail, userDate)
VALUES('$userId', '$hashPw', '$userName', '$userAddr', '$userPhone','$userEmail','$userDate')
";
$rst = mysqli_query($con, $sql);
if($rst){
echo"
<script>
alert(\"Member registration complete!!\");
location.href = \"./index.html\";
</script>
";
}else{
echo "
<script>
alert(\"Member registration Fail!!!\");
history.back();
</script>
";
exit;
}
?>
- crpyt()를 통해서 사용자 비밀번호를 해시 함수를 이용해 암호화시켜 DB Table에 저장한다
- 로그인을 위해 salt값을 가지고 있는다
- date()를 사용하여 사용자가 회원가입을 하는 시간을 저장한다
- Insert문이 성공하면 회원가입 성공 alert()로 출력하고 로그인페이지로 이동시킨다
- insert문이 실패하면 회원가입 실패 alert()로 출력하고 이전(회원가입) 페이지로 이동시킨다
![]() |
![]() |
![]() |
![]() |
03. 사용된 css 파일
03-1) shared.css(페이지들에 공통적으로 사용되는 css)
/* ========== Page Common ========== */
*{
margin: 0;
padding: 0;
font-family: 'Roboto', sans-serif;
}
body{
width: 100%;
margin: 0 auto;
background-color: rgb(59,65,64);
}
h1{
font-size: 30px;
margin-bottom: 4rem;
}
ul{
list-style: none;
}
a{
text-decoration: none;
}
/* ========== Header ========== */
header{
top: 0;
width: 90%;
height: 5rem;
display: flex;
justify-content: space-between;
align-items: center;
position: fixed;
background-color: rgb(29,26,24);
padding: 0 6rem;
}
header ul{
display: flex;
margin: 0;
padding: 0;
}
header li{
margin: 0 1rem;
}
header nav a{
color: rgb(185,131,31);
font-size: 1.25rem;
}
header nav a:hover{
color: rgb(185,131,44);
}
#logo{
font-size: 1.5rem;
font-weight: bold;
color: rgb(238,164,80);
text-transform: uppercase;
}
/* ========== Main ==========*/
.wrap{
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
input:not(input[type="submit"]){
border: 1px solid rgb(211, 203, 203);
width: 25rem;
height: 3.2rem;
margin: 5px;
padding-left: 10px;
border-radius: 5px;
box-sizing: border-box;
font-size: 18px;
}
.wrap .form_btn{
width: 25rem;
height: 3.2rem;
margin: 5px;
border-radius: 5px;
border: 1px solid rgb(238,164,0 );
background-color: rgb(238,164,0 );
color: rgb(255,255,255);
font-weight: bold;
font-size: 18px;
cursor: pointer;
}
03-2) index.css(로그인 페이지에만 사용되는 css)
/* ========== Page Common ========== */
html{
width: 100%;
height: 100%;
display: flex;
}
/* ========== Main ========== */
#login_wrap{
width: 31.2rem;
height: 41rem;
margin: 10rem auto;
background-color: rgb(255, 255, 255);
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), 0 6px 4px rgba(0, 0, 0, 0.2);
}
section{
padding: 4rem 0;
}
input:not(input[type="submit"]){
border: 1px solid rgb(211, 203, 203);
width: 25rem;
height: 3.2rem;
margin: 5px;
padding-left: 10px;
border-radius: 5px;
box-sizing: border-box;
font-size: 18px;
}
#forget_pw{
padding: 0.5rem;
}
#join_btn a,
#forget_pw a{
color: rgb(238,164,0);
}
03-3) join.css (회원가입페이지에만 사용되는 css)
/* ========== Page Common ========== */
h1{
margin-bottom: 1rem;
}
/* ========== Header ========== */
header{
padding: 0 5rem;
}
/* ========== Main ==========*/
#join_wrap{
width: 31.2rem;
height: 45rem;
margin: 10rem auto;
background-color: rgb(255, 255, 255);
}
#check_id_btn,
#addr_search_btn {
position: relative;
top: -2px;
width: 50px;
margin-left: 0;
padding-left: 0;
border: 0;
box-sizing:content-box;
background-color: rgb(238,164,0);
font-size: 12px;
font-weight: bold;
color: rgb(255, 255, 255);
cursor: pointer;
}
#join_wrap #join_form #result {
display: none;
}
.pre_btn a{
color:rgb(238,164,0);
}
※ DB Connect php !!
<?php
$con = mysqli_connect('localhost', 'DB_ID', 'DB_PW','DB_Name') or die('Database Connect Fail!!!!');
//if($con) echo "OK\n";
//else echo "Fail\n";
?>
- $변수 = mysqli_connect('주소', 'DB아이디', 'DB비밀번호', 'DB명(Table아님!!!)') or die('에러 메시지');
- or die() : 메시지를 출력하고 현재 스크립트를 종료하는 함수
'모의해킹 공부 > WEB 개발' 카테고리의 다른 글
[4주차 과제-1] 회원가입 - 주소 검색 기능 구현 (0) | 2023.04.26 |
---|---|
[2주차 과제 -2] 로그인 & 메인 페이지 구현 (0) | 2023.04.08 |
[1주차 과제-3] DB연결 (0) | 2023.04.01 |
[1주차 과제-2] Happy Hacking & GET / POST Method (0) | 2023.04.01 |
[1주차 과제 -1] 리눅스 환경에 APM환경 세팅하기 (0) | 2023.04.01 |