오늘은 로그인 로직에 대해 알아보도록 하겠습니다
로그인이란 무엇일까요?
로그인은 본인 확인 작업입니다
그렇다면 본인 확인을 하기 위해 어떤 과정이 필요할까요?
먼저, 이 사람이 누구인지 알아야 합니다
이것을 식별
이라고 합니다
그리고 이 사람이 정말 그 사람인지 알아야 합니다
이 과정은 인증
이라고 합니다
식별과 인증이 무엇인지 이해하셨나요?
예를 들어 볼게요
A라는 사람이 공항에서 출국을 하는 상황입니다
A씨는 여권을 가지고 공항으로 가서 출국심사를 하겠죠?
요즘은 공항에 가면 대부분 기계로 자동출입국심사를 진행합니다
자동출입국심사는 2개의 과정을 거치게 되어 있습니다
여권 인식
얼굴 및 지문 인식
먼저 A씨는 자동출입국심사 기계 앞에 가서 여권을 기계에 가져다 댑니다
그럼 기계는 “아 A라는 사람이 출국을 하려고 하는구나!” 라는 사실을 알 수 있습니다
그런데 여기서 심사가 끝이라면 어떤 일이 벌어질까요?
만약 B라는 사람이 A씨의 여권을 몰래 훔쳐 A씨인척하고 출국을 시도하더라도, 걸리지 않고 통과하게 되는 상황이 발생합니다
이런 상황이 일어나지 않도록 하려면, A씨의 여권을 가지고 출국을 하려는 사람이 정말 A씨가 맞는지 확인해야 합니다
이 확인을 위해 심사 기계는 얼굴 및 지문 인식을 진행하고, 정말로 A씨임을 확인합니다
그럼 여기서, 무엇이 식별이고 무엇이 인증일까요?
바로 여권 인식이 식별, 얼굴 및 지문 인식이 인증입니다
여권 인식을 통해 누구인지 알고, 얼굴 및 지문 인식을 통해 정말 그 사람 본인인지 확인했기 때문입니다
바로 아이디 입니다
아이디를 통해 서비스에 접근하려는 사람이 누구인지 알게 됩니다
식별은 이처럼 수많은 데이터에서 특정 데이터를 찾아내는 작업입니다
이 식별 데이터가 중복된다면 어떻게 될까요?
예를 들어 이름만으로 한 사람을 찾아내야 하는 상황에서 동명이인이 존재하는 상황이면 그 사람을 제대로 찾아낼 수 있을까요?
그럴 수 없습니다. 여기서 우리는 식별을 위한 데이터는 고유(unique)해야 한다는 사실을 알 수 있습니다
그렇기 때문에 로그인에서 아이디는 중복될 수 없는 것입니다
우리는 아이디가 중복되지 않도록 회원가입 구현 시 아이디를 primary key로 설정할 수 있습니다
로그인에서의 인증은 무엇인지 감이 오시죠?
바로 비밀번호 입니다
꼭 비밀번호가 아니더라도 OTP, 지문 인식 등이 로그인에서의 인증이 될 수 있습니다
인증은 본인이 맞다는 것을 증명하는 과정이기 때문에, 인증 데이터는 절대 노출되어서는 안 됩니다
식별 / 인증 동시는 식별과 인증을 동시에 진행하는 로직입니다
늘 로그인 할 때 아이디와 비밀번호를 함께 입력한 후 로그인한다고 생각하실 수 있지만,
지금 얘기하는 것은 내부적인 로직 구조를 의미합니다
아이디와 비밀번호를 입력받으면 우리는 내부적으로 그것이 DB에 있는 데이터와 일치하는 지 확인하는 과정을 거치게 됩니다
이 때 하나의 쿼리문에서 아이디와 비밀번호의 일치여부를 한번에 확인하는 것을 식별 / 인증 동시 로직이라고 합니다
예문을 볼까요?
//아이디, 비밀번호 변수에 저장
$userid = $_POST['userid'];
$password = $_POST['password'];
//식별 및 인증 진행
$sql = "SELECT * FROM account WHERE username == ".$userid." AND password ==".$password.";";
$result = mysqli_query($DB_conn, $sql);
if ($result) {
//로그인 성공
} else {
//로그인 실패
}
위와 같이 아이디(식별)와 비밀번호(인증)를 동시에 확인하는 것을 식별 / 인증 동시라고 합니다
식별 / 인증 분리는 아이디와 비밀번호 확인을 내부적으로 분리하여 진행하는 로직입니다
먼저, 아이디가 DB에 존재하는 지 확인 후 (인증 후),
아이디가 존재한다면 그 아이디에 해당하는 비밀번호를 DB에서 가져와 사용자가 입력한 비밀번호와 일치하는 지 확인(식별)하는 것입니다
예문을 볼까요?
//아이디, 비밀번호 변수에 저장
$userid = $_POST['userid'];
$password = $_POST['password'];
//식별 진행
$sql = "SELECT * FROM account WHERE username == ".$userid.";";
$result = mysqli_query($DB_conn, $sql);
$row = mysqli_fetch_array($result);
if ($row[0] != "") {
//아이디가 있는 경우 인증 진행
$sql_pw = ""SELECT * FROM account WHERE username='".$username."' and password = '".$password."';";
$result_pw = mysqli_query($DB_conn, $sql_pw);
$row_pw = mysqli_fetch_array($result_pw);
if($row_pw[0]!="") {
//로그인 성공
} else {
//로그인 실패
}
} else {
//로그인 실패
}
위와 같이 아이디를 먼저 확인한 후(식별), 아이디에 해당하는 비밀번호와 사용자가 입력한 비밀번호가 일치하는 지 확인하는 것(인증)을 식별 / 인증 분리라고 합니다
💡 HASH란?
해시는 임의의 길이의 데이터를 입력 받아 고정된 길이의 값을 출력하는 함수입니다
해시함수는 일방향 함수입니다
즉, 해시함수가 출력한 값을 이용해 다시 역으로 원래 데이터 값을 구할 수 없습니다
또한 해시함수는 입력한 값이 조금만 다르더라도 서로 아주 다른 출력 값이 나온다는 특성을 가지고 있습니다
이런 해시 함수가 왜 필요할까요?
해시함수는 우선 해시값으로 원래 값을 찾을 수 없기 때문에 보안에 활용됩니다.
예를 들어, 비밀번호를 평문으로 저장하게 되면 데이터베이스가 유출되었을 때 유저들의 비밀번호가 그대로 노출될 것입니다
하지만 비밀번호에 대한 해시값만 저장하고 사용자가 비밀번호를 입력했을 때 입력한 값에 대한 해시값과 저장된 해시값과의 비교를 통해 로그인 하는 방식을 선택한다면, 데이터베이스가 유출되더라도 일차적으로 유저들의 비밀번호가 그대로 노출되는 일은 막을 수 있습니다.
해시함수는 입력 값이 달라지면 그에 대한 출력 값 역시 달라진다는 점을 이용해 데이터가 변하지 않았음을 확인하는 데 활용할 수도 있습니다
저는 해시함수를 비밀번호의 보안 유지를 위해 활용해 보겠습니다
먼저 DB에 비밀번호 평문이 아닌 입력받은 비밀번호에 대한 해시 값이 들어가야 하므로,
회원가입 페이지에서 비밀번호 부분을 수정해보도록 하겠습니다
해시함수 알고리즘에는 여러가지 종류가 있습니다
저는 그 중 SHA256
이라는 해시함수를 사용하겠습니다
// 회원가입 페이지
$username = $_POST['username'];
$password = hash('sha256',$_POST['password']); //비밀번호에 해시 처리
$name = $_POST['name'];
$phone = $_POST['phone'];
$email = $_POST['email'];
// 이하 동일
그리고 로그인을 진행할 때도 입력받은 비밀번호 평문이 아닌, 해시 값과 DB에 저장된 해시 값이 일치하는 지 확인합니다
//로그인 페이지
$username = $_POST['username'];
$password = hash('sha256', $_POST['password']);
//식별 및 인증 진행
$sql = "SELECT * FROM account WHERE username == ".$userid." AND password ==".$password.";";
$result = mysqli_query($DB_conn, $sql);
if ($result) {
//로그인 성공
} else {
//로그인 실패
}
식별 / 인증 분리에 HASH 함수를 적용한 것 역시 사용자의 비밀번호 입력 값에 hash를 적용하기만 하면 됩니다
//로그인 페이지
$username = $_POST['username'];
$password = hash('sha256', $_POST['password']);
//식별 진행
$sql = "SELECT * FROM account WHERE username == ".$userid.";";
$result = mysqli_query($DB_conn, $sql);
$row = mysqli_fetch_array($result);
if ($row[0] != "") {
//아이디가 있는 경우 인증 진행
$sql_pw = ""SELECT * FROM account WHERE username='".$username."' and password = '".$password."';";
$result_pw = mysqli_query($DB_conn, $sql_pw);
$row_pw = mysqli_fetch_array($result_pw);
if($row_pw[0]!="") {
//로그인 성공
} else {
//로그인 실패
}
} else {
//로그인 실패
}