Hệ thống đăng nhập Client-Server được xây dựng dựa trên mô hình giao tiếp TCP Socket giữa máy khách (Client) và máy chủ (Server). Trong hệ thống này, Server sẽ nhận và xử lý các yêu cầu từ phía Client. Người dùng phía Client sẽ thực hiện thao tác đăng nhập bằng cách nhập tên tài khoản và mật khẩu, sau đó thông tin này sẽ được gửi tới Server thông qua kết nối TCP. Phía Server có giao diện quản lý tài khoản trực quan, cho phép Thêm, Sửa, Xoá dữ liệu người dùng. Dữ liệu này được lưu trữ và quản lý trong cơ sở dữ liệu MySQL, được kết nối bằng JDBC (Java Database Connectivity), đảm bảo tính an toàn và toàn vẹn dữ liệu.
Trong đó:
- Java: ngôn ngữ chính để xây dựng Client và Server theo mô hình TCP Socket.
- MySQL: hệ quản trị cơ sở dữ liệu lưu trữ thông tin tài khoản người dùng.
- JDBC: cầu nối giữa ứng dụng Java và cơ sở dữ liệu MySQL.
![]() Giao diện đăng nhập |
![]() Giao diện đăng ký |
![]() Giao diện User (màn hình chính) |
![]() Thông tin hồ sơ |
![]() Sửa thông tin User |
![]() Đổi mật khẩu |
![]() Cập nhật ảnh đại diện |
- Cài đặt JDK 8+: Download Java
- Cài đặt MySQL Server: Download MySQL
- Cài đặt Git (nếu chưa có): Download Git
- IDE khuyến nghị: IntelliJ IDEA hoặc Eclipse
Mở terminal/cmd và chạy lệnh:
git clone https://github.com/dtb0405/LTM-1604-D07-Sign-in-Client-Server.git
cd LTM-1604-D07-Sign-in-Client-ServerMở MySQL Workbench và chạy lệnh:
CREATE DATABASE IF NOT EXISTS he_thong_dang_nhap;
USE he_thong_dang_nhap;
-- =====================================================
-- BẢNG TÀI KHOẢN NGƯỜI DÙNG
-- =====================================================
CREATE TABLE tai_khoan (
id INT PRIMARY KEY AUTO_INCREMENT,
ten_dang_nhap VARCHAR(50) UNIQUE NOT NULL,
mat_khau VARCHAR(255) NOT NULL,
ho_ten VARCHAR(100) NOT NULL,
email VARCHAR(100),
so_dien_thoai VARCHAR(15),
ngay_sinh DATE,
vai_tro ENUM('user', 'admin') DEFAULT 'user',
trang_thai ENUM('hoat_dong', 'bi_khoa') DEFAULT 'hoat_dong',
trang_thai_online ENUM('online', 'offline') DEFAULT 'offline',
ngay_tao TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
lan_dang_nhap_cuoi TIMESTAMP NULL,
-- Các cột mới cho tính năng ảnh đại diện
avatar_path VARCHAR(500) NULL,
avatar_data LONGBLOB NULL
);
-- =====================================================
-- BẢNG LỊCH SỬ ĐĂNG NHẬP
-- =====================================================
CREATE TABLE lich_su_dang_nhap (
id INT PRIMARY KEY AUTO_INCREMENT,
tai_khoan_id INT,
ten_dang_nhap VARCHAR(50),
thoi_gian_dang_nhap TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
thoi_gian_dang_xuat TIMESTAMP NULL,
dia_chi_ip VARCHAR(45),
trang_thai ENUM('thanh_cong', 'that_bai') DEFAULT 'thanh_cong',
ghi_chu TEXT,
FOREIGN KEY (tai_khoan_id) REFERENCES tai_khoan(id) ON DELETE CASCADE
);
-- =====================================================
-- DỮ LIỆU MẪU
-- =====================================================
-- Tạo tài khoản admin mặc định
INSERT INTO tai_khoan (ten_dang_nhap, mat_khau, ho_ten, vai_tro, avatar_path)
VALUES ('binh', 'binhbinh', 'Đặng Thanh Bình', 'admin', 'default_avatar.png');
-- Tạo một số tài khoản user mẫu
INSERT INTO tai_khoan (ten_dang_nhap, mat_khau, ho_ten, email, vai_tro, avatar_path)
VALUES
('user1', 'user123', 'Nguyen Van A', '[email protected]', 'user', 'default_avatar.png'),
('user2', 'user123', 'Tran Thi B', '[email protected]', 'user', 'default_avatar.png'),
('admin1', 'admin123', 'Admin User', '[email protected]', 'admin', 'default_avatar.png'),
('testuser', 'test123', 'Test User', '[email protected]', 'user', 'default_avatar.png');
-- Index cho tìm kiếm theo tên đăng nhập
CREATE INDEX idx_ten_dang_nhap ON tai_khoan(ten_dang_nhap);
-- Index cho tìm kiếm theo email
CREATE INDEX idx_email ON tai_khoan(email);
-- Index cho lọc theo vai trò
CREATE INDEX idx_vai_tro ON tai_khoan(vai_tro);
-- Index cho lọc theo trạng thái
CREATE INDEX idx_trang_thai ON tai_khoan(trang_thai);
-- Index cho lọc theo trạng thái online
CREATE INDEX idx_trang_thai_online ON tai_khoan(trang_thai_online);
-- Index cho lịch sử đăng nhập theo tài khoản
CREATE INDEX idx_lich_su_tai_khoan ON lich_su_dang_nhap(tai_khoan_id);
-- Index cho lịch sử đăng nhập theo thời gian
CREATE INDEX idx_lich_su_thoi_gian ON lich_su_dang_nhap(thoi_gian_dang_nhap);
-- Index cho lịch sử đăng nhập theo trạng thái
CREATE INDEX idx_lich_su_trang_thai ON lich_su_dang_nhap(trang_thai);
-- =====================================================
-- VIEWS ĐỂ BÁO CÁO
-- =====================================================
-- View thống kê tổng quan
CREATE VIEW vw_thong_ke_tong_quan AS
SELECT
COUNT(*) as tong_tai_khoan,
SUM(CASE WHEN vai_tro = 'admin' THEN 1 ELSE 0 END) as so_admin,
SUM(CASE WHEN vai_tro = 'user' THEN 1 ELSE 0 END) as so_user,
SUM(CASE WHEN trang_thai = 'hoat_dong' THEN 1 ELSE 0 END) as tai_khoan_hoat_dong,
SUM(CASE WHEN trang_thai = 'bi_khoa' THEN 1 ELSE 0 END) as tai_khoan_bi_khoa,
SUM(CASE WHEN trang_thai_online = 'online' THEN 1 ELSE 0 END) as tai_khoan_online,
SUM(CASE WHEN trang_thai_online = 'offline' THEN 1 ELSE 0 END) as tai_khoan_offline
FROM tai_khoan;
-- View thống kê đăng nhập theo ngày
CREATE VIEW vw_thong_ke_dang_nhap_ngay AS
SELECT
DATE(thoi_gian_dang_nhap) as ngay,
COUNT(*) as tong_luot_dang_nhap,
SUM(CASE WHEN trang_thai = 'thanh_cong' THEN 1 ELSE 0 END) as dang_nhap_thanh_cong,
SUM(CASE WHEN trang_thai = 'that_bai' THEN 1 ELSE 0 END) as dang_nhap_that_bai
FROM lich_su_dang_nhap
GROUP BY DATE(thoi_gian_dang_nhap)
ORDER BY ngay DESC;
-- View thống kê đăng nhập theo tài khoản
CREATE VIEW vw_thong_ke_dang_nhap_tai_khoan AS
SELECT
tk.id,
tk.ten_dang_nhap,
tk.ho_ten,
tk.vai_tro,
COUNT(ls.id) as tong_luot_dang_nhap,
SUM(CASE WHEN ls.trang_thai = 'thanh_cong' THEN 1 ELSE 0 END) as dang_nhap_thanh_cong,
SUM(CASE WHEN ls.trang_thai = 'that_bai' THEN 1 ELSE 0 END) as dang_nhap_that_bai,
MAX(ls.thoi_gian_dang_nhap) as lan_dang_nhap_cuoi
FROM tai_khoan tk
LEFT JOIN lich_su_dang_nhap ls ON tk.id = ls.tai_khoan_id
GROUP BY tk.id, tk.ten_dang_nhap, tk.ho_ten, tk.vai_tro;
-- =====================================================
-- STORED PROCEDURES
-- =====================================================
-- Procedure để cập nhật trạng thái online/offline
DELIMITER //
CREATE PROCEDURE sp_cap_nhat_trang_thai_online(
IN p_tai_khoan_id INT,
IN p_trang_thai_online ENUM('online', 'offline')
)
BEGIN
UPDATE tai_khoan
SET trang_thai_online = p_trang_thai_online,
lan_dang_nhap_cuoi = CASE
WHEN p_trang_thai_online = 'online' THEN NOW()
ELSE lan_dang_nhap_cuoi
END
WHERE id = p_tai_khoan_id;
END //
DELIMITER ;
-- Procedure để lấy thống kê đăng nhập trong ngày
DELIMITER //
CREATE PROCEDURE sp_thong_ke_dang_nhap_ngay(IN p_ngay DATE)
BEGIN
SELECT
COUNT(*) as tong_luot,
SUM(CASE WHEN trang_thai = 'thanh_cong' THEN 1 ELSE 0 END) as thanh_cong,
SUM(CASE WHEN trang_thai = 'that_bai' THEN 1 ELSE 0 END) as that_bai
FROM lich_su_dang_nhap
WHERE DATE(thoi_gian_dang_nhap) = p_ngay;
END //
DELIMITER ;
-- =====================================================
-- TRIGGERS
-- =====================================================
-- Trigger để tự động cập nhật thời gian đăng nhập cuối
DELIMITER //
CREATE TRIGGER tr_cap_nhat_dang_nhap_cuoi
AFTER INSERT ON lich_su_dang_nhap
FOR EACH ROW
BEGIN
IF NEW.trang_thai = 'thanh_cong' THEN
UPDATE tai_khoan
SET lan_dang_nhap_cuoi = NEW.thoi_gian_dang_nhap
WHERE id = NEW.tai_khoan_id;
END IF;
END //
DELIMITER ;
-- =====================================================
-- QUYỀN TRUY CẬP
-- =====================================================
-- Tạo user cho ứng dụng
CREATE USER IF NOT EXISTS 'app_user'@'localhost' IDENTIFIED BY 'app_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON he_thong_dang_nhap.* TO 'app_user'@'localhost';
-- Tạo user cho báo cáo (chỉ đọc)
CREATE USER IF NOT EXISTS 'report_user'@'localhost' IDENTIFIED BY 'report_password';
GRANT SELECT ON he_thong_dang_nhap.* TO 'report_user'@'localhost';- Mở file
DBConnection.javatrong thư mụcServer. - Cập nhật thông tin kết nối cơ sở dữ liệu MySQL như sau:
private static final String URL = "jdbc:mysql://localhost:3306/LoginDB?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"; private static final String TEN_NGUOI_DUNG = "root"; // thay bằng user MySQL private static final String MAT_KHAU = "your_password";
- URL: Địa chỉ kết nối đến cơ sở dữ liệu MySQL (thay
LoginDBnếu tên database khác). - TEN_NGUOI_DUNG: Tên người dùng MySQL (mặc định là
root). - MAT_KHAU: Mật khẩu MySQL (thay
your_passwordbằng mật khẩu thực tế của bạn).
- URL: Địa chỉ kết nối đến cơ sở dữ liệu MySQL (thay
- Mở lớp
GiaoDienServer.javatrong thư mụcgui. - Chạy chương trình (
Run). - Bật Server, Server sẽ khởi động và lắng nghe kết nối trên port 2712.
- Mở lớp
ManHinhDangNhap.javatrong thư mụcgui. - Chạy chương trình (
Run). - Giao diện người dùng sẽ hiển thị, cho phép:
- Đăng nhập: Nhập tài khoản và mật khẩu để đăng nhập.
- Đăng ký: Nhập thông tin để tạo tài khoản mới.
- Server log: Hiển thị thông tin kết nối chi tiết
- Giao diện Server: Hiển thị trạng thái "Đang chạy" và log real-time
- Giao diện Client: Chuyển đến giao diện tương ứng (User/Admin)
- Database: Dữ liệu được lưu trực tiếp vào MySQL
INSERT INTO tai_khoan (ho_ten, ten_dang_nhap, mat_khau, vai_tro, trang_thai, ngay_tao) VALUES ('Nguyễn Văn A', 'nguyenvana', 'hashed_password', 'user', 'hoat_dong', NOW());
- Validation: Kiểm tra tên đăng nhập trùng lặp
- Mật khẩu: Mã hóa an toàn trước khi lưu database
🔹 Thêm người dùng:
- Hộp thoại: Màu xanh dương với hoa văn chìm
- Thông tin: Họ tên, tên đăng nhập, mật khẩu, vai trò, trạng thái
- Validation: Kiểm tra tên đăng nhập trùng lặp, độ dài mật khẩu
- Kết quả: Tài khoản được tạo và hiển thị trong bảng quản lý
🔹 Sửa thông tin người dùng:
- Hiển thị: Thông tin hiện tại của tài khoản được chọn
- Chỉnh sửa: Có thể thay đổi họ tên, email, số điện thoại, ngày sinh
- Mật khẩu: Hiển thị mật khẩu hiện tại, cho phép đổi mật khẩu mới
- Lưu: Cập nhật thông tin vào database
🔹 Xóa người dùng:
- Xác nhận: Hộp thoại xác nhận trước khi xóa
- Thông tin: Hiển thị tên tài khoản sẽ bị xóa
- Kết quả: Tài khoản bị xóa khỏi database và bảng quản lý
🔹 Khóa/Mở khóa tài khoản:
- Khóa: Thay đổi trạng thái từ "hoat_dong" thành "bi_khoa"
- Mở khóa: Thay đổi trạng thái từ "bi_khoa" thành "hoat_dong"
- Xác nhận: Hộp thoại xác nhận trước khi thực hiện
- Hiển thị: Trạng thái được cập nhật trong bảng quản lý
- Ghi log: Mọi lần đăng nhập/đăng xuất được ghi lại
- Thông tin: Tên đăng nhập, thời gian, địa chỉ IP, trạng thái, ghi chú
- Hiển thị: Bảng lịch sử với màu xen kẽ (xanh nhạt/trắng)
- Xuất báo cáo: Tạo file Excel với lịch sử đăng nhập
- Mã hóa mật khẩu: Sử dụng hash an toàn
- Session management: Theo dõi trạng thái đăng nhập
- Logging: Ghi lại mọi hoạt động của người dùng
- Validation: Kiểm tra dữ liệu đầu vào
- Theme: Màu hồng cho User, màu xanh dương cho Admin
- Responsive: Tự động điều chỉnh kích thước
- User-friendly: Giao diện thân thiện, dễ sử dụng
- Real-time: Cập nhật thông tin ngay lập tức
- Kết nối: Server và Client kết nối thành công
- Database: Dữ liệu được lưu và truy xuất chính xác
- Giao diện: Tất cả chức năng hoạt động bình thường
- Bảo mật: Mật khẩu được mã hóa, session được quản lý
- Logging: Mọi hoạt động được ghi lại chi tiết
- Đảm bảo MySQL server đang chạy và cơ sở dữ liệu
he_thong_dang_nhapđã được tạo trước khi chạy chương trình. - Kiểm tra thông tin kết nối JDBC (URL, TEN_NGUOI_DUNG, MAT_KHAU) để đảm bảo chính xác.
- Server phải được chạy trước khi Client kết nối.
- 👨🎓 Người thực hiện: Đặng Thanh Bình
- 🎓 Khoa: Công nghệ thông tin – Trường Đại học Đại Nam
- 📞 Số điện thoại: 0822968881
- 📧 Email: [email protected]






















