Hệ thống đăng nhập Unity với PHP và MySQL

Trong hướng dẫn này, tôi sẽ hướng dẫn cách tạo hệ thống đăng nhập trong Unity bằng cách sử dụng PHP và MySQL.

Hướng dẫn này yêu cầu máy chủ có cPanel cùng với PHP và MySQLi (phiên bản cải tiến của MySQL).

Vui lòng kiểm tra dịch vụ lưu trữ VPS cao cấp có giá cả phải chăng hoặc giải pháp thay thế Shared Hosting rẻ hơn.

Bước 1: Thiết lập cơ sở dữ liệu MySQL

  • Đăng nhập vào cPanel
  • Bấm vào Cơ sở dữ liệu MySQL trong phần CƠ SỞ DỮ LIỆU

  • Trong phần "Create New Database", nhập tên cho cơ sở dữ liệu của bạn rồi nhấp vào "Create Database"

Sau khi cơ sở dữ liệu được tạo, chúng ta cần tạo một người dùng sẽ được liên kết với nó:

  • Nhập Tên người dùng trong phần "MySQL Users" sau đó nhập mật khẩu (hoặc tốt nhất là sử dụng Trình tạo mật khẩu để tạo mật khẩu mạnh). Đừng quên lưu mật khẩu ở đâu đó, sau này sẽ cần đến.

Cuối cùng, chúng ta cần chỉ định người dùng vào cơ sở dữ liệu với một bộ quyền cụ thể.

  • Trong phần "Add User To Database", chọn người dùng và cơ sở dữ liệu mới tạo rồi nhấp vào "Add"

Sau khi nhấp vào "Add" bạn sẽ thấy danh sách Đặc quyền. Chỉ chọn những đặc quyền mà bạn định sử dụng trong tương lai. Phổ biến nhất là XÓA, CHỌN, CHÈN và CẬP NHẬT:

  • Bấm "Make Changes" để hoàn tất

Bước 2: Tạo bảng MySQL

Bảng MySQL sẽ lưu trữ các giá trị do người dùng cung cấp, chẳng hạn như tên người dùng, email, mật khẩu, v.v.

  • Nhấp vào "phpMyAdmin" trong phần CƠ SỞ DỮ LIỆU

  • Bấm vào cơ sở dữ liệu vừa tạo rồi bấm vào tab SQL

  • Dán mã bên dưới vào trình soạn thảo truy vấn, sau đó nhấp vào "Go"
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";

--
-- Table structure for table `sc_users`
--

CREATE TABLE `sc_users` (
  `user_id` int(11) NOT NULL,
  `username` varchar(20) CHARACTER SET utf8 NOT NULL,
  `email` varchar(254) CHARACTER SET utf8 NOT NULL,
  `password` char(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `registration_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Indexes for table `sc_users`
--
ALTER TABLE `sc_users`
  ADD PRIMARY KEY (`user_id`),
  ADD UNIQUE KEY `username` (`username`),
  ADD UNIQUE KEY `email` (`email`);

--
-- AUTO_INCREMENT for table `sc_users`
--
ALTER TABLE `sc_users`
  MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;
COMMIT;

Truy vấn trên sẽ tạo một bảng mới 'sc_users' để lưu trữ dữ liệu người dùng.

Bước 3: Lập trình logic phía máy chủ

Logic phía máy chủ sẽ bao gồm các tập lệnh PHP sẽ nhận và xử lý dữ liệu Bài đăng từ Unity.

Tệp đầu tiên là cơ sở dữ liệu.php sẽ kết nối với cơ sở dữ liệu MySQL bằng phần mở rộng PHP MySQLi.

cơ sở dữ liệu.php

<?php
	$host = "localhost"; // Host name 
	$db_username = "DATABASE_USER"; // Mysql username 
	$db_password = "USER_PASSWORD"; // Mysql password 
	$db_name = "DATABASE_NAME"; // Database name 

	$mysqli_conection = mysqli_connect($host, $db_username, $db_password, $db_name)or die("cannot connect"); 
?>

Thay thế DATABASE_USER, USER_PASSWORD,DATABASE_NAME bằng các giá trị của bạn.

Tệp thứ hai là register.php. Tệp này sẽ nhận dữ liệu bài đăng từ Unity và chèn bản ghi người dùng mới vào bảng cơ sở dữ liệu.

đăng ký.php

<?php
	if(isset($_POST["email"]) && isset($_POST["username"]) && isset($_POST["password1"]) && isset($_POST["password2"])){
		$errors = array();
		
		$emailMaxLength = 254;
		$usernameMaxLength = 20;
		$usernameMinLength = 3;
		$passwordMaxLength = 19;
		$passwordMinLength = 5;
		
		$email = strtolower($_POST["email"]);
		$username = $_POST["username"];
		$password1 = $_POST["password1"];
		$password2 = $_POST["password2"];
		
		//Validate email
		if(preg_match('/\s/', $email)){
			$errors[] = "Email can't have spaces";
		}else{
			if(!validate_email_address($email)){
				$errors[] = "Invalid email";
			}else{
				if(strlen($email) > $emailMaxLength){
					$errors[] = "Email is too long, must be equal or under " . strval($emailMaxLength) . " characters";
				}
			}
		}
		
		//Validate username
		if(strlen($username) > $usernameMaxLength || strlen($username) < $usernameMinLength){
			$errors[] = "Incorrect username length, must be between " . strval($usernameMinLength) . " and " . strval($usernameMaxLength) . " characters";
		}else{
			if(!ctype_alnum ($username)){
				$errors[] = "Username must be alphanumeric";
			}
		}
		
		//Validate password
		if($password1 != $password2){
			$errors[] = "Passwords do not match";
		}else{
			if(preg_match('/\s/', $password1)){
				$errors[] = "Password can't have spaces";
			}else{
				if(strlen($password1) > $passwordMaxLength || strlen($password1) < $passwordMinLength){
					$errors[] = "Incorrect password length, must be between " . strval($passwordMinLength) . " and " . strval($passwordMaxLength) . " characters";
				}else{
					if(!preg_match('/[A-Za-z]/', $password1) || !preg_match('/[0-9]/', $password1)){
						$errors[] = "Password must contain atleast 1 letter and 1 number";
					}
				}
			}
		}
		
		//Check if there is user already registered with the same email or username
		if(count($errors) == 0){
			//Connect to database
			require dirname(__FILE__) . '/database.php';
			
			if ($stmt = $mysqli_conection->prepare("SELECT username, email FROM sc_users WHERE email = ? OR username = ? LIMIT 1")) {
				
				/* bind parameters for markers */
				$stmt->bind_param('ss', $email, $username);
					
				/* execute query */
				if($stmt->execute()){
					
					/* store result */
					$stmt->store_result();

					if($stmt->num_rows > 0){
					
						/* bind result variables */
						$stmt->bind_result($username_tmp, $email_tmp);

						/* fetch value */
						$stmt->fetch();
						
						if($email_tmp == $email){
							$errors[] = "User with this email already exist.";
						}
						else if($username_tmp == $username){
							$errors[] = "User with this name already exist.";
						}
					}
					
					/* close statement */
					$stmt->close();
					
				}else{
					$errors[] = "Something went wrong, please try again.";
				}
			}else{
				$errors[] = "Something went wrong, please try again.";
			}
		}
		
		//Finalize registration
		if(count($errors) == 0){
			$hashedPassword = password_hash($password1, PASSWORD_BCRYPT);
			if ($stmt = $mysqli_conection->prepare("INSERT INTO sc_users (username, email, password) VALUES(?, ?, ?)")) {
				
				/* bind parameters for markers */
				$stmt->bind_param('sss', $username, $email, $hashedPassword);
					
				/* execute query */
				if($stmt->execute()){
					
					/* close statement */
					$stmt->close();
					
				}else{
					$errors[] = "Something went wrong, please try again.";
				}
			}else{
				$errors[] = "Something went wrong, please try again.";
			}
		}
		
		if(count($errors) > 0){
			echo $errors[0];
		}else{
			echo "Success";
		}
	}else{
		echo "Missing data";
	}
	
	function validate_email_address($email) {
		return preg_match('/^([a-z0-9!#$%&\'*+-\/=?^_`{|}~.]+@[a-z0-9.-]+\.[a-z0-9]+)$/i', $email);
	}
?>

Và tệp cuối cùng là login.php sẽ nhận thông tin đăng nhập và kiểm tra chúng dựa trên bảng sc_users.

đăng nhập.php

<?php
	if(isset($_POST["email"]) && isset($_POST["password"])){
		$errors = array();
		
		$email = $_POST["email"];
		$password = $_POST["password"];
		
		//Connect to database
		require dirname(__FILE__) . '/database.php';
		
		if ($stmt = $mysqli_conection->prepare("SELECT username, email, password FROM sc_users WHERE email = ? LIMIT 1")) {
			
			/* bind parameters for markers */
			$stmt->bind_param('s', $email);
				
			/* execute query */
			if($stmt->execute()){
				
				/* store result */
				$stmt->store_result();

				if($stmt->num_rows > 0){
					/* bind result variables */
					$stmt->bind_result($username_tmp, $email_tmp, $password_hash);

					/* fetch value */
					$stmt->fetch();
					
					if(password_verify ($password, $password_hash)){
						echo "Success" . "|" . $username_tmp . "|" .  $email_tmp;
						
						return;
					}else{
						$errors[] = "Wrong email or password.";
					}
				}else{
					$errors[] = "Wrong email or password.";
				}
				
				/* close statement */
				$stmt->close();
				
			}else{
				$errors[] = "Something went wrong, please try again.";
			}
		}else{
			$errors[] = "Something went wrong, please try again.";
		}
		
		if(count($errors) > 0){
			echo $errors[0];
		}
	}else{
		echo "Missing data";
	}
?>
  • Tải cả 3 file lên thư mục public_html của bạn.

Bước 4: Lập trình logic máy khách trong Unity

Logic máy khách sẽ bao gồm tập lệnh C# sẽ đăng dữ liệu lên tập lệnh PHP.

  • Tạo một tập lệnh mới trong Unity và đặt tên là SC_LoginSystem rồi dán đoạn mã bên dưới vào bên trong nó:

SC_LoginSystem.cs

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class SC_LoginSystem : MonoBehaviour
{
    public enum CurrentWindow { Login, Register }
    public CurrentWindow currentWindow = CurrentWindow.Login;

    string loginEmail = "";
    string loginPassword = "";
    string registerEmail = "";
    string registerPassword1 = "";
    string registerPassword2 = "";
    string registerUsername = "";
    string errorMessage = "";

    bool isWorking = false;
    bool registrationCompleted = false;
    bool isLoggedIn = false;

    //Logged-in user data
    string userName = "";
    string userEmail = "";

    string rootURL = "http://YOUR_SITE.COM/"; //Path where php files are located

    void OnGUI()
    {
        if (!isLoggedIn)
        {
            if (currentWindow == CurrentWindow.Login)
            {
                GUI.Window(0, new Rect(Screen.width / 2 - 125, Screen.height / 2 - 115, 250, 230), LoginWindow, "Login");
            }
            if (currentWindow == CurrentWindow.Register)
            {
                GUI.Window(0, new Rect(Screen.width / 2 - 125, Screen.height / 2 - 165, 250, 330), RegisterWindow, "Register");
            }
        }

        GUI.Label(new Rect(5, 5, 500, 25), "Status: " + (isLoggedIn ? "Logged-in Username: " + userName + " Email: " + userEmail : "Logged-out"));
        if (isLoggedIn)
        {
            if (GUI.Button(new Rect(5, 30, 100, 25), "Log Out"))
            {
                isLoggedIn = false;
                userName = "";
                userEmail = "";
                currentWindow = CurrentWindow.Login;
            }
        }
    }

    void LoginWindow(int index)
    {
        if (isWorking)
        {
            GUI.enabled = false;
        }

        if (errorMessage != "")
        {
            GUI.color = Color.red;
            GUILayout.Label(errorMessage);
        }
        if (registrationCompleted)
        {
            GUI.color = Color.green;
            GUILayout.Label("Registration Completed!");
        }

        GUI.color = Color.white;
        GUILayout.Label("Email:");
        loginEmail = GUILayout.TextField(loginEmail);
        GUILayout.Label("Password:");
        loginPassword = GUILayout.PasswordField(loginPassword, '*');

        GUILayout.Space(5);

        if (GUILayout.Button("Submit", GUILayout.Width(85)))
        {
            StartCoroutine(LoginEnumerator());
        }

        GUILayout.FlexibleSpace();

        GUILayout.Label("Do not have account?");
        if (GUILayout.Button("Register", GUILayout.Width(125)))
        {
            ResetValues();
            currentWindow = CurrentWindow.Register;
        }
    }

    void RegisterWindow(int index)
    {
        if (isWorking)
        {
            GUI.enabled = false;
        }

        if (errorMessage != "")
        {
            GUI.color = Color.red;
            GUILayout.Label(errorMessage);
        }

        GUI.color = Color.white;
        GUILayout.Label("Email:");
        registerEmail = GUILayout.TextField(registerEmail, 254);
        GUILayout.Label("Username:");
        registerUsername = GUILayout.TextField(registerUsername, 20);
        GUILayout.Label("Password:");
        registerPassword1 = GUILayout.PasswordField(registerPassword1, '*', 19);
        GUILayout.Label("Password Again:");
        registerPassword2 = GUILayout.PasswordField(registerPassword2, '*', 19);

        GUILayout.Space(5);

        if (GUILayout.Button("Submit", GUILayout.Width(85)))
        {
            StartCoroutine(RegisterEnumerator());
        }

        GUILayout.FlexibleSpace();

        GUILayout.Label("Already have an account?");
        if (GUILayout.Button("Login", GUILayout.Width(125)))
        {
            ResetValues();
            currentWindow = CurrentWindow.Login;
        }
    }

    IEnumerator RegisterEnumerator()
    {
        isWorking = true;
        registrationCompleted = false;
        errorMessage = "";

        WWWForm form = new WWWForm();
        form.AddField("email", registerEmail);
        form.AddField("username", registerUsername);
        form.AddField("password1", registerPassword1);
        form.AddField("password2", registerPassword2);

        using (UnityWebRequest www = UnityWebRequest.Post(rootURL + "register.php", form))
        {
            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                errorMessage = www.error;
            }
            else
            {
                string responseText = www.downloadHandler.text;

                if (responseText.StartsWith("Success"))
                {
                    ResetValues();
                    registrationCompleted = true;
                    currentWindow = CurrentWindow.Login;
                }
                else
                {
                    errorMessage = responseText;
                }
            }
        }

        isWorking = false;
    }

    IEnumerator LoginEnumerator()
    {
        isWorking = true;
        registrationCompleted = false;
        errorMessage = "";

        WWWForm form = new WWWForm();
        form.AddField("email", loginEmail);
        form.AddField("password", loginPassword);

        using (UnityWebRequest www = UnityWebRequest.Post(rootURL + "login.php", form))
        {
            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                errorMessage = www.error;
            }
            else
            {
                string responseText = www.downloadHandler.text;

                if (responseText.StartsWith("Success"))
                {
                    string[] dataChunks = responseText.Split('|');
                    userName = dataChunks[1];
                    userEmail = dataChunks[2];
                    isLoggedIn = true;

                    ResetValues();
                }
                else
                {
                    errorMessage = responseText;
                }
            }
        }

        isWorking = false;
    }

    void ResetValues()
    {
        errorMessage = "";
        loginEmail = "";
        loginPassword = "";
        registerEmail = "";
        registerPassword1 = "";
        registerPassword2 = "";
        registerUsername = "";
    }
}

Thay thế http://YOUR_SITE.COM/ bằng giá trị của bạn (Đây phải là đường dẫn gốc nơi bạn đã tải lên tệp PHP). Ngoài ra, hãy đảm bảo sử dụng HTTPS nếu máy chủ của bạn đã cài đặt Chứng chỉ SSL.

  • Tạo một GameObject mới và đặt tên cho nó "LoginSystem"
  • Đính kèm vào SC_LoginSystem vào đối tượng loginSystem

Nhấn Play sau đó nhấp Đăng ký để tạo tài khoản mới hoặc cung cấp thông tin xác thực để đăng nhập.

Chúng tôi sẽ tiếp tục hướng dẫn này về cách tạo bảng xếp hạng trực tuyến.

Bài viết được đề xuất
Hướng dẫn về bảng xếp hạng trực tuyến Unity
Xây dựng các trò chơi nối mạng nhiều người chơi trong Unity
Nén dữ liệu nhiều người chơi và thao tác bit
Tạo trò chơi ô tô nhiều người chơi với PUN 2
Tạo trò chơi nhiều người chơi trong Unity bằng PUN 2
Hướng dẫn cho người mới bắt đầu về Mạng Photon (Cổ điển)
Giới thiệu về Photon Fusion 2 trong Unity