728x90

MySQLi 객체지향 접속방식으로 코드를 작성한 회원가입과 로그인 예제를 만들었다.

모두 꼼꼼하게 테스트하여 잘 동작함을 확인했다.


안전한 비밀번호 작성 규칙

- 영문자, 숫자, 특수문자 중 2가지 종류를 조합할 때에는 10자리 이상 / 3가지 종류를 조합할 때에는 8자리 이상으로 설정

- 비밀번호는 최소 6개월에 한번씩 변경

- 누구나 쉽게 알 수 있는 비밀번호 사용은 자제


<?php
// DB 정보 입력
define("DB_HOST", "localhost");
define("DB_DATABASE", "test");
define("DB_USER", "root");
define("DB_PASSWORD", "autoset");
?>

<?php
class DBController {
    protected $db; // 변수를 선언한 클래스와 상속받은 클래스에서 참조할 수 있다.

    // 생성자
    function __construct() {
        $this->db = $this->connectDB();
        // construct 메소드는 객체가 생성(인스턴스화)될 때 자동으로 실행되는 특수한 메소드다.
    }

    // 소멸자(destructor)
    function __destruct() {
        mysqli_close($this->connectDB());
    }

    private function connectDB() {
        require_once 'config.php';
        // MySQLi 객체지향 DB 연결
        $conn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE);
        return $conn; // return database handler
    }

}
?>

<?php
class LoginClass extends DBController {
    // class 자식클래스 extends 부모클래스
    // override : 부모 클래스와 자식 클래스가 같은 메소드를 정의했을 경우 자식 클래스가 우선시된다.

    public function hashSSHA($password) {

        $salt = sha1(rand());
        $salt = substr($salt, 0, 10);
        $encrypted = base64_encode(sha1($password . $salt, true) . $salt);
        $hash = array("salt" => $salt, "encrypted" => $encrypted);
        return $hash;
    }

    public function checkhashSSHA($salt, $password) {
        $hash = base64_encode(sha1($password . $salt, true) . $salt);
        return $hash;
    }

    // 회원 정보 신규 입력
    public function storeUser($userID, $userNM, $password, $mobileNO) {
        $hash = $this->hashSSHA($password);
        $encrypted_password = $hash['encrypted']; // encrypted password
        $salt = $hash['salt']; // salt
        $regdate = date("YmdHis");

        $stmt = $this->db->prepare("INSERT INTO members(userID, userNM, passwd, salt, regdate) VALUES(?, ?, ?, ?, ?)");
        $stmt->bind_param("sssss", $userID, $userNM, $encrypted_password, $salt,$regdate);
        $result = $stmt->execute();
        $stmt->close();

        // check for successful store
        if ($result) {
            $user = $this->getUser($userID, $password);
            //echo '<pre>';print_r($user);echo '</pre>';
            $rs = $this->storeUserDetail($user['uid'],$userNM,$userID,$mobileNO);
            if($rs == 1){
                return $user;
            } else {
                return -1;
            }
        } else {
            return -1; // 0
        }
    }

    // 회원 세부 정보 입력
    public function storeUserDetail($relateduid,$userNM,$email,$mobileNO){
        $mobileNO = preg_replace("/[^0-9]/", "", $mobileNO); //전화번호 숫자만 남기고 제거
        $sql ="INSERT INTO member_data(relateduid,userNM,email,mobileNO) VALUES(?, ?, ?, ?)";
        $stmt = $this->db->prepare($sql);
        $stmt->bind_param("isss", $relateduid, $userNM, $email, $mobileNO);
        $result = $stmt->execute();
        $stmt->close();
        if($result){
            return 1;
        } else {
            return 0;
        }
    }


    // 로그인 체크
    public function getUser($userID, $password) {
        $stmt = $this->db->prepare("SELECT * FROM members WHERE userID = ?");
        $stmt->bind_param("s", $userID);

        if ($stmt->execute()) {
            $user = $stmt->get_result()->fetch_assoc();
            $stmt->close();

            // verifying user password
            $salt = $user['salt'];
            $encrypted_password = $user['passwd'];
            $hash = $this->checkhashSSHA($salt, $password);
            // check for password equality
            if ($encrypted_password == $hash) {
                // user authentication details are correct
                return $user;
            }
        } else {
            return NULL;
        }
    }

    // 안드로이드/아이폰 로그인 체크
    public function LoginUserChk($userID,$password,$deviceID){
        if(empty($userID) || empty($password)){
            return 0;
        } else {
            $user = $this->getUser($userID, $password);
            if($user['uid']>0){ // 가입자 정보가 있다면
                // 장치 일련번호 체크
                if($user['phoneSE'] == NULL){
                    // 신규 장치번호 입력(최초 로그인)
                    $this->LoginUserEquipInput($userID,$deviceID);
                    return 1;
                } else {
                    if($user['phoneSE'] === $deviceID){
                        return 1; // 일련번호 일치
                    } else {
                        return -1; //일련번호 불일치
                    }
                }
            } else {
                return 0; // 로그인 실패
            }
        }

    }

    // 장치번호 업데이트
    public function LoginUserEquipInput($userID,$deviceID){
        if(strlen($deviceID)>0 && is_numeric($deviceID)){ // 안드로이드폰
            $ostype = 2;
        } else if(strlen($deviceID)>30){ // 아이폰
            $ostype = 1;
        } else { // 기타
            $ostype = 0;
        }

        $sql='update members set phoneSE=?, OStype=? where userID=?';
        $stmt = $this->db->prepare($sql);
        $stmt->bind_param("sss", $deviceID, $ostype, $userID);
        $status = $stmt->execute();
        if($status == true){
            return 1;
        } else {
            return 0;
        }
    }//end

    // 장치번호 초기화 (관리자용)
    public function EquipReset($userID){
        $ostype = 0;
        $sql='update members set phoneSE=NULL, OStype=? where userID=?';
        $stmt = $this->db->prepare($sql);
        $stmt->bind_param("ss", $ostype, $userID);
        $status = $stmt->execute();
        if($status == true){
            return 1;
        } else {
            return 0;
        }
    }//end

    // 회원 가입 여부 체크
    public function isUserExisted($userID) {
        $stmt = $this->db->prepare("SELECT userID from members WHERE userID = ?");

        $stmt->bind_param("s", $userID);
        $stmt->execute();
        //$stmt->store_result();
        $result = $stmt->get_result();

        if ($result->num_rows > 0) {
            // user existed
            $stmt->free_result();
            $stmt->close();
            return true;
        } else {
            // user not existed
            $stmt->free_result();
            $stmt->close();
            return false;
        }
    }

    // 회원 정보 삭제
    public function deleteUser($userID){
        $stmt = $this->db->prepare("delete FROM members WHERE userID = ?");
        $stmt->bind_param("s", $userID);
        $stmt->execute();
        $stmt->close();
    }

    // 인증이 성공한 상태에서 직접 접속을 시도하는 외부 접속으로부터 보호
    function checkReferer($url) {
        $referer = $_SERVER['HTTP_REFERER'];
        $res = strpos($referer,$url);
        return $res == 0 ? false : true;
    }
}
?>

 <?php
if (!isset($_SESSION)) {
    session_start();
}

// 파일을 직접 실행하면 동작되지 않도록 하기 위해서
if(isset($_POST) && $_SERVER['REQUEST_METHOD'] == "POST"){
    @extract($_POST); // $_POST['loginID'] 라고 쓰지 않고, $loginID 라고 써도 인식되게 함
    //echo '<pre>';print_r($_POST);echo '</pre>'; // 전송받은 배열을 확인하고 싶을 때 사용
    if(isset($userID) && !empty($userID) && isset($password) && !empty($password)) {
        include_once 'config/dbconnect.php';
        require_once 'config/loginClass.php';
        $c = new LoginClass();
        if ($c->isUserExisted($userID) === true) {
            echo '{"result":"0"}'; // echo json_encode(array('result' => '0')); 과 동일
        } else {
            $mobileNO = preg_replace("/[^0-9]/", "", $mobileNO); //전화번호 숫자만 남기고 제거
            // 회원 등록
            $user = $c->storeUser($userID, $userNM, $password, $mobileNO);
            if($user) {// 회원 등록 성공
                $_SESSION['userID'] = $user['userID'];
                $_SESSION['userNM'] = $user['userNM'];
                $_SESSION['admin'] = $user['admin'];
                echo json_encode(array('result' => '1'));
            } else {
                // 회원 등록 실패
                echo json_encode(array('result' => '-1'));
            }
        }
    }else {// 입력받은 데이터에 문제가 있을 경우
        echo json_encode(array('result' => '-2'));
    }
}
?>

 <?php
// 파일을 직접 실행하는 비정상적 동작을 방지 목적
if(isset($_POST) && $_SERVER['REQUEST_METHOD'] == "POST"){
    @extract($_POST); // $_POST['loginID'] 라고 쓰지 않고, $loginID 라고 써도 인식되게 함
    if(isset($userID) && !empty($userID) && isset($password) && !empty($password)) {
        include_once 'config/dbconnect.php';
        require_once 'config/loginClass.php';
        $c = new LoginClass();
        $user = $c->getUser($userID, $password);
        //echo '<pre>'; print_r($user);echo '</pre>';
        if ($user != false) {
            $_SESSION['userID'] = $user['userID'];
            $_SESSION['userNM'] = $user['userNM'];
            $_SESSION['admin'] = $user['admin'];
            echo json_encode(array('result' => '1'));
        } else {
            echo json_encode(array('result' => '0'));
        }
    }else {// 입력받은 데이터에 문제가 있을 경우
        echo json_encode(array('result' => '-2'));
    }
} else { // 비정상적인 접속인 경우
    echo 0; // a.loginChk.php 파일을 직접 실행할 경우에는 화면에 0을 찍어준다.
    exit;
}
?>


직접 실행해 볼 수 있는 테이블 구조 및 관련 파일을 모두 첨부한다.

안드로이드에서 로그인하는 코드 샘플도 포함되어 있다.


mysqlI_login.zip



블로그 이미지

Link2Me

,
728x90

KIA 성적이 전년도 우승팀 답지 않게 중위권에서 놀고 있는 이유는 뭘까?



올해 투수력이 작년만큼 강하지 못하고 경쟁팀들은 전력보강 및 전력분석을 통해 KIA 투수의 약점을 공략하고 있다.

구위가 떨어져서일까?

김민식 포수는 타력보강을 위해 우승후에 캠프에 자청하고 가서 타격을 보강했다.

김민식은 작년도만큼 절심함도 없는데다가 투수리드가 타격보다 훨씬 더 중요하다는 걸 간과하고 있다.

가장 중요한 것은 2017년도 KIA가 SK와 4:4 트레이드를 통해서 약점이었던 포수를 보강하고 최형우가 4번 타자의 몫을 톡톡히 해주면서 시너지가 급상승했다.

그러면서 중위권에서 1위로 분위기가 급반전되면서 우승을 차지했다.

올해 헥터 투수도 난타를 많이 당했다. 하지만 한승택과 호흡을 맞춘 경기에서는 점수도 적게 주고 투구수도 훨씬 더 적게 주면서 안정적인 모습을 보여줬다.

타격이 좀 약한 한승택을 2군으로 보내고, 백용환을 올리는데 김기태 감독은 투수리드의 가치가 얼마나 큰 지를 잘 모르는 거 같다.

투수리드 능력이 좋은 포수를 기용하는 것이 공격형 포수보다 훨씬 더 중요하다.

NC는 김태군 포수가 군입대를 하면서 포수가 엄청 약해지면서 NC가 꼴찌를 하고 있다.

투수리드가 읽혀서 대량실점을 많이 하게 했던 정범모 포수를 NC가 트레이드 하여 경기에 임하지만 좋아지기는 했어도 아직 점수를 주는 편이다.


KIA가 반등하는 것은 투수리드 능력이 좋은 한승택을 더 자주 기용하는 것이라고 본다.

김민식 포수는 타격 잘하려고 노력할 시간에 상대 타자분석하고 투수리드를 어떻게 하면 더 잘할 것인지 연구해야 한다.

김민식 포수와 호흡을 맞추면 공을 던지는 투구수가 한승택에 비해 더 많다.

박경완 포수처럼 최고의 야전사령관이 되려면 끊임없이 노력해야 한다.

포수 능력이 좋은 팀이 상위권이라는 건 두산을 보면 알 수 있지 않는가.


김기태 감독은 선수 기용을 본인이 트레이드하거나 영입했던 선수 중심이 아니라 객관적인 관점에서 기용해야 한다.

연봉이 높은 선수라도 못하면 기용하지 말고 열심히 하는 선수에게 기회를 줘야 한다.

윤석민 3닝 혹시 마무리해서 안좋은 결과를 만들었으면 양현종 투구수 관리도 해주고 선수를 아끼는 모습을 보여줘야 하는데 참 아쉽다..

공평한 기회를 준다는 느낌이 들도록 선수를 기용하길 ...

'스포츠' 카테고리의 다른 글

넥센 야구가 더 성장하려면  (0) 2014.11.23
심창민 데드볼을 지켜보며.... 데드볼과 선수멘탈  (0) 2013.06.07
김상현 트레이드  (0) 2013.05.07
블로그 이미지

Link2Me

,