0% found this document useful (0 votes)
3 views117 pages

Cleanup and Create QLNS Environment

Uploaded by

48Từ Anh Văn
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views117 pages

Cleanup and Create QLNS Environment

Uploaded by

48Từ Anh Văn
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

-- =========================================================

-- FILE 1: CLEANUP QLNS ENVIRONMENT


-- Dọn dẹp sạch sẽ môi trường cũ
-- CHẠY AS: SYS (SYSDBA)
-- =========================================================
SET SERVEROUTPUT ON SIZE 1000000;

PROMPT
=========================================================
PROMPT === FILE 1: CLEANUP QLNS ENVIRONMENT ===
PROMPT
=========================================================

-- Đảm bảo đang thao tác trong ORCLPDB


ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT Current container:


SHOW CON_NAME;

-- Kill sessions
PROMPT
PROMPT Bước 1: Kill sessions
BEGIN
FOR s IN (
SELECT sid, serial#, username
FROM v$session
WHERE username IN
('QLNS','ADMIN','HOATV','MAIANH','NGUYEN','PHUONG','QUOC')
) LOOP
BEGIN
EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION '''||[Link]||','||
[Link]#||''' IMMEDIATE';
DBMS_OUTPUT.PUT_LINE('>> Đã kill session: ' || [Link]);
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('!! Không thể kill: ' || [Link]);
END;
END LOOP;
END;
/

-- Drop users
PROMPT
PROMPT Bước 2: Drop users
BEGIN
FOR u IN (
SELECT username FROM dba_users
WHERE username IN
('QLNS','ADMIN','HOATV','MAIANH','NGUYEN','PHUONG','QUOC')
) LOOP
BEGIN
EXECUTE IMMEDIATE 'DROP USER '||[Link]||' CASCADE';
DBMS_OUTPUT.PUT_LINE('>> Đã xóa user: ' || [Link]);
EXCEPTION WHEN OTHERS THEN NULL;
END;
END LOOP;
END;
/

-- Drop roles
PROMPT
PROMPT Bước 3: Drop roles
BEGIN
FOR r IN (
SELECT role FROM dba_roles
WHERE role IN
('ROLE_QUANLY_CAP_CAO','ROLE_NHANVIEN_GIAO_DICH','ROLE_NHAN
VIEN_KHO')
) LOOP
BEGIN
EXECUTE IMMEDIATE 'DROP ROLE '||[Link];
DBMS_OUTPUT.PUT_LINE('>> Đã xóa role: ' || [Link]);
EXCEPTION WHEN OTHERS THEN NULL;
END;
END LOOP;
END;
/

-- Drop public synonyms


PROMPT
PROMPT Bước 4: Drop public synonyms
BEGIN
FOR s IN (
SELECT synonym_name FROM dba_synonyms
WHERE owner='PUBLIC' AND synonym_name IN
('SACH','HOADON','KHACHHANG','NHANVIEN')
) LOOP
BEGIN
EXECUTE IMMEDIATE 'DROP PUBLIC SYNONYM '||s.synonym_name;
DBMS_OUTPUT.PUT_LINE('>> Đã xóa synonym: ' || s.synonym_name);
EXCEPTION WHEN OTHERS THEN NULL;
END;
END LOOP;
END;
/

-- Drop profile
PROMPT
PROMPT Bước 5: Drop profile
BEGIN
EXECUTE IMMEDIATE 'DROP PROFILE MyPassword CASCADE';
DBMS_OUTPUT.PUT_LINE('>> Đã xóa profile MyPassword');
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

-- Drop tablespace
PROMPT
PROMPT Bước 6: Drop tablespace
BEGIN
EXECUTE IMMEDIATE 'DROP TABLESPACE QLNS_DATA INCLUDING
CONTENTS AND DATAFILES CASCADE CONSTRAINTS';
DBMS_OUTPUT.PUT_LINE('>> Đã xóa tablespace QLNS_DATA');
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('!! Tablespace: ' || SQLERRM);
END;
/

PROMPT
PROMPT
=========================================================
PROMPT === FILE 1 HOÀN THÀNH ===
PROMPT
=========================================================
PROMPT Môi trường đã được dọn dẹp sạch sẽ
PROMPT Sẵn sàng chạy FILE 2
-- =========================================================
-- FILE 2: CREATE QLNS ENVIRONMENT
-- Tạo môi trường: Tablespace, Profile, Users, Roles
-- CHẠY AS: SYS (SYSDBA)
-- =========================================================
SET SERVEROUTPUT ON SIZE 1000000;
PROMPT
=========================================================
PROMPT === FILE 2: CREATE QLNS ENVIRONMENT ===
PROMPT
=========================================================
ALTER SESSION SET CONTAINER = ORCLPDB;

-- Tạo Tablespace
PROMPT
PROMPT Bước 1: Tạo Tablespace
BEGIN
EXECUTE IMMEDIATE 'DROP TABLESPACE QLNS_DATA INCLUDING
CONTENTS AND DATAFILES';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE TABLESPACE QLNS_DATA
DATAFILE 'C:\USERS\ADMINISTRATOR\
WINDOWS.X64_193000_DB_HOME\DATABASE\QLNS_DATA_01.DBF'
SIZE 100M
AUTOEXTEND ON NEXT 10M MAXSIZE 500M;
PROMPT >> Đã tạo tablespace QLNS_DATA
-- Tạo Profile
PROMPT
PROMPT Bước 2: Tạo Profile
BEGIN
EXECUTE IMMEDIATE 'DROP PROFILE MyPassword CASCADE';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
ALTER SYSTEM SET RESOURCE_LIMIT = TRUE;
CREATE PROFILE MyPassword LIMIT
SESSIONS_PER_USER UNLIMITED
CPU_PER_SESSION UNLIMITED
CONNECT_TIME 60
IDLE_TIME 30
LOGICAL_READS_PER_SESSION UNLIMITED
FAILED_LOGIN_ATTEMPTS 3
PASSWORD_LIFE_TIME 60
PASSWORD_REUSE_TIME 180
PASSWORD_LOCK_TIME 1
PASSWORD_GRACE_TIME 7;
PROMPT >> Đã tạo profile MyPassword

-- Tạo user QLNS


PROMPT
PROMPT Bước 3: Tạo user QLNS
BEGIN
EXECUTE IMMEDIATE 'DROP USER QLNS CASCADE';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE USER QLNS IDENTIFIED BY qlns
DEFAULT TABLESPACE QLNS_DATA
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON QLNS_DATA
PROFILE MyPassword;
PROMPT >> Đã tạo user QLNS

-- Cấp quyền cho QLNS


PROMPT
PROMPT Bước 4: Cấp quyền cho QLNS
GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE
SEQUENCE,
CREATE PROCEDURE, CREATE TRIGGER, UNLIMITED TABLESPACE
TO QLNS;
GRANT EXECUTE ON DBMS_RLS TO QLNS;
GRANT EXECUTE ON DBMS_SESSION TO QLNS;
GRANT EXECUTE ON DBMS_CRYPTO TO QLNS;
GRANT EXECUTE ON UTL_RAW TO QLNS;
GRANT EXEMPT ACCESS POLICY TO QLNS;
GRANT ADMINISTER DATABASE TRIGGER TO QLNS;
GRANT CREATE ANY CONTEXT TO QLNS;
PROMPT >> Đã cấp quyền cho QLNS
-- Tạo users nhân viên
PROMPT
PROMPT Bước 5: Tạo users nhân viên
BEGIN
FOR u IN (
SELECT 'ADMIN' AS uname, 'admin' AS pwd FROM dual UNION ALL
SELECT 'HOATV', 'user01' FROM dual UNION ALL
SELECT 'MAIANH', 'user01' FROM dual UNION ALL
SELECT 'NGUYEN', '123' FROM dual UNION ALL
SELECT 'PHUONG', '123' FROM dual UNION ALL
SELECT 'QUOC', '123' FROM dual
) LOOP
BEGIN
EXECUTE IMMEDIATE 'DROP USER ' || [Link] || ' CASCADE';
EXCEPTION WHEN OTHERS THEN NULL;
END;
EXECUTE IMMEDIATE 'CREATE USER ' || [Link] ||
' IDENTIFIED BY ' || [Link] ||
' PROFILE MyPassword DEFAULT TABLESPACE USERS';
EXECUTE IMMEDIATE 'GRANT CREATE SESSION TO ' || [Link];
DBMS_OUTPUT.PUT_LINE('>> Đã tạo user: ' || [Link]);
END LOOP;
END;
/

-- Tạo public synonyms


PROMPT
PROMPT Bước 6: Tạo public synonyms
BEGIN
EXECUTE IMMEDIATE 'DROP PUBLIC SYNONYM SACH';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE PUBLIC SYNONYM SACH FOR [Link];
BEGIN
EXECUTE IMMEDIATE 'DROP PUBLIC SYNONYM HOADON';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE PUBLIC SYNONYM HOADON FOR [Link];
BEGIN
EXECUTE IMMEDIATE 'DROP PUBLIC SYNONYM KHACHHANG';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE PUBLIC SYNONYM KHACHHANG FOR [Link];
BEGIN
EXECUTE IMMEDIATE 'DROP PUBLIC SYNONYM NHANVIEN';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE PUBLIC SYNONYM NHANVIEN FOR [Link];
PROMPT >> Đã tạo 4 public synonyms
-- Tạo roles
PROMPT
PROMPT Bước 7: Tạo roles
ALTER SESSION SET "_ORACLE_SCRIPT"=TRUE;
BEGIN
FOR r IN (
SELECT 'ROLE_QUANLY_CAP_CAO' AS rname FROM dual UNION ALL
SELECT 'ROLE_NHANVIEN_GIAO_DICH' FROM dual UNION ALL
SELECT 'ROLE_NHANVIEN_KHO' FROM dual
) LOOP
BEGIN
EXECUTE IMMEDIATE 'DROP ROLE ' || [Link];
DBMS_OUTPUT.PUT_LINE('>> Đã xóa role cũ: ' || [Link]);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('>> Bỏ qua lỗi DROP role: ' || [Link] || ' (' ||
SQLERRM || ')');
END;
EXECUTE IMMEDIATE 'CREATE ROLE ' || [Link];
DBMS_OUTPUT.PUT_LINE('>> Đã tạo role: ' || [Link]);
END LOOP;
END;
/
PROMPT >> Đã tạo 3 roles

-- Gán roles cho users


PROMPT
PROMPT Bước 8: Gán roles cho users
-- Clear default roles trước bằng ALTER USER DEFAULT ROLE NONE
ALTER USER ADMIN DEFAULT ROLE NONE;
ALTER USER NGUYEN DEFAULT ROLE NONE;
ALTER USER QUOC DEFAULT ROLE NONE;
ALTER USER MAIANH DEFAULT ROLE NONE;
ALTER USER HOATV DEFAULT ROLE NONE;
ALTER USER PHUONG DEFAULT ROLE NONE;
ALTER USER QLNS DEFAULT ROLE NONE;

-- Revoke roles cũ nếu có (tránh lỗi nếu không tồn tại)


BEGIN
EXECUTE IMMEDIATE 'REVOKE ROLE_QUANLY_CAP_CAO FROM
ADMIN, NGUYEN, QUOC, QLNS';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
BEGIN
EXECUTE IMMEDIATE 'REVOKE ROLE_NHANVIEN_GIAO_DICH FROM
MAIANH, PHUONG, QLNS';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
BEGIN
EXECUTE IMMEDIATE 'REVOKE ROLE_NHANVIEN_KHO FROM HOATV,
PHUONG, QLNS';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

-- Grant roles mới


GRANT ROLE_QUANLY_CAP_CAO TO ADMIN, NGUYEN, QUOC, QLNS;
GRANT ROLE_NHANVIEN_GIAO_DICH TO MAIANH, PHUONG, QLNS;
GRANT ROLE_NHANVIEN_KHO TO HOATV, PHUONG, QLNS;

-- Set default roles


ALTER USER ADMIN DEFAULT ROLE ROLE_QUANLY_CAP_CAO;
ALTER USER NGUYEN DEFAULT ROLE ROLE_QUANLY_CAP_CAO;
ALTER USER QUOC DEFAULT ROLE ROLE_QUANLY_CAP_CAO;
ALTER USER MAIANH DEFAULT ROLE ROLE_NHANVIEN_GIAO_DICH;
ALTER USER HOATV DEFAULT ROLE ROLE_NHANVIEN_KHO;
ALTER USER PHUONG DEFAULT ROLE ALL;
ALTER USER QLNS DEFAULT ROLE ALL;
PROMPT >> Đã gán roles

-- Kiểm tra
PROMPT
PROMPT Kiểm tra users
SELECT username, account_status, profile
FROM dba_users
WHERE username IN
('QLNS','ADMIN','HOATV','MAIANH','NGUYEN','PHUONG','QUOC');

PROMPT
PROMPT
=========================================================
PROMPT === FILE 2 HOÀN THÀNH ===
PROMPT
=========================================================
PROMPT Môi trường đã sẵn sàng
PROMPT Disconnect SYS, Connect QLNS để chạy FILE 3

-- =========================================================
-- FILE 3: CREATE SCHEMA QLNS
-- Tạo bảng, dữ liệu, functions, procedures, triggers, VPD
-- CHẠY AS: QLNS
-- =========================================================
SET SERVEROUTPUT ON SIZE 1000000;
PROMPT
=========================================================
PROMPT === FILE 3: CREATE SCHEMA QLNS ===
PROMPT
=========================================================
ALTER SESSION SET CONTAINER = ORCLPDB;
SHOW USER;
-- Xóa toàn bộ bảng cũ
PROMPT
PROMPT Bước 1: Xóa bảng cũ (nếu có)
BEGIN
FOR t IN (SELECT table_name FROM user_tables) LOOP
EXECUTE IMMEDIATE 'DROP TABLE ' || t.table_name || ' CASCADE
CONSTRAINTS';
END LOOP;
DBMS_OUTPUT.PUT_LINE('>> Đã xóa tất cả bảng cũ');
END;
/
-- Tạo bảng SACH
PROMPT
PROMPT Bước 2: Tạo bảng SACH
CREATE TABLE Sach (
MaSach VARCHAR2(10) CONSTRAINT PK_Sach PRIMARY KEY,
TenSach NVARCHAR2(100) NOT NULL,
TacGia NVARCHAR2(100),
NhaXuatBan NVARCHAR2(100),
NamXuatBan NUMBER(4) CHECK (NamXuatBan >= 1900),
TheLoai NVARCHAR2(50),
GiaBan NUMBER(10,2) CHECK (GiaBan >= 0),
SoLuongTon NUMBER(10) DEFAULT 0 CHECK (SoLuongTon >= 0),
MoTa NVARCHAR2(1000),
HinhBia NVARCHAR2(200),
TrangThaiKhuyenMai NVARCHAR2(50)
);
PROMPT >> Đã tạo bảng SACH
-- Tạo bảng KHACHHANG
PROMPT
PROMPT Bước 3: Tạo bảng KHACHHANG
CREATE TABLE KhachHang (
MaKH VARCHAR2(10) CONSTRAINT PK_KhachHang PRIMARY KEY,
HoTen NVARCHAR2(100) NOT NULL,
SoDienThoai VARCHAR2(15),
Email NVARCHAR2(100),
DiaChi NVARCHAR2(200),
DiemTichLuy NUMBER(10) DEFAULT 0 CHECK (DiemTichLuy >= 0),
NgayDangKy DATE DEFAULT SYSDATE
);
ALTER TABLE KhachHang ADD (
EMAIL_ENC1 VARCHAR2(1000),
EMAIL_ENC2 VARCHAR2(1000)
);
PROMPT >> Đã tạo bảng KHACHHANG
-- Tạo bảng NHANVIEN
PROMPT
PROMPT Bước 4: Tạo bảng NHANVIEN
CREATE TABLE NhanVien (
MaNV VARCHAR2(10) CONSTRAINT PK_NhanVien PRIMARY KEY,
HoTen NVARCHAR2(100) NOT NULL,
ChucVu NVARCHAR2(50),
TenDangNhap NVARCHAR2(50) UNIQUE NOT NULL,
MatKhau_HASH NVARCHAR2(256),
Salt NVARCHAR2(100) NOT NULL,
QuyenHan NVARCHAR2(10) DEFAULT 'User' CHECK (QuyenHan IN
('Admin','User')),
NgayVaoLam DATE DEFAULT SYSDATE,
MatKhau_Goc NVARCHAR2(256)
);
PROMPT >> Đã tạo bảng NHANVIEN
-- Tạo bảng HOADON
PROMPT
PROMPT Bước 5: Tạo bảng HOADON
CREATE TABLE HoaDon (
MaHD VARCHAR2(10) CONSTRAINT PK_HoaDon PRIMARY KEY,
NgayLap DATE DEFAULT SYSDATE,
MaKH VARCHAR2(10),
MaNV VARCHAR2(10),
TongTien NUMBER(12,2) DEFAULT 0 CHECK (TongTien >= 0),
ChietKhau NUMBER(5,2) DEFAULT 0 CHECK (ChietKhau BETWEEN 0 AND
100),
Thue NUMBER(5,2) DEFAULT 0 CHECK (Thue BETWEEN 0 AND 100),
TrangThai NVARCHAR2(30) DEFAULT 'CHO_XAC_NHAN',
ChuKyRSA CLOB,
NgayKy DATE,
CONSTRAINT FK_HoaDon_KhachHang FOREIGN KEY (MaKH) REFERENCES
KhachHang(MaKH) ON DELETE SET NULL,
CONSTRAINT FK_HoaDon_NhanVien FOREIGN KEY (MaNV) REFERENCES
NhanVien(MaNV) ON DELETE SET NULL
);
PROMPT >> Đã tạo bảng HOADON
-- Tạo bảng CHITIETHOADON
PROMPT
PROMPT Bước 6: Tạo bảng CHITIETHOADON
CREATE TABLE ChiTietHoaDon (
MaCTHD VARCHAR2(10) CONSTRAINT PK_ChiTietHoaDon PRIMARY KEY,
MaHD VARCHAR2(10) NOT NULL,
MaSach VARCHAR2(10) NOT NULL,
SoLuong NUMBER(10) DEFAULT 1 CHECK (SoLuong > 0),
DonGia NUMBER(10,2) CHECK (DonGia >= 0),
CONSTRAINT FK_CTHD_HoaDon FOREIGN KEY (MaHD) REFERENCES
HoaDon(MaHD) ON DELETE CASCADE,
CONSTRAINT FK_CTHD_Sach FOREIGN KEY (MaSach) REFERENCES
Sach(MaSach) ON DELETE SET NULL
);
PROMPT >> Đã tạo bảng CHITIETHOADON
-- Tạo bảng KEYSTORE
PROMPT
PROMPT Bước 7: Tạo bảng KEYSTORE
CREATE TABLE KeyStore (
KeyID NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
PublicKey CLOB,
PrivateKey CLOB,
CreatedAt DATE DEFAULT SYSDATE
);
PROMPT >> Đã tạo bảng KEYSTORE
-- Tạo bảng LOGHEOTHONG
PROMPT
PROMPT Bước 8: Tạo bảng LOGHETHONG
CREATE TABLE LogHeThong (
MaLog VARCHAR2(10) CONSTRAINT PK_LogHeThong PRIMARY KEY,
ThaoTac NVARCHAR2(100),
ThoiGian DATE DEFAULT SYSDATE,
MaNV VARCHAR2(10),
MoTa NVARCHAR2(1000),
CONSTRAINT FK_Log_NhanVien FOREIGN KEY (MaNV) REFERENCES
NhanVien(MaNV) ON DELETE SET NULL
);
PROMPT >> Đã tạo bảng LOGHETHONG
-- Tạo Sequence + Trigger cho NHANVIEN
PROMPT
PROMPT Bước 9: Tạo sequence cho NHANVIEN
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE NhanVien_SEQ';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE SEQUENCE NhanVien_SEQ
START WITH 7
INCREMENT BY 1
NOCACHE
NOCYCLE;
PROMPT >> Đã tạo sequence NhanVien_SEQ
CREATE OR REPLACE TRIGGER TRG_NHANVIEN_AUTOMANV
BEFORE INSERT ON NhanVien
FOR EACH ROW
BEGIN
IF :[Link] IS NULL OR TRIM(:[Link]) = '' THEN
:[Link] := 'NV' || LPAD(NhanVien_SEQ.NEXTVAL, 3, '0');
END IF;
END;
/
PROMPT >> Đã tạo trigger TRG_NHANVIEN_AUTOMANV
-- Tạo hàm HASH password
PROMPT
PROMPT Bước 10: Tạo hàm hash password
-- Lệnh ALTER được comment vì cột MatKhau_HASH đã cho phép NULL từ
CREATE TABLE
-- ALTER TABLE NhanVien MODIFY (MatKhau_HASH NVARCHAR2(256)
NULL);
CREATE OR REPLACE FUNCTION FN_HASH_PASSWORD(p_password
VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
RETURN RAWTOHEX(DBMS_CRYPTO.HASH(
UTL_I18N.STRING_TO_RAW(p_password, 'AL32UTF8'),
DBMS_CRYPTO.HASH_SH256
));
END;
/
PROMPT >> Đã tạo function FN_HASH_PASSWORD
CREATE OR REPLACE PROCEDURE PROC_HASH_MATKHAU_NV
IS
BEGIN
FOR r IN (SELECT MaNV, MatKhau_Goc FROM NhanVien WHERE
MatKhau_Goc IS NOT NULL) LOOP
UPDATE NhanVien
SET MatKhau_HASH = FN_HASH_PASSWORD(r.MatKhau_Goc)
WHERE MaNV = [Link];
END LOOP;
COMMIT;
END;
/
PROMPT >> Đã tạo procedure PROC_HASH_MATKHAU_NV
-- Tạo hàm mã hóa AES
PROMPT
PROMPT Bước 11: Tạo hàm mã hóa AES
CREATE OR REPLACE FUNCTION encrypt_email_aes(p_email IN VARCHAR2)
RETURN CLOB
IS
l_key_raw RAW(32);
l_iv_raw RAW(16);
l_enc_raw RAW(32767);
l_enc_b64 VARCHAR2(32767);
l_key_b64 VARCHAR2(32767);
l_iv_b64 VARCHAR2(32767);
l_json CLOB;
BEGIN
l_key_raw := DBMS_CRYPTO.RANDOMBYTES(32);
l_iv_raw := DBMS_CRYPTO.RANDOMBYTES(16);
l_enc_raw := DBMS_CRYPTO.ENCRYPT(
src => UTL_I18N.STRING_TO_RAW(NVL(p_email, ''), 'AL32UTF8'),
typ => DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC +
DBMS_CRYPTO.PAD_PKCS5,
key => l_key_raw,
iv => l_iv_raw
);
l_enc_b64 :=
REPLACE(UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCOD
E(l_enc_raw)), CHR(10));
l_key_b64 :=
REPLACE(UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCOD
E(l_key_raw)), CHR(10));
l_iv_b64 :=
REPLACE(UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCOD
E(l_iv_raw)), CHR(10));
l_json := TO_CLOB('{"ciphertext_b64":"') || l_enc_b64 ||
'","aes_key_b64":"' || l_key_b64 ||
'","iv_b64":"' || l_iv_b64 || '"}';
RETURN l_json;
END;
/
PROMPT >> Đã tạo function encrypt_email_aes
PROMPT
PROMPT
=========================================================
PROMPT === PHẦN 1 HOÀN THÀNH: CẤU TRÚC BẢNG ===
PROMPT
=========================================================
-- =========================================================
-- PHẦN 2: INSERT DỮ LIỆU MẪU
-- =========================================================
-- Insert SACH
PROMPT
PROMPT Bước 12: Insert dữ liệu SACH
INSERT ALL
INTO Sach VALUES ('S001', N'Truyện Kiều', N'Nguyễn Du', N'NXB Văn Học',
2015, N'Truyện thơ', 55000, 30, N'Tác phẩm kinh điển', 'truyen_kieu.jpg', N'Không')
INTO Sach VALUES ('S002', N'Doraemon Tập 1', N'Fujiko F. Fujio', N'NXB Kim
Đồng', 2020, N'Thiếu nhi', 25000, 50, N'Truyện tranh Nhật Bản', '[Link]',
N'Không')
INTO Sach VALUES ('S003', N'Conan Tập 100', N'Aoyama Gosho', N'NXB Kim
Đồng', 2022, N'Truyện tranh', 28000, 40, N'Thám tử Conan', '[Link]', N'Giảm
giá')
INTO Sach VALUES ('S004', N'Lập Trình C# Cơ Bản', N'Nguyễn Văn A', N'NXB
CNTT', 2023, N'Giáo trình', 95000, 20, N'Học lập trình C#', '[Link]',
N'Không')
SELECT * FROM dual;
PROMPT >> Đã insert 4 sách
-- Insert KHACHHANG
PROMPT
PROMPT Bước 13: Insert dữ liệu KHACHHANG
INSERT ALL
INTO KhachHang VALUES ('KH001', N'Nguyễn Văn Minh', '0912345678',
'minh@[Link]', N'Hà Nội', 120, SYSDATE - 20, NULL, NULL)
INTO KhachHang VALUES ('KH002', N'Lê Thị Hạnh', '0987654321',
'hanh@[Link]', N'Đà Nẵng', 300, SYSDATE - 50, NULL, NULL)
INTO KhachHang VALUES ('KH003', N'Phạm Quốc Cường', '0905123456',
'cuong@[Link]', N'Hồ Chí Minh', 50, SYSDATE - 10, NULL, NULL)
SELECT * FROM dual;
PROMPT >> Đã insert 3 khách hàng
-- Insert NHANVIEN
PROMPT
PROMPT Bước 14: Insert dữ liệu NHANVIEN
INSERT ALL
INTO NhanVien VALUES ('NV001', N'Nguyễn Thị Lan', N'Quản lý', 'admin', NULL,
'salt_abc', 'Admin', SYSDATE - 100, 'admin')
INTO NhanVien VALUES ('NV002', N'Trần Văn Hòa', N'Nhân viên bán hàng',
'hoatv', NULL, 'salt_xyz', 'User', SYSDATE - 20, 'user01')
INTO NhanVien VALUES ('NV003', N'Phạm Mai Anh', N'Nhân viên kho', 'maianh',
NULL, 'salt_def', 'User', SYSDATE - 15, 'user01')
INTO NhanVien VALUES ('NV004', N'Trần Bảo Nguyên', N'Quản lý', 'Nguyen',
NULL, 'salt_ghi', 'Admin', SYSDATE - 15, '123')
INTO NhanVien VALUES ('NV005', N'Trần Thị Minh Phương', N'Quản lý', 'Phuong',
NULL, 'salt_jkl', 'Admin', SYSDATE - 15, '123')
INTO NhanVien VALUES ('NV006', N'Lê Hồng Quốc', N'Quản lý', 'Quoc', NULL,
'salt_mno', 'Admin', SYSDATE - 15, '123')
SELECT * FROM dual;
PROMPT >> Đã insert 6 nhân viên
-- Cập nhật QuyenHan
UPDATE NhanVien SET QuyenHan = 'Admin' WHERE TenDangNhap IN ('admin',
'Nguyen', 'Phuong', 'Quoc');
UPDATE NhanVien SET QuyenHan = 'User' WHERE TenDangNhap IN ('hoatv',
'maianh');
COMMIT;
PROMPT >> Đã cập nhật QuyenHan
-- Insert HOADON
PROMPT
PROMPT Bước 15: Insert dữ liệu HOADON
INSERT ALL
INTO HoaDon VALUES ('HD001', SYSDATE - 12, 'KH001', 'NV002', 150000, 0, 5,
'CHO_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD002', SYSDATE - 10, 'KH002', 'NV002', 28000, 10, 0,
'DA_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD003', SYSDATE - 8, 'KH003', 'NV003', 110000, 5, 0,
'CHO_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD004', SYSDATE - 7, 'KH001', 'NV005', 78000, 0, 0,
'DA_THANH_TOAN', NULL, NULL)
INTO HoaDon VALUES ('HD005', SYSDATE - 6, 'KH002', 'NV004', 55000, 0, 10,
'DA_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD006', SYSDATE - 5, 'KH003', 'NV001', 120000, 15, 5,
'DA_THANH_TOAN', NULL, NULL)
INTO HoaDon VALUES ('HD007', SYSDATE - 4, 'KH001', 'NV002', 56000, 0, 0,
'CHO_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD008', SYSDATE - 3, 'KH003', 'NV003', 75000, 0, 5,
'DA_THANH_TOAN', NULL, NULL)
INTO HoaDon VALUES ('HD009', SYSDATE - 2, 'KH002', 'NV006', 205000, 5, 0,
'DA_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD010', SYSDATE - 1, 'KH001', 'NV005', 95000, 0, 0,
'CHO_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD011', SYSDATE, 'KH003', 'NV004', 55000, 0, 0,
'DA_THANH_TOAN', NULL, NULL)
INTO HoaDon VALUES ('HD012', SYSDATE, 'KH002', 'NV002', 123000, 10, 5,
'DA_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD013', SYSDATE, 'KH001', 'NV003', 80000, 0, 0,
'CHO_XAC_NHAN', NULL, NULL)
SELECT * FROM dual;
PROMPT >> Đã insert 13 hóa đơn
-- Insert CHITIETHOADON
PROMPT
PROMPT Bước 16: Insert dữ liệu CHITIETHOADON
INSERT ALL
INTO ChiTietHoaDon VALUES ('CT001', 'HD001', 'S001', 1, 55000)
INTO ChiTietHoaDon VALUES ('CT002', 'HD001', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT003', 'HD002', 'S003', 1, 28000)
INTO ChiTietHoaDon VALUES ('CT004', 'HD003', 'S001', 2, 55000)
INTO ChiTietHoaDon VALUES ('CT005', 'HD004', 'S002', 2, 25000)
INTO ChiTietHoaDon VALUES ('CT006', 'HD004', 'S003', 1, 28000)
INTO ChiTietHoaDon VALUES ('CT007', 'HD005', 'S001', 1, 55000)
INTO ChiTietHoaDon VALUES ('CT008', 'HD006', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT009', 'HD006', 'S002', 1, 25000)
INTO ChiTietHoaDon VALUES ('CT010', 'HD007', 'S003', 2, 28000)
INTO ChiTietHoaDon VALUES ('CT011', 'HD008', 'S002', 3, 25000)
INTO ChiTietHoaDon VALUES ('CT012', 'HD009', 'S001', 2, 55000)
INTO ChiTietHoaDon VALUES ('CT013', 'HD009', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT014', 'HD010', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT015', 'HD011', 'S001', 1, 55000)
INTO ChiTietHoaDon VALUES ('CT016', 'HD012', 'S003', 1, 28000)
INTO ChiTietHoaDon VALUES ('CT017', 'HD012', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT018', 'HD013', 'S001', 1, 55000)
INTO ChiTietHoaDon VALUES ('CT019', 'HD013', 'S002', 1, 25000)
SELECT * FROM dual;
PROMPT >> Đã insert 19 chi tiết hóa đơn
COMMIT;
-- Hash mật khẩu
PROMPT
PROMPT Bước 17: Hash mật khẩu nhân viên
EXEC PROC_HASH_MATKHAU_NV;
PROMPT >> Đã hash mật khẩu
-- Kiểm tra dữ liệu
PROMPT
PROMPT Bước 18: Kiểm tra dữ liệu
SELECT COUNT(*) AS TOTAL_SACH FROM Sach;
SELECT COUNT(*) AS TOTAL_KHACHHANG FROM KhachHang;
SELECT COUNT(*) AS TOTAL_NHANVIEN FROM NhanVien;
SELECT COUNT(*) AS TOTAL_HOADON FROM HoaDon;
SELECT COUNT(*) AS TOTAL_CTHD FROM ChiTietHoaDon;
PROMPT
PROMPT
=========================================================
PROMPT === PHẦN 2 HOÀN THÀNH: DỮ LIỆU ===
PROMPT
=========================================================

-- =========================================================
-- FILE 3: CREATE SCHEMA QLNS
-- Tạo bảng, dữ liệu, functions, procedures, triggers, VPD
-- CHẠY AS: QLNS
-- =========================================================
SET SERVEROUTPUT ON SIZE 1000000;
PROMPT
=========================================================
PROMPT === FILE 3: CREATE SCHEMA QLNS ===
PROMPT
=========================================================
ALTER SESSION SET CONTAINER = ORCLPDB;
SHOW USER;

-- Xóa toàn bộ bảng cũ


PROMPT
PROMPT Bước 1: Xóa bảng cũ (nếu có)
BEGIN
FOR t IN (SELECT table_name FROM user_tables) LOOP
EXECUTE IMMEDIATE 'DROP TABLE ' || t.table_name || ' CASCADE
CONSTRAINTS';
END LOOP;
DBMS_OUTPUT.PUT_LINE('>> Đã xóa tất cả bảng cũ');
END;
/

-- Tạo bảng SACH


PROMPT
PROMPT Bước 2: Tạo bảng SACH
CREATE TABLE Sach (
MaSach VARCHAR2(10) CONSTRAINT PK_Sach PRIMARY KEY,
TenSach NVARCHAR2(100) NOT NULL,
TacGia NVARCHAR2(100),
NhaXuatBan NVARCHAR2(100),
NamXuatBan NUMBER(4) CHECK (NamXuatBan >= 1900),
TheLoai NVARCHAR2(50),
GiaBan NUMBER(10,2) CHECK (GiaBan >= 0),
SoLuongTon NUMBER(10) DEFAULT 0 CHECK (SoLuongTon >= 0),
MoTa NVARCHAR2(1000),
HinhBia NVARCHAR2(200),
TrangThaiKhuyenMai NVARCHAR2(50)
);
PROMPT >> Đã tạo bảng SACH

-- Tạo bảng KHACHHANG


PROMPT
PROMPT Bước 3: Tạo bảng KHACHHANG
CREATE TABLE KhachHang (
MaKH VARCHAR2(10) CONSTRAINT PK_KhachHang PRIMARY KEY,
HoTen NVARCHAR2(100) NOT NULL,
SoDienThoai VARCHAR2(15),
Email NVARCHAR2(100),
DiaChi NVARCHAR2(200),
DiemTichLuy NUMBER(10) DEFAULT 0 CHECK (DiemTichLuy >= 0),
NgayDangKy DATE DEFAULT SYSDATE
);
ALTER TABLE KhachHang ADD (
EMAIL_ENC1 VARCHAR2(1000),
EMAIL_ENC2 VARCHAR2(1000)
);
PROMPT >> Đã tạo bảng KHACHHANG

-- Tạo bảng NHANVIEN


PROMPT
PROMPT Bước 4: Tạo bảng NHANVIEN
CREATE TABLE NhanVien (
MaNV VARCHAR2(10) CONSTRAINT PK_NhanVien PRIMARY KEY,
HoTen NVARCHAR2(100) NOT NULL,
ChucVu NVARCHAR2(50),
TenDangNhap NVARCHAR2(50) UNIQUE NOT NULL,
MatKhau_HASH NVARCHAR2(256),
Salt NVARCHAR2(100) NOT NULL,
QuyenHan NVARCHAR2(10) DEFAULT 'User' CHECK (QuyenHan IN
('Admin','User')),
NgayVaoLam DATE DEFAULT SYSDATE,
MatKhau_Goc NVARCHAR2(256)
);
PROMPT >> Đã tạo bảng NHANVIEN

-- Tạo bảng HOADON


PROMPT
PROMPT Bước 5: Tạo bảng HOADON
CREATE TABLE HoaDon (
MaHD VARCHAR2(10) CONSTRAINT PK_HoaDon PRIMARY KEY,
NgayLap DATE DEFAULT SYSDATE,
MaKH VARCHAR2(10),
MaNV VARCHAR2(10),
TongTien NUMBER(12,2) DEFAULT 0 CHECK (TongTien >= 0),
ChietKhau NUMBER(5,2) DEFAULT 0 CHECK (ChietKhau BETWEEN 0 AND
100),
Thue NUMBER(5,2) DEFAULT 0 CHECK (Thue BETWEEN 0 AND 100),
TrangThai NVARCHAR2(30) DEFAULT 'CHO_XAC_NHAN',
ChuKyRSA CLOB,
NgayKy DATE,
CONSTRAINT FK_HoaDon_KhachHang FOREIGN KEY (MaKH)
REFERENCES KhachHang(MaKH) ON DELETE SET NULL,
CONSTRAINT FK_HoaDon_NhanVien FOREIGN KEY (MaNV) REFERENCES
NhanVien(MaNV) ON DELETE SET NULL
);
PROMPT >> Đã tạo bảng HOADON

-- Tạo bảng CHITIETHOADON


PROMPT
PROMPT Bước 6: Tạo bảng CHITIETHOADON
CREATE TABLE ChiTietHoaDon (
MaCTHD VARCHAR2(10) CONSTRAINT PK_ChiTietHoaDon PRIMARY KEY,
MaHD VARCHAR2(10) NOT NULL,
MaSach VARCHAR2(10) NOT NULL,
SoLuong NUMBER(10) DEFAULT 1 CHECK (SoLuong > 0),
DonGia NUMBER(10,2) CHECK (DonGia >= 0),
CONSTRAINT FK_CTHD_HoaDon FOREIGN KEY (MaHD) REFERENCES
HoaDon(MaHD) ON DELETE CASCADE,
CONSTRAINT FK_CTHD_Sach FOREIGN KEY (MaSach) REFERENCES
Sach(MaSach) ON DELETE SET NULL
);
PROMPT >> Đã tạo bảng CHITIETHOADON

-- Tạo bảng KEYSTORE


PROMPT
PROMPT Bước 7: Tạo bảng KEYSTORE
CREATE TABLE KeyStore (
KeyID NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
PublicKey CLOB,
PrivateKey CLOB,
CreatedAt DATE DEFAULT SYSDATE
);
PROMPT >> Đã tạo bảng KEYSTORE

-- Tạo bảng LOGHEOTHONG


PROMPT
PROMPT Bước 8: Tạo bảng LOGHETHONG
CREATE TABLE LogHeThong (
MaLog VARCHAR2(10) CONSTRAINT PK_LogHeThong PRIMARY KEY,
ThaoTac NVARCHAR2(100),
ThoiGian DATE DEFAULT SYSDATE,
MaNV VARCHAR2(10),
MoTa NVARCHAR2(1000),
CONSTRAINT FK_Log_NhanVien FOREIGN KEY (MaNV) REFERENCES
NhanVien(MaNV) ON DELETE SET NULL
);
PROMPT >> Đã tạo bảng LOGHETHONG

-- Tạo Sequence + Trigger cho NHANVIEN


PROMPT
PROMPT Bước 9: Tạo sequence cho NHANVIEN
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE NhanVien_SEQ';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE SEQUENCE NhanVien_SEQ
START WITH 7
INCREMENT BY 1
NOCACHE
NOCYCLE;
PROMPT >> Đã tạo sequence NhanVien_SEQ

CREATE OR REPLACE TRIGGER TRG_NHANVIEN_AUTOMANV


BEFORE INSERT ON NhanVien
FOR EACH ROW
BEGIN
IF :[Link] IS NULL OR TRIM(:[Link]) = '' THEN
:[Link] := 'NV' || LPAD(NhanVien_SEQ.NEXTVAL, 3, '0');
END IF;
END;
/
PROMPT >> Đã tạo trigger TRG_NHANVIEN_AUTOMANV

-- Tạo hàm HASH password


PROMPT
PROMPT Bước 10: Tạo hàm hash password
-- Lệnh ALTER được wrap exception vì cột MatKhau_HASH đã cho phép NULL từ
CREATE TABLE
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE NhanVien MODIFY (MatKhau_HASH
NVARCHAR2(256) NULL)';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

CREATE OR REPLACE FUNCTION FN_HASH_PASSWORD(p_password


VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
RETURN RAWTOHEX(DBMS_CRYPTO.HASH(
UTL_I18N.STRING_TO_RAW(p_password, 'AL32UTF8'),
DBMS_CRYPTO.HASH_SH256
));
END;
/
PROMPT >> Đã tạo function FN_HASH_PASSWORD

CREATE OR REPLACE PROCEDURE PROC_HASH_MATKHAU_NV


IS
BEGIN
FOR r IN (SELECT MaNV, MatKhau_Goc FROM NhanVien WHERE
MatKhau_Goc IS NOT NULL) LOOP
UPDATE NhanVien
SET MatKhau_HASH = FN_HASH_PASSWORD(r.MatKhau_Goc)
WHERE MaNV = [Link];
END LOOP;
COMMIT;
END;
/
PROMPT >> Đã tạo procedure PROC_HASH_MATKHAU_NV

-- Tạo hàm mã hóa AES


PROMPT
PROMPT Bước 11: Tạo hàm mã hóa AES
CREATE OR REPLACE FUNCTION encrypt_email_aes(p_email IN VARCHAR2)
RETURN CLOB
IS
l_key_raw RAW(32);
l_iv_raw RAW(16);
l_enc_raw RAW(32767);
l_enc_b64 VARCHAR2(32767);
l_key_b64 VARCHAR2(32767);
l_iv_b64 VARCHAR2(32767);
l_json CLOB;
BEGIN
l_key_raw := DBMS_CRYPTO.RANDOMBYTES(32);
l_iv_raw := DBMS_CRYPTO.RANDOMBYTES(16);
l_enc_raw := DBMS_CRYPTO.ENCRYPT(
src => UTL_I18N.STRING_TO_RAW(NVL(p_email, ''), 'AL32UTF8'),
typ => DBMS_CRYPTO.ENCRYPT_AES256 +
DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5,
key => l_key_raw,
iv => l_iv_raw
);
l_enc_b64 :=
REPLACE(UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCOD
E(l_enc_raw)), CHR(10));
l_key_b64 :=
REPLACE(UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCOD
E(l_key_raw)), CHR(10));
l_iv_b64 :=
REPLACE(UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCOD
E(l_iv_raw)), CHR(10));
l_json := TO_CLOB('{"ciphertext_b64":"') || l_enc_b64 ||
'","aes_key_b64":"' || l_key_b64 ||
'","iv_b64":"' || l_iv_b64 || '"}';
RETURN l_json;
END;
/
PROMPT >> Đã tạo function encrypt_email_aes

PROMPT
PROMPT
=========================================================
PROMPT === PHẦN 1 HOÀN THÀNH: CẤU TRÚC BẢNG ===
PROMPT
=========================================================

-- =========================================================
-- PHẦN 2: INSERT DỮ LIỆU MẪU
-- =========================================================

-- Insert SACH
PROMPT
PROMPT Bước 12: Insert dữ liệu SACH
INSERT ALL
INTO Sach VALUES ('S001', N'Truyện Kiều', N'Nguyễn Du', N'NXB Văn Học',
2015, N'Truyện thơ', 55000, 30, N'Tác phẩm kinh điển', 'truyen_kieu.jpg', N'Không')
INTO Sach VALUES ('S002', N'Doraemon Tập 1', N'Fujiko F. Fujio', N'NXB Kim
Đồng', 2020, N'Thiếu nhi', 25000, 50, N'Truyện tranh Nhật Bản', '[Link]',
N'Không')
INTO Sach VALUES ('S003', N'Conan Tập 100', N'Aoyama Gosho', N'NXB Kim
Đồng', 2022, N'Truyện tranh', 28000, 40, N'Thám tử Conan', '[Link]', N'Giảm
giá')
INTO Sach VALUES ('S004', N'Lập Trình C# Cơ Bản', N'Nguyễn Văn A', N'NXB
CNTT', 2023, N'Giáo trình', 95000, 20, N'Học lập trình C#', '[Link]',
N'Không')
SELECT * FROM dual;
PROMPT >> Đã insert 4 sách

-- Insert KHACHHANG
PROMPT
PROMPT Bước 13: Insert dữ liệu KHACHHANG
INSERT ALL
INTO KhachHang VALUES ('KH001', N'Nguyễn Văn Minh', '0912345678',
'minh@[Link]', N'Hà Nội', 120, SYSDATE - 20, NULL, NULL)
INTO KhachHang VALUES ('KH002', N'Lê Thị Hạnh', '0987654321',
'hanh@[Link]', N'Đà Nẵng', 300, SYSDATE - 50, NULL, NULL)
INTO KhachHang VALUES ('KH003', N'Phạm Quốc Cường', '0905123456',
'cuong@[Link]', N'Hồ Chí Minh', 50, SYSDATE - 10, NULL, NULL)
SELECT * FROM dual;
PROMPT >> Đã insert 3 khách hàng

-- Insert NHANVIEN
PROMPT
PROMPT Bước 14: Insert dữ liệu NHANVIEN
INSERT ALL
INTO NhanVien VALUES ('NV001', N'Nguyễn Thị Lan', N'Quản lý', 'admin',
NULL, 'salt_abc', 'Admin', SYSDATE - 100, 'admin')
INTO NhanVien VALUES ('NV002', N'Trần Văn Hòa', N'Nhân viên bán hàng',
'hoatv', NULL, 'salt_xyz', 'User', SYSDATE - 20, 'user01')
INTO NhanVien VALUES ('NV003', N'Phạm Mai Anh', N'Nhân viên kho',
'maianh', NULL, 'salt_def', 'User', SYSDATE - 15, 'user01')
INTO NhanVien VALUES ('NV004', N'Trần Bảo Nguyên', N'Quản lý', 'Nguyen',
NULL, 'salt_ghi', 'Admin', SYSDATE - 15, '123')
INTO NhanVien VALUES ('NV005', N'Trần Thị Minh Phương', N'Quản lý',
'Phuong', NULL, 'salt_jkl', 'Admin', SYSDATE - 15, '123')
INTO NhanVien VALUES ('NV006', N'Lê Hồng Quốc', N'Quản lý', 'Quoc', NULL,
'salt_mno', 'Admin', SYSDATE - 15, '123')
SELECT * FROM dual;
PROMPT >> Đã insert 6 nhân viên

-- Cập nhật QuyenHan


UPDATE NhanVien SET QuyenHan = 'Admin' WHERE TenDangNhap IN ('admin',
'Nguyen', 'Phuong', 'Quoc');
UPDATE NhanVien SET QuyenHan = 'User' WHERE TenDangNhap IN ('hoatv',
'maianh');
COMMIT;
PROMPT >> Đã cập nhật QuyenHan

-- Insert HOADON
PROMPT
PROMPT Bước 15: Insert dữ liệu HOADON
INSERT ALL
INTO HoaDon VALUES ('HD001', SYSDATE - 12, 'KH001', 'NV002', 150000, 0,
5, 'CHO_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD002', SYSDATE - 10, 'KH002', 'NV002', 28000, 10,
0, 'DA_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD003', SYSDATE - 8, 'KH003', 'NV003', 110000, 5, 0,
'CHO_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD004', SYSDATE - 7, 'KH001', 'NV005', 78000, 0, 0,
'DA_THANH_TOAN', NULL, NULL)
INTO HoaDon VALUES ('HD005', SYSDATE - 6, 'KH002', 'NV004', 55000, 0, 10,
'DA_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD006', SYSDATE - 5, 'KH003', 'NV001', 120000, 15,
5, 'DA_THANH_TOAN', NULL, NULL)
INTO HoaDon VALUES ('HD007', SYSDATE - 4, 'KH001', 'NV002', 56000, 0, 0,
'CHO_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD008', SYSDATE - 3, 'KH003', 'NV003', 75000, 0, 5,
'DA_THANH_TOAN', NULL, NULL)
INTO HoaDon VALUES ('HD009', SYSDATE - 2, 'KH002', 'NV006', 205000, 5, 0,
'DA_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD010', SYSDATE - 1, 'KH001', 'NV005', 95000, 0, 0,
'CHO_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD011', SYSDATE, 'KH003', 'NV004', 55000, 0, 0,
'DA_THANH_TOAN', NULL, NULL)
INTO HoaDon VALUES ('HD012', SYSDATE, 'KH002', 'NV002', 123000, 10, 5,
'DA_XAC_NHAN', NULL, NULL)
INTO HoaDon VALUES ('HD013', SYSDATE, 'KH001', 'NV003', 80000, 0, 0,
'CHO_XAC_NHAN', NULL, NULL)
SELECT * FROM dual;
PROMPT >> Đã insert 13 hóa đơn

-- Insert CHITIETHOADON
PROMPT
PROMPT Bước 16: Insert dữ liệu CHITIETHOADON
INSERT ALL
INTO ChiTietHoaDon VALUES ('CT001', 'HD001', 'S001', 1, 55000)
INTO ChiTietHoaDon VALUES ('CT002', 'HD001', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT003', 'HD002', 'S003', 1, 28000)
INTO ChiTietHoaDon VALUES ('CT004', 'HD003', 'S001', 2, 55000)
INTO ChiTietHoaDon VALUES ('CT005', 'HD004', 'S002', 2, 25000)
INTO ChiTietHoaDon VALUES ('CT006', 'HD004', 'S003', 1, 28000)
INTO ChiTietHoaDon VALUES ('CT007', 'HD005', 'S001', 1, 55000)
INTO ChiTietHoaDon VALUES ('CT008', 'HD006', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT009', 'HD006', 'S002', 1, 25000)
INTO ChiTietHoaDon VALUES ('CT010', 'HD007', 'S003', 2, 28000)
INTO ChiTietHoaDon VALUES ('CT011', 'HD008', 'S002', 3, 25000)
INTO ChiTietHoaDon VALUES ('CT012', 'HD009', 'S001', 2, 55000)
INTO ChiTietHoaDon VALUES ('CT013', 'HD009', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT014', 'HD010', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT015', 'HD011', 'S001', 1, 55000)
INTO ChiTietHoaDon VALUES ('CT016', 'HD012', 'S003', 1, 28000)
INTO ChiTietHoaDon VALUES ('CT017', 'HD012', 'S004', 1, 95000)
INTO ChiTietHoaDon VALUES ('CT018', 'HD013', 'S001', 1, 55000)
INTO ChiTietHoaDon VALUES ('CT019', 'HD013', 'S002', 1, 25000)
SELECT * FROM dual;
PROMPT >> Đã insert 19 chi tiết hóa đơn
COMMIT;

-- Hash mật khẩu


PROMPT
PROMPT Bước 17: Hash mật khẩu nhân viên
EXEC PROC_HASH_MATKHAU_NV;
PROMPT >> Đã hash mật khẩu

-- Kiểm tra dữ liệu


PROMPT
PROMPT Bước 18: Kiểm tra dữ liệu
SELECT COUNT(*) AS TOTAL_SACH FROM Sach;
SELECT COUNT(*) AS TOTAL_KHACHHANG FROM KhachHang;
SELECT COUNT(*) AS TOTAL_NHANVIEN FROM NhanVien;
SELECT COUNT(*) AS TOTAL_HOADON FROM HoaDon;
SELECT COUNT(*) AS TOTAL_CTHD FROM ChiTietHoaDon;

PROMPT
PROMPT
=========================================================
PROMPT === PHẦN 2 HOÀN THÀNH: DỮ LIỆU ===
PROMPT
=========================================================

-- =========================================================
-- PHẦN 3: VPD/MAC (VIRTUAL PRIVATE DATABASE)
-- =========================================================

-- Xóa policy và context cũ


PROMPT
PROMPT Bước 19: Xóa VPD policy và context cũ
BEGIN
DBMS_RLS.DROP_POLICY('QLNS', 'HOADON',
'POLICY_HOADON_THEO_NV');
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP CONTEXT CTX_NHASACH';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TRIGGER
QLNS.TRG_SET_NHASACH_CTX';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
PROMPT >> Đã xóa policy và context cũ

-- Tạo procedure set context


PROMPT
PROMPT Bước 20: Tạo procedure set context
CREATE OR REPLACE PROCEDURE QLNS.PROC_SET_NHASACH_CTX IS
v_user VARCHAR2(100);
v_manv VARCHAR2(10);
v_quyenhan VARCHAR2(10);
BEGIN
v_user := SYS_CONTEXT('USERENV', 'SESSION_USER');
BEGIN
SELECT MANV, QUYENHAN INTO v_manv, v_quyenhan
FROM [Link]
WHERE UPPER(TENDANGNHAP) = UPPER(v_user);
EXCEPTION WHEN NO_DATA_FOUND THEN
v_manv := NULL;
v_quyenhan := NULL;
END;
DBMS_SESSION.SET_CONTEXT('CTX_NHASACH','USER_MANV',v_manv);

DBMS_SESSION.SET_CONTEXT('CTX_NHASACH','USER_QUYENHAN',v_qu
yenhan);
END;
/
PROMPT >> Đã tạo procedure PROC_SET_NHASACH_CTX

-- Tạo context
PROMPT
PROMPT Bước 21: Tạo context
CREATE OR REPLACE CONTEXT CTX_NHASACH USING
QLNS.PROC_SET_NHASACH_CTX;
PROMPT >> Đã tạo context CTX_NHASACH

-- Tạo function VPD policy


PROMPT
PROMPT Bước 22: Tạo function VPD policy
CREATE OR REPLACE FUNCTION FNC_POLICY_HOADON(
p_schema IN VARCHAR2,
p_object IN VARCHAR2
) RETURN VARCHAR2
IS
v_manv VARCHAR2(100);
v_user VARCHAR2(100);
v_quyenhan VARCHAR2(100);
BEGIN
v_user := SYS_CONTEXT('USERENV', 'SESSION_USER');

-- Owner thấy tất cả


IF UPPER(v_user) = UPPER(p_schema) THEN
RETURN '1=1';
END IF;

-- Lấy quyền từ context


v_quyenhan := SYS_CONTEXT('CTX_NHASACH', 'USER_QUYENHAN');
v_manv := SYS_CONTEXT('CTX_NHASACH', 'USER_MANV');

-- Admin thấy tất cả


IF v_quyenhan = 'Admin' THEN
RETURN '1=1';

-- User chỉ thấy hóa đơn của mình


ELSIF v_quyenhan = 'User' THEN
IF v_manv IS NOT NULL THEN
RETURN 'MaNV = ''' || v_manv || '''';
ELSE
RETURN '1=2';
END IF;

ELSE
RETURN '1=2';
END IF;
END;
/
PROMPT >> Đã tạo function FNC_POLICY_HOADON

-- Apply policy vào bảng HOADON


PROMPT
PROMPT Bước 23: Apply policy vào HOADON
BEGIN
DBMS_RLS.ADD_POLICY(
object_schema => 'QLNS',
object_name => 'HOADON',
policy_name => 'POLICY_HOADON_THEO_NV',
function_schema => 'QLNS',
policy_function => 'FNC_POLICY_HOADON',
statement_types => 'SELECT, UPDATE, DELETE'
);
DBMS_OUTPUT.PUT_LINE('>> Đã apply policy
POLICY_HOADON_THEO_NV');
END;
/
-- Tạo trigger LOGON
PROMPT
PROMPT Bước 24: Tạo trigger LOGON
CREATE OR REPLACE TRIGGER QLNS.TRG_SET_NHASACH_CTX
AFTER LOGON ON DATABASE
DECLARE
v_user VARCHAR2(100);
BEGIN
v_user := SYS_CONTEXT('USERENV', 'SESSION_USER');

IF v_user IN ('QLNS', 'ADMIN', 'HOATV', 'MAIANH', 'NGUYEN', 'PHUONG',


'QUOC') THEN
BEGIN
QLNS.PROC_SET_NHASACH_CTX;
EXCEPTION WHEN OTHERS THEN NULL;
END;
END IF;
END;
/
ALTER TRIGGER QLNS.TRG_SET_NHASACH_CTX ENABLE;
PROMPT >> Đã tạo trigger TRG_SET_NHASACH_CTX

-- Cấp quyền object cho roles


PROMPT
PROMPT Bước 25: Cấp quyền object cho roles
BEGIN
-- ROLE_QUANLY_CAP_CAO
EXECUTE IMMEDIATE 'GRANT SELECT, INSERT, UPDATE, DELETE ON
[Link] TO ROLE_QUANLY_CAP_CAO';
EXECUTE IMMEDIATE 'GRANT SELECT, INSERT, UPDATE, DELETE ON
[Link] TO ROLE_QUANLY_CAP_CAO';
EXECUTE IMMEDIATE 'GRANT SELECT, INSERT, UPDATE, DELETE ON
[Link] TO ROLE_QUANLY_CAP_CAO';
EXECUTE IMMEDIATE 'GRANT SELECT, INSERT, UPDATE, DELETE ON
[Link] TO ROLE_QUANLY_CAP_CAO';

-- ROLE_NHANVIEN_GIAO_DICH
EXECUTE IMMEDIATE 'GRANT SELECT, INSERT, UPDATE, DELETE ON
[Link] TO ROLE_NHANVIEN_GIAO_DICH';
EXECUTE IMMEDIATE 'GRANT SELECT, INSERT, UPDATE, DELETE ON
[Link] TO ROLE_NHANVIEN_GIAO_DICH';
EXECUTE IMMEDIATE 'GRANT SELECT, UPDATE ON [Link] TO
ROLE_NHANVIEN_GIAO_DICH';
EXECUTE IMMEDIATE 'GRANT SELECT ON [Link] TO
ROLE_NHANVIEN_GIAO_DICH';

-- ROLE_NHANVIEN_KHO
EXECUTE IMMEDIATE 'GRANT SELECT, UPDATE ON [Link] TO
ROLE_NHANVIEN_KHO';
EXECUTE IMMEDIATE 'GRANT SELECT ON [Link] TO
ROLE_NHANVIEN_KHO';
EXECUTE IMMEDIATE 'GRANT SELECT ON [Link] TO
ROLE_NHANVIEN_KHO';

DBMS_OUTPUT.PUT_LINE('>> Đã cấp quyền object');


END;
/

-- Kiểm tra RLS


PROMPT
PROMPT Bước 26: Kiểm tra RLS
SELECT COUNT(*) AS TOTAL_HOADON_VISIBLE FROM HOADON;
-- Kiểm tra objects
SELECT OBJECT_NAME, OBJECT_TYPE, STATUS
FROM USER_OBJECTS
WHERE OBJECT_NAME IN ('PROC_SET_NHASACH_CTX',
'FNC_POLICY_HOADON', 'TRG_SET_NHASACH_CTX');

PROMPT
PROMPT
=========================================================
PROMPT === FILE 3 HOÀN THÀNH ===
PROMPT
=========================================================
PROMPT Đã tạo:
PROMPT - 8 bảng
PROMPT - Dữ liệu mẫu
PROMPT - Hash password
PROMPT - Encryption function
PROMPT - VPD/MAC policy
PROMPT
PROMPT MÔI TRƯỜNG QLNS ĐÃ SẴN SÀNG!
PROMPT
PROMPT BƯỚC TIẾP THEO:
PROMPT - Chạy CÂU 11 (OLS - 4 files)
PROMPT - Chạy CÂU 12 (Auditing - 3 files)
PROMPT
=========================================================

-- =========================================================
-- CÂU 11: ORACLE LABEL SECURITY - FILE 01
-- Cấp quyền OLS cho user QLNS
-- CHẠY AS: SYS (SYSDBA)
-- Thời gian: 1 phút
-- =========================================================
SET SERVEROUTPUT ON;
ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT
=========================================================
PROMPT === CÂU 11 - FILE 01: SETUP OLS ===
PROMPT === Đang login as:
SHOW USER;
PROMPT
=========================================================

PROMPT
PROMPT Bước 1: Kiểm tra OLS đã cài chưa
PROMPT
=========================================================
SELECT comp_name, version, status
FROM dba_registry
WHERE comp_id = 'OLS';

PROMPT
PROMPT LƯU Ý: Nếu không có kết quả hoặc STATUS ≠ VALID:
PROMPT 1. Chạy trong SQL*Plus: @?/rdbms/admin/[Link]
PROMPT 2. Chạy: EXEC LBACSYS.CONFIGURE_OLS;
PROMPT 3. Chạy: EXEC LBACSYS.OLS_ENFORCEMENT.ENABLE_OLS;
PROMPT

PROMPT
PROMPT Bước 2: Cấp quyền OLS cho QLNS
PROMPT
=========================================================

-- Quyền 1: LBAC_DBA role


GRANT LBAC_DBA TO QLNS;
PROMPT ✓ LBAC_DBA role

-- Quyền 2: sa_components
GRANT EXECUTE ON LBACSYS.sa_components TO QLNS;
PROMPT ✓ sa_components

-- Quyền 3: sa_label_admin
GRANT EXECUTE ON LBACSYS.sa_label_admin TO QLNS;
PROMPT ✓ sa_label_admin

-- Quyền 4: LBAC_POLICY_ADMIN (package thật, không phải synonym!)


GRANT EXECUTE ON LBACSYS.LBAC_POLICY_ADMIN TO QLNS;
PROMPT ✓ LBAC_POLICY_ADMIN (package thật)

-- Quyền 5: sa_user_admin
GRANT EXECUTE ON LBACSYS.sa_user_admin TO QLNS;
PROMPT ✓ sa_user_admin

-- Quyền 6: sa_sysdba
GRANT EXECUTE ON LBACSYS.sa_sysdba TO QLNS;
PROMPT ✓ sa_sysdba

-- Quyền 7: to_lbac_data_label (cho PUBLIC)


GRANT EXECUTE ON LBACSYS.to_lbac_data_label TO PUBLIC;
PROMPT ✓ to_lbac_data_label

PROMPT
PROMPT
=========================================================
PROMPT === FILE 01 HOÀN THÀNH ===
PROMPT
=========================================================
PROMPT ✓ Đã cấp đầy đủ 7 quyền OLS cho user QLNS
PROMPT
PROMPT BƯỚC TIẾP THEO:
PROMPT 1. Disconnect SYS
PROMPT 2. Connect LBACSYS (username: LBACSYS, password: <tìm hoặc
reset>)
PROMPT 3. Chạy FILE 02
PROMPT
PROMPT Nếu không biết password LBACSYS:
PROMPT As SYS: ALTER USER LBACSYS IDENTIFIED BY lbacsys123;
PROMPT

-- =========================================================
-- CÂU 11: ORACLE LABEL SECURITY - FILE 02
-- Tạo OLS Policy và áp dụng vào bảng NHANVIEN
-- CHẠY AS: LBACSYS
-- Thời gian: 2 phút
-- =========================================================
SET SERVEROUTPUT ON;
ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT
=========================================================
PROMPT === CÂU 11 - FILE 02: CREATE POLICY ===
PROMPT === Đang login as:
SHOW USER;
PROMPT
=========================================================

PROMPT
PROMPT Bước 1: Xóa policy cũ (nếu có)
PROMPT
=========================================================
BEGIN
-- Xóa policy
BEGIN
sa_sysdba.drop_policy(
policy_name => 'NHANSU_POL',
drop_column => TRUE
);
DBMS_OUTPUT.PUT_LINE('✓ Đã xóa policy cũ: NHANSU_POL');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12461 THEN
DBMS_OUTPUT.PUT_LINE('○ Policy NHANSU_POL chưa tồn tại');
ELSE
DBMS_OUTPUT.PUT_LINE('! ' || SQLERRM);
END IF;
END;

-- Xóa role (bỏ qua mọi lỗi)


BEGIN
EXECUTE IMMEDIATE 'DROP ROLE NHANSU_POL_DBA';
DBMS_OUTPUT.PUT_LINE('✓ Đã xóa role NHANSU_POL_DBA');
EXCEPTION
WHEN OTHERS THEN NULL;
END;
END;
/

PROMPT
PROMPT Bước 2: Tạo policy NHANSU_POL
PROMPT
=========================================================
BEGIN
sa_sysdba.create_policy(
policy_name => 'NHANSU_POL',
column_name => 'OLS_LABEL',
default_options => 'NO_CONTROL'
);
DBMS_OUTPUT.PUT_LINE('✓ Policy: NHANSU_POL');
DBMS_OUTPUT.PUT_LINE(' Column: OLS_LABEL');
DBMS_OUTPUT.PUT_LINE(' Owner: LBACSYS');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12447 THEN
DBMS_OUTPUT.PUT_LINE('! Policy đã tồn tại, tiếp tục...');
ELSE
RAISE;
END IF;
END;
/

PROMPT
PROMPT Bước 3: Tạo 3 Levels (mức độ bảo mật)
PROMPT
=========================================================
BEGIN
-- Level 1: PUBLIC (1000)
BEGIN
sa_components.create_level(
policy_name => 'NHANSU_POL',
level_num => 1000,
short_name => 'PUB',
long_name => 'PUBLIC'
);
DBMS_OUTPUT.PUT_LINE('✓ Level 1: PUBLIC (1000)');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12422 THEN
DBMS_OUTPUT.PUT_LINE('○ Level PUBLIC đã tồn tại');
ELSE RAISE;
END IF;
END;

-- Level 2: CONFIDENTIAL (2000)


BEGIN
sa_components.create_level(
policy_name => 'NHANSU_POL',
level_num => 2000,
short_name => 'CONF',
long_name => 'CONFIDENTIAL'
);
DBMS_OUTPUT.PUT_LINE('✓ Level 2: CONFIDENTIAL (2000)');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12422 THEN
DBMS_OUTPUT.PUT_LINE('○ Level CONFIDENTIAL đã tồn tại');
ELSE RAISE;
END IF;
END;

-- Level 3: SECRET (3000)


BEGIN
sa_components.create_level(
policy_name => 'NHANSU_POL',
level_num => 3000,
short_name => 'SEC',
long_name => 'SECRET'
);
DBMS_OUTPUT.PUT_LINE('✓ Level 3: SECRET (3000)');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12422 THEN
DBMS_OUTPUT.PUT_LINE('○ Level SECRET đã tồn tại');
ELSE RAISE;
END IF;
END;
END;
/

PROMPT
PROMPT Bước 4: Tạo 3 Compartments (phòng ban)
PROMPT
=========================================================
BEGIN
-- Compartment 1: Quản lý (100)
BEGIN
sa_components.create_compartment(
policy_name => 'NHANSU_POL',
comp_num => 100,
short_name => 'QL',
long_name => 'QUANLY'
);
DBMS_OUTPUT.PUT_LINE('✓ Compartment 1: QUANLY (100)');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12423 THEN
DBMS_OUTPUT.PUT_LINE('○ Compartment QUANLY đã tồn tại');
ELSE RAISE;
END IF;
END;

-- Compartment 2: Bán hàng (200)


BEGIN
sa_components.create_compartment(
policy_name => 'NHANSU_POL',
comp_num => 200,
short_name => 'BH',
long_name => 'BANHANG'
);
DBMS_OUTPUT.PUT_LINE('✓ Compartment 2: BANHANG (200)');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12423 THEN
DBMS_OUTPUT.PUT_LINE('○ Compartment BANHANG đã tồn tại');
ELSE RAISE;
END IF;
END;

-- Compartment 3: Kho (300)


BEGIN
sa_components.create_compartment(
policy_name => 'NHANSU_POL',
comp_num => 300,
short_name => 'KHO',
long_name => 'KHO'
);
DBMS_OUTPUT.PUT_LINE('✓ Compartment 3: KHO (300)');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12423 THEN
DBMS_OUTPUT.PUT_LINE('○ Compartment KHO đã tồn tại');
ELSE RAISE;
END IF;
END;
END;
/

PROMPT
PROMPT Bước 5: Tạo 5 Data Labels
PROMPT
=========================================================
BEGIN
-- Label 1: PUBLIC (tag 10)
BEGIN
sa_label_admin.create_label(
policy_name => 'NHANSU_POL',
label_tag => 10,
label_value => 'PUB',
data_label => TRUE
);
DBMS_OUTPUT.PUT_LINE('✓ Label 10: PUB');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12424 THEN
DBMS_OUTPUT.PUT_LINE('○ Label PUB đã tồn tại');
ELSE RAISE;
END IF;
END;

-- Label 2: CONF:BANHANG (tag 20)


BEGIN
sa_label_admin.create_label(
policy_name => 'NHANSU_POL',
label_tag => 20,
label_value => 'CONF:BH',
data_label => TRUE
);
DBMS_OUTPUT.PUT_LINE('✓ Label 20: CONF:BH');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12424 THEN
DBMS_OUTPUT.PUT_LINE('○ Label CONF:BH đã tồn tại');
ELSE RAISE;
END IF;
END;

-- Label 3: CONF:KHO (tag 30)


BEGIN
sa_label_admin.create_label(
policy_name => 'NHANSU_POL',
label_tag => 30,
label_value => 'CONF:KHO',
data_label => TRUE
);
DBMS_OUTPUT.PUT_LINE('✓ Label 30: CONF:KHO');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12424 THEN
DBMS_OUTPUT.PUT_LINE('○ Label CONF:KHO đã tồn tại');
ELSE RAISE;
END IF;
END;

-- Label 4: CONF:QUANLY (tag 40)


BEGIN
sa_label_admin.create_label(
policy_name => 'NHANSU_POL',
label_tag => 40,
label_value => 'CONF:QL',
data_label => TRUE
);
DBMS_OUTPUT.PUT_LINE('✓ Label 40: CONF:QL');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12424 THEN
DBMS_OUTPUT.PUT_LINE('○ Label CONF:QL đã tồn tại');
ELSE RAISE;
END IF;
END;

-- Label 5: SECRET (tag 50)


BEGIN
sa_label_admin.create_label(
policy_name => 'NHANSU_POL',
label_tag => 50,
label_value => 'SEC',
data_label => TRUE
);
DBMS_OUTPUT.PUT_LINE('✓ Label 50: SEC');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12424 THEN
DBMS_OUTPUT.PUT_LINE('○ Label SEC đã tồn tại');
ELSE RAISE;
END IF;
END;
END;
/

PROMPT
PROMPT Bước 6: Áp dụng policy vào bảng NHANVIEN
PROMPT
=========================================================
BEGIN
BEGIN
LBAC_POLICY_ADMIN.apply_table_policy(
policy_name => 'NHANSU_POL',
schema_name => 'QLNS',
table_name => 'NHANVIEN',
table_options => 'READ_CONTROL',
label_function => NULL,
predicate => NULL
);
DBMS_OUTPUT.PUT_LINE('✓ Đã apply policy vào [Link]');
DBMS_OUTPUT.PUT_LINE(' Cột OLS_LABEL được thêm tự động');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -12474 THEN
DBMS_OUTPUT.PUT_LINE('○ Policy đã được apply trước đó');
ELSE
DBMS_OUTPUT.PUT_LINE('! Lỗi: ' || SQLERRM);
RAISE;
END IF;
END;
END;
/

COMMIT;

PROMPT
PROMPT
=========================================================
PROMPT === FILE 02 HOÀN THÀNH ===
PROMPT
=========================================================
PROMPT ✓ Policy: NHANSU_POL (owner: LBACSYS)
PROMPT ✓ 3 Levels: PUB, CONF, SEC
PROMPT ✓ 3 Compartments: QL, BH, KHO
PROMPT ✓ 5 Labels: 10, 20, 30, 40, 50
PROMPT ✓ Applied to: [Link]
PROMPT
PROMPT BƯỚC TIẾP THEO:
PROMPT 1. Disconnect LBACSYS
PROMPT 2. Connect QLNS (username: QLNS, password: qlns)
PROMPT 3. Chạy FILE 03A (gán data labels)
PROMPT

-- =========================================================
-- CÂU 11: ORACLE LABEL SECURITY - FILE 03A
-- Gán OLS labels cho DỮ LIỆU (bảng NHANVIEN)
-- CHẠY AS: QLNS
-- Thời gian: 1 phút
-- =========================================================
SET SERVEROUTPUT ON;
ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT
=========================================================
PROMPT === CÂU 11 - FILE 03A: GÁN DATA LABELS ===
PROMPT === Đang login as:
SHOW USER;
PROMPT
=========================================================

PROMPT
PROMPT Bước 1: Xem dữ liệu hiện tại
PROMPT
=========================================================
SELECT MANV, HOTEN, CHUCVU, TENDANGNHAP, QUYENHAN,
OLS_LABEL
FROM NHANVIEN
ORDER BY MANV;

PROMPT
PROMPT Bước 2: Gán OLS_LABEL cho từng nhân viên
PROMPT
=========================================================

-- Gán label SEC (50) cho 4 admin users


UPDATE NHANVIEN
SET OLS_LABEL = 50
WHERE TENDANGNHAP IN ('admin', 'Nguyen', 'Phuong', 'Quoc');

PROMPT ✓ Đã gán SEC (50) cho 4 admin users

-- Gán label CONF:KHO (30) cho nhân viên kho


UPDATE NHANVIEN
SET OLS_LABEL = 30
WHERE TENDANGNHAP = 'hoatv';

PROMPT ✓ Đã gán CONF:KHO (30) cho hoatv

-- Gán label CONF:BH (20) cho nhân viên bán hàng


UPDATE NHANVIEN
SET OLS_LABEL = 20
WHERE TENDANGNHAP = 'maianh';

PROMPT ✓ Đã gán CONF:BH (20) cho maianh

-- Các nhân viên còn lại (nếu có) -> PUBLIC


UPDATE NHANVIEN
SET OLS_LABEL = 10
WHERE OLS_LABEL IS NULL;

COMMIT;

PROMPT
PROMPT Bước 3: Kiểm tra kết quả
PROMPT
=========================================================
SELECT
MANV,
HOTEN,
TENDANGNHAP,
OLS_LABEL,
LABEL_TO_CHAR(OLS_LABEL) AS LABEL_NAME
FROM NHANVIEN
ORDER BY OLS_LABEL DESC, MANV;

PROMPT
PROMPT
=========================================================
PROMPT === FILE 03A HOÀN THÀNH ===
PROMPT
=========================================================
PROMPT ✓ Đã gán OLS_LABEL cho 6 nhân viên:
PROMPT - 4 admin (admin, Nguyen, Phuong, Quoc) → SEC (50)
PROMPT - 1 kho (hoatv) → CONF:KHO (30)
PROMPT - 1 bán hàng (maianh) → CONF:BH (20)
PROMPT
PROMPT BƯỚC TIẾP THEO:
PROMPT 1. Disconnect QLNS
PROMPT 2. Connect LBACSYS (username: LBACSYS)
PROMPT 3. Chạy FILE 03B (gán user labels)
PROMPT
-- =========================================================
-- CÂU 11: ORACLE LABEL SECURITY - FILE 03B
-- Gán OLS labels cho DATABASE USERS
-- CHẠY AS: LBACSYS
-- Thời gian: 1 phút
-- =========================================================
SET SERVEROUTPUT ON;
ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT
=========================================================
PROMPT === CÂU 11 - FILE 03B: GÁN USER LABELS ===
PROMPT === Đang login as:
SHOW USER;
PROMPT
=========================================================

PROMPT
PROMPT Gán user labels cho 7 database users
PROMPT
=========================================================
BEGIN
-- User QLNS - Owner, thấy tất cả
sa_user_admin.set_user_labels(
policy_name => 'NHANSU_POL',
user_name => 'QLNS',
max_read_label => 'SEC',
max_write_label => 'SEC',
def_label => 'SEC',
row_label => 'SEC'
);
DBMS_OUTPUT.PUT_LINE('✓ QLNS → SEC (thấy tất cả)');

-- User ADMIN
sa_user_admin.set_user_labels(
policy_name => 'NHANSU_POL',
user_name => 'ADMIN',
max_read_label => 'SEC',
def_label => 'SEC',
row_label => 'SEC'
);
DBMS_OUTPUT.PUT_LINE('✓ ADMIN → SEC');

-- User NGUYEN
sa_user_admin.set_user_labels(
policy_name => 'NHANSU_POL',
user_name => 'NGUYEN',
max_read_label => 'SEC',
def_label => 'SEC',
row_label => 'SEC'
);
DBMS_OUTPUT.PUT_LINE('✓ NGUYEN → SEC');

-- User PHUONG
sa_user_admin.set_user_labels(
policy_name => 'NHANSU_POL',
user_name => 'PHUONG',
max_read_label => 'SEC',
def_label => 'SEC',
row_label => 'SEC'
);
DBMS_OUTPUT.PUT_LINE('✓ PHUONG → SEC');

-- User QUOC
sa_user_admin.set_user_labels(
policy_name => 'NHANSU_POL',
user_name => 'QUOC',
max_read_label => 'SEC',
def_label => 'SEC',
row_label => 'SEC'
);
DBMS_OUTPUT.PUT_LINE('✓ QUOC → SEC');

-- User HOATV - Nhân viên kho


sa_user_admin.set_user_labels(
policy_name => 'NHANSU_POL',
user_name => 'HOATV',
max_read_label => 'CONF:KHO',
def_label => 'CONF:KHO',
row_label => 'CONF:KHO'
);
DBMS_OUTPUT.PUT_LINE('✓ HOATV → CONF:KHO (chỉ thấy PUBLIC +
KHO)');

-- User MAIANH - Nhân viên bán hàng


sa_user_admin.set_user_labels(
policy_name => 'NHANSU_POL',
user_name => 'MAIANH',
max_read_label => 'CONF:BH',
def_label => 'CONF:BH',
row_label => 'CONF:BH'
);
DBMS_OUTPUT.PUT_LINE('✓ MAIANH → CONF:BH (chỉ thấy PUBLIC +
BANHANG)');

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('! Lỗi: ' || SQLERRM);
RAISE;
END;
/

COMMIT;

PROMPT
PROMPT
=========================================================
PROMPT === FILE 03B HOÀN THÀNH ===
PROMPT
=========================================================
PROMPT ✓ Đã gán user labels cho 7 database users:
PROMPT - 5 admin (QLNS, ADMIN, NGUYEN, PHUONG, QUOC) → SEC
PROMPT - 1 kho (HOATV) → CONF:KHO
PROMPT - 1 bán hàng (MAIANH) → CONF:BH
PROMPT
PROMPT BƯỚC TIẾP THEO:
PROMPT 1. Tạo 4 connections riêng để test:
PROMPT - QLNS / qlns
PROMPT - ADMIN / admin
PROMPT - HOATV / user01
PROMPT - MAIANH / user01
PROMPT 2. Chạy FILE 04 để test OLS
PROMPT

-- =========================================================
-- CÂU 12: STANDARD AUDITING & FGA - FILE 01
-- Setup Standard Auditing và FGA Policy
-- CHẠY AS: SYS (SYSDBA)
-- Thời gian: 30 giây
-- =========================================================
SET SERVEROUTPUT ON SIZE 1000000;
ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT
=========================================================
PROMPT === CÂU 12 - FILE 01: SETUP AUDITING ===
PROMPT === Đang login as:
SHOW USER;
PROMPT
=========================================================

-- Define để tránh prompt &HOADON nếu có


DEFINE HOADON = "HOADON";

PROMPT
PROMPT Bước 1: Kiểm tra auditing status
PROMPT
=========================================================
SELECT NAME, VALUE FROM V$PARAMETER WHERE NAME = 'audit_trail';

PROMPT
PROMPT Bước 2: Kiểm tra và enable Standard Auditing
PROMPT
=========================================================
BEGIN
DBMS_OUTPUT.PUT_LINE('○ Giả định auditing đã được enable (mặc định
Oracle 12c+)');
END;
/

PROMPT
PROMPT Bước 3: Tạo Standard Audit Policy cho QLNS schema
PROMPT
=========================================================
-- Audit tất cả SELECT, INSERT, UPDATE, DELETE trên NHANVIEN và
HOADON
AUDIT SELECT, INSERT, UPDATE, DELETE ON [Link] BY
ACCESS;
AUDIT SELECT, INSERT, UPDATE, DELETE ON QLNS.&HOADON BY
ACCESS;
-- Audit failed sessions cho QLNS (syntax chuẩn)
AUDIT SESSION BY QLNS WHENEVER NOT SUCCESSFUL;
BEGIN
DBMS_OUTPUT.PUT_LINE('✓ Standard Audit: NHANVIEN & HOADON
(ALL DML)');
DBMS_OUTPUT.PUT_LINE('✓ Standard Audit: Failed sessions for QLNS');
END;
/

PROMPT
PROMPT Bước 4: Setup Fine-Grained Auditing (FGA) cho NHANVIEN
PROMPT
=========================================================
-- Cấp quyền INSERT/SELECT LOGHETHONG cho SYS và PUBLIC (để handler
chạy)
BEGIN
EXECUTE IMMEDIATE 'GRANT INSERT, SELECT ON
[Link] TO SYS';
EXECUTE IMMEDIATE 'GRANT INSERT, SELECT ON
[Link] TO PUBLIC';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

-- Cấp quyền CREATE ANY DIRECTORY cho QLNS (cho Data Pump)
GRANT CREATE ANY DIRECTORY TO QLNS;
BEGIN
DBMS_OUTPUT.PUT_LINE('✓ Đã cấp quyền CREATE ANY DIRECTORY cho
QLNS (cho backup)');
END;
/

BEGIN
-- Drop FGA cũ nếu có
BEGIN
DBMS_FGA.DROP_POLICY(
object_schema => 'QLNS',
object_name => 'NHANVIEN',
policy_name => 'NHANSU_FGA_POLICY'
);
DBMS_OUTPUT.PUT_LINE('○ Đã xóa FGA policy cũ');
EXCEPTION WHEN OTHERS THEN
NULL; -- Bỏ qua nếu chưa tồn tại
END;

-- Tạo FGA Policy: Audit UPDATE MatKhau_HASH hoặc QuyenHan


BEGIN
DBMS_FGA.ADD_POLICY(
object_schema => 'QLNS',
object_name => 'NHANVIEN',
policy_name => 'NHANSU_FGA_POLICY',
audit_condition => NULL, -- Audit tất cả UPDATE trên các cột được chỉ định
statement_types => 'UPDATE',
audit_column => 'MATKHAU_HASH, QUYENHAN', -- Chỉ audit khi
UPDATE các cột này
handler_schema => 'QLNS',
handler_module => 'FGA_AUDIT_HANDLER'
);
DBMS_OUTPUT.PUT_LINE('✓ FGA Policy: NHANSU_FGA_POLICY
(UPDATE mật khẩu/quyền)');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN
DBMS_OUTPUT.PUT_LINE('○ FGA Policy đã tồn tại');
ELSE RAISE;
END IF;
END;
END;
/

-- Drop procedure cũ nếu có


BEGIN
EXECUTE IMMEDIATE 'DROP PROCEDURE
QLNS.FGA_AUDIT_HANDLER';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

-- Tạo handler procedure cho FGA (trực tiếp, sửa tên cột THOIGIAN)
CREATE OR REPLACE PROCEDURE QLNS.FGA_AUDIT_HANDLER(
schema_name VARCHAR2,
table_name VARCHAR2,
policy_name VARCHAR2
) IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO [Link] (MALOG, THAOTAC, THOIGIAN,
MANV, MOTA)
VALUES (SUBSTR(RAWTOHEX(SYS_GUID()), 1, 10), 'FGA_AUDIT:
UPDATE NHANVIEN', SYSDATE,
SYS_CONTEXT('USERENV', 'SESSION_USER'),
'FGA Update by ' || NVL(SYS_CONTEXT('USERENV', 'SESSION_USER'),
'UNKNOWN') || ' Policy: ' || policy_name);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
NULL; -- Tránh crash handler
END;
/

-- Grant quyền execute


GRANT EXECUTE ON QLNS.FGA_AUDIT_HANDLER TO PUBLIC;

BEGIN
DBMS_OUTPUT.PUT_LINE('✓ FGA Handler: FGA_AUDIT_HANDLER (ghi
vào LOGHETHONG)');
END;
/

PROMPT
PROMPT
=========================================================
PROMPT === FILE 01 HOÀN THÀNH ===
PROMPT
=========================================================
PROMPT ✓ Standard Auditing: DML trên NHANVIEN/HOADON + Failed sessions
PROMPT ✓ FGA: UPDATE mật khẩu/quyền trên NHANVIEN (log vào
LOGHETHONG)
PROMPT ✓ Cấp quyền CREATE ANY DIRECTORY cho QLNS (cho backup)
PROMPT
PROMPT BƯỚC TIẾP THEO:
PROMPT 1. Disconnect SYS
PROMPT 2. Connect QLNS / qlns
PROMPT 3. Chạy FILE 02 (Sao lưu)

-- =========================================================
-- CÂU 12: STANDARD AUDITING & FGA - FILE 02
-- Nghiệp vụ cập nhật + Trigger ghi LOGHETHONG + Test FGA
-- CHẠY AS: QLNS
-- Thời gian: 3–5 phút
-- =========================================================
SET SERVEROUTPUT ON SIZE 1000000;
SET DEFINE OFF
ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT
=========================================================
PROMPT === CÂU 12 - FILE 02: NGHIỆP VỤ + TRIGGER LOG ===
PROMPT === Đang login as:
SHOW USER;
PROMPT
=========================================================

PROMPT
PROMPT Bước 1: Trigger ghi nhật ký trên bảng HOADON
PROMPT
=========================================================

-- Xoá trigger cũ (nếu có)


BEGIN
EXECUTE IMMEDIATE 'DROP TRIGGER TRG_HOADON_LOG';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

-- Trigger: mọi INSERT/UPDATE/DELETE HOADON sẽ ghi vào LOGHETHONG


CREATE OR REPLACE TRIGGER TRG_HOADON_LOG
AFTER INSERT OR UPDATE OR DELETE ON HoaDon
FOR EACH ROW
DECLARE
v_action NVARCHAR2(100);
v_mota NVARCHAR2(1000);
v_manv_log VARCHAR2(10);
BEGIN
-- Lấy MaNV để log (dùng MaNV trên hóa đơn, đúng FK sang NHANVIEN)
IF INSERTING THEN
v_action := N'INSERT HOADON';
v_manv_log := :[Link];
v_mota := N'Tạo mới hóa đơn ' || :[Link]
|| N', KH=' || :[Link]
|| N', NV=' || :[Link]
|| N', TongTien=' || :[Link];
ELSIF UPDATING THEN
v_action := N'UPDATE HOADON';
v_manv_log := :[Link];
v_mota := N'Cập nhật hóa đơn ' || :[Link]
|| N' | TrangThai: ' || :[Link] || N' → ' || :[Link]
|| N' | TongTien: ' || :[Link] || N' → ' || :[Link];
ELSIF DELETING THEN
v_action := N'DELETE HOADON';
v_manv_log := :[Link];
v_mota := N'Xoá hóa đơn ' || :[Link];
END IF;

INSERT INTO LogHeThong (MaLog, ThaoTac, ThoiGian, MaNV, MoTa)


VALUES (
SUBSTR(RAWTOHEX(SYS_GUID()), 1, 10),
v_action,
SYSDATE,
v_manv_log,
v_mota
);
END;
/
PROMPT ✓ TRG_HOADON_LOG: Ghi log nghiệp vụ HOADON vào
LOGHETHONG

PROMPT
PROMPT Bước 2: Thủ tục đổi mật khẩu nhân viên (kích hoạt FGA)
PROMPT
=========================================================

-- Xoá procedure cũ (nếu có)


BEGIN
EXECUTE IMMEDIATE 'DROP PROCEDURE PROC_DOI_MATKHAU_NV';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

-- Nghiệp vụ: đổi mật khẩu cho 1 nhân viên


-- Lưu ý: có UPDATE MATKHAU_HASH nên sẽ kích hoạt FGA policy
NHANSU_FGA_POLICY
CREATE OR REPLACE PROCEDURE PROC_DOI_MATKHAU_NV (
p_tendangnhap IN NVARCHAR2,
p_matkhaumoi IN NVARCHAR2
) IS
v_manv [Link]%TYPE;
BEGIN
SELECT MaNV INTO v_manv
FROM NhanVien
WHERE UPPER(TenDangNhap) = UPPER(p_tendangnhap);

UPDATE NhanVien
SET MatKhau_Goc = p_matkhaumoi,
MatKhau_HASH = FN_HASH_PASSWORD(p_matkhaumoi)
WHERE MaNV = v_manv;

INSERT INTO LogHeThong (MaLog, ThaoTac, ThoiGian, MaNV, MoTa)


VALUES (
SUBSTR(RAWTOHEX(SYS_GUID()), 1, 10),
N'DOI_MATKHAU',
SYSDATE,
v_manv,
N'Đổi mật khẩu cho user ' || p_tendangnhap
);

COMMIT;
END;
/
PROMPT ✓ PROC_DOI_MATKHAU_NV: Đổi mật khẩu + ghi LOGHETHONG +
kích hoạt FGA

PROMPT
PROMPT Bước 3: Thủ tục cập nhật quyền hạn nhân viên (kích hoạt FGA)
PROMPT
=========================================================

BEGIN
EXECUTE IMMEDIATE 'DROP PROCEDURE
PROC_CAPNHAT_QUYENHAN_NV';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

CREATE OR REPLACE PROCEDURE PROC_CAPNHAT_QUYENHAN_NV (


p_tendangnhap IN NVARCHAR2,
p_quyenmoi IN NVARCHAR2
) IS
v_manv [Link]%TYPE;
BEGIN
-- Chỉ cho phép giá trị Admin/User
IF p_quyenmoi NOT IN ('Admin','User') THEN
RAISE_APPLICATION_ERROR(-20010, 'QuyenHan khong hop le');
END IF;

SELECT MaNV INTO v_manv


FROM NhanVien
WHERE UPPER(TenDangNhap) = UPPER(p_tendangnhap);

UPDATE NhanVien
SET QuyenHan = p_quyenmoi
WHERE MaNV = v_manv;

INSERT INTO LogHeThong (MaLog, ThaoTac, ThoiGian, MaNV, MoTa)


VALUES (
SUBSTR(RAWTOHEX(SYS_GUID()), 1, 10),
N'CAPNHAT_QUYENHAN',
SYSDATE,
v_manv,
N'Cap nhat QuyenHan cho user ' || p_tendangnhap
|| N' → ' || p_quyenmoi
);

COMMIT;
END;
/
PROMPT ✓ PROC_CAPNHAT_QUYENHAN_NV: Cập nhật quyền + ghi
LOGHETHONG + kích hoạt FGA

PROMPT
PROMPT Bước 4: Chạy thử nghiệp vụ để phát sinh Audit / FGA
PROMPT
=========================================================

-- 4.1. Thao tác trên HOADON: sẽ có


-- + Standard Audit (AUDIT ... ON [Link] BY ACCESS)
-- + Trigger TRG_HOADON_LOG ghi vào LOGHETHONG
PROMPT ► Test 1: Cập nhật trạng thái HOADON
UPDATE HoaDon
SET TrangThai = 'DA_THANH_TOAN'
WHERE MaHD = 'HD001';
COMMIT;

-- 4.2. Đổi mật khẩu cho 1 nhân viên: sẽ có


-- + Standard Audit trên NHANVIEN
-- + FGA (vì UPDATE MATKHAU_HASH)
-- + LOGHETHONG do PROC_DOI_MATKHAU_NV
PROMPT ► Test 2: Đổi mật khẩu cho hoatv
EXEC PROC_DOI_MATKHAU_NV('hoatv', 'user01_moi');

-- 4.3. Cập nhật quyền hạn cho 1 nhân viên: cũng kích hoạt Standard Audit + FGA
PROMPT ► Test 3: Nâng quyền maianh thành Admin
EXEC PROC_CAPNHAT_QUYENHAN_NV('maianh', 'Admin');

PROMPT
PROMPT Bước 5: Xem nhanh LOGHETHONG (ứng dụng dùng để giải trình)
PROMPT
=========================================================
COLUMN THAOTAC FORMAT A25
COLUMN MOTA FORMAT A60

SELECT MaLog, ThaoTac, ThoiGian, MaNV, MoTa


FROM LogHeThong
ORDER BY ThoiGian DESC;

PROMPT
PROMPT
=========================================================
PROMPT === FILE 02 HOÀN THÀNH – ĐÃ CÓ NGHIỆP VỤ + TRIGGER LOG
===
PROMPT
=========================================================
PROMPT ✓ Trigger TRG_HOADON_LOG ghi log mọi DML HOADON
PROMPT ✓ PROC_DOI_MATKHAU_NV &
PROC_CAPNHAT_QUYENHAN_NV kích hoạt FGA
PROMPT ✓ LOGHETHONG dùng để xem nhật ký ở mức ứng dụng
PROMPT
PROMPT BƯỚC TIẾP THEO:
PROMPT 1. Disconnect QLNS
PROMPT 2. Connect SYS (SYSDBA)
PROMPT 3. Chạy FILE 03 để xem nhật ký DBA_AUDIT_TRAIL,
DBA_FGA_AUDIT_TRAIL

-- =========================================================
-- CÂU 12: STANDARD AUDITING & FGA - FILE 03
-- Truy vấn nhật ký Standard Auditing + FGA + LOGHETHONG
-- CHẠY AS: SYS (SYSDBA)
-- Thời gian: 2–3 phút
-- =========================================================
SET SERVEROUTPUT ON;
ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT
=========================================================
PROMPT === CÂU 12 - FILE 03: XEM VÀ GIẢI TRÌNH NHẬT KÝ ===
PROMPT === Đang login as:
SHOW USER;
PROMPT
=========================================================
PROMPT
PROMPT Bước 1: Standard Audit – thao tác trên NHANVIEN / HOADON
PROMPT
=========================================================
COLUMN USERNAME FORMAT A12
COLUMN OBJ_NAME FORMAT A12
COLUMN ACTION_NAME FORMAT A15
COLUMN RETURN_CODE FORMAT 999999
COLUMN EXTENDED_TIMESTAMP FORMAT A30

SELECT
USERNAME,
OBJ_NAME,
ACTION_NAME,
TO_CHAR(EXTENDED_TIMESTAMP, 'DD/MM/YYYY HH24:MI:SS') AS
THOIGIAN,
RETURNCODE AS RETURN_CODE
FROM DBA_AUDIT_TRAIL
WHERE OWNER = 'QLNS'
AND OBJ_NAME IN ('NHANVIEN','HOADON')
ORDER BY EXTENDED_TIMESTAMP DESC;

PROMPT
PROMPT Bước 2: FGA Audit – cập nhật MATKHAU_HASH / QUYENHAN
PROMPT
=========================================================
COLUMN DB_USER FORMAT A12
COLUMN OBJECT_SCHEMA FORMAT A8
COLUMN OBJECT_NAME FORMAT A10
COLUMN STATEMENT_TYPE FORMAT A10
COLUMN POLICY_NAME FORMAT A18

SELECT
DB_USER,
OBJECT_SCHEMA,
OBJECT_NAME,
STATEMENT_TYPE,
POLICY_NAME,
TO_CHAR(EXTENDED_TIMESTAMP, 'DD/MM/YYYY HH24:MI:SS') AS
THOIGIAN
FROM DBA_FGA_AUDIT_TRAIL
WHERE OBJECT_SCHEMA = 'QLNS'
AND OBJECT_NAME = 'NHANVIEN'
ORDER BY EXTENDED_TIMESTAMP DESC;

PROMPT
PROMPT Bước 3: Xem LOGHETHONG của ứng dụng (FGA handler + Trigger)
PROMPT
=========================================================
COLUMN THAOTAC FORMAT A25
COLUMN MOTA FORMAT A60
SELECT MaLog, ThaoTac, ThoiGian, MaNV, MoTa
FROM [Link]
ORDER BY ThoiGian DESC;

PROMPT
PROMPT
=========================================================
PROMPT === FILE 03 HOÀN THÀNH – BÁO CÁO GIẢI TRÌNH ===
PROMPT
=========================================================
PROMPT ✓ DBA_AUDIT_TRAIL: DML trên NHANVIEN/HOADON (Standard
Auditing)
PROMPT ✓ DBA_FGA_AUDIT_TRAIL: UPDATE
MATKHAU_HASH/QUYENHAN (FGA)
PROMPT ✓ [Link]: Nhật ký nghiệp vụ từ Trigger + Handler
PROMPT
PROMPT ==> Câu 12 đã đầy đủ: Standard Auditing + Trigger + FGA + màn hình giải
trình

-- =========================================================
-- CÂU 13 - FILE 01: BACKUP SCHEMA QLNS
-- Sử dụng DBMS_DATAPUMP (không cần CMD)
-- CHẠY AS: SYS (SYSDBA) trong SQL Developer
-- =========================================================
SET SERVEROUTPUT ON SIZE 1000000;
ALTER SESSION SET CONTAINER = ORCLPDB;
PROMPT
=========================================================
PROMPT CÂU 13 - FILE 01: BACKUP
SHOW USER;
PROMPT
=========================================================

-- Tạo directory nếu chưa có


BEGIN
EXECUTE IMMEDIATE 'DROP DIRECTORY BACKUP_DIR';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

CREATE OR REPLACE DIRECTORY BACKUP_DIR AS 'C:\oracle_backup';


PROMPT ✓ Đã tạo directory

-- Cấp quyền
GRANT READ, WRITE ON DIRECTORY BACKUP_DIR TO QLNS;
GRANT READ, WRITE ON DIRECTORY BACKUP_DIR TO SYSTEM;
GRANT DATAPUMP_EXP_FULL_DATABASE TO QLNS;
GRANT DATAPUMP_IMP_FULL_DATABASE TO QLNS;
PROMPT ✓ Đã cấp quyền

-- Kiểm tra dữ liệu trước backup


PROMPT
PROMPT Dữ liệu hiện tại:
SELECT 'SACH' AS BANG, COUNT(*) AS SO_LUONG FROM [Link]
UNION ALL SELECT 'KHACHHANG', COUNT(*) FROM [Link]
UNION ALL SELECT 'NHANVIEN', COUNT(*) FROM [Link]
UNION ALL SELECT 'HOADON', COUNT(*) FROM [Link]
UNION ALL SELECT 'CHITIETHOADON', COUNT(*) FROM
[Link];

-- BACKUP sử dụng DBMS_DATAPUMP


PROMPT
PROMPT
=========================================================
PROMPT Đang thực hiện BACKUP...
PROMPT
=========================================================

DECLARE
v_handle NUMBER;
v_status VARCHAR2(20);
v_job_state VARCHAR2(30);
BEGIN
-- Mở Data Pump job
v_handle := DBMS_DATAPUMP.OPEN(
operation => 'EXPORT',
job_mode => 'SCHEMA',
job_name => 'QLNS_BACKUP_JOB'
);

-- Chỉ định schema cần backup


DBMS_DATAPUMP.ADD_FILE(
handle => v_handle,
filename => 'QLNS_BACKUP.dmp',
directory => 'BACKUP_DIR',
filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_DUMP_FILE
);

-- File log
DBMS_DATAPUMP.ADD_FILE(
handle => v_handle,
filename => 'QLNS_BACKUP.log',
directory => 'BACKUP_DIR',
filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE
);

-- Chỉ định schema


DBMS_DATAPUMP.METADATA_FILTER(
handle => v_handle,
name => 'SCHEMA_EXPR',
value => 'IN (''QLNS'')'
);

-- Bắt đầu job


DBMS_DATAPUMP.START_JOB(v_handle);

-- Đợi job hoàn thành


DBMS_DATAPUMP.WAIT_FOR_JOB(v_handle, v_job_state);
DBMS_OUTPUT.PUT_LINE('✓ Backup hoàn thành!');
DBMS_OUTPUT.PUT_LINE(' File: C:\oracle_backup\QLNS_BACKUP.dmp');
DBMS_OUTPUT.PUT_LINE(' Log: C:\oracle_backup\QLNS_BACKUP.log');

-- Đóng job
DBMS_DATAPUMP.DETACH(v_handle);

EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -31626 THEN
-- Job đã tồn tại, drop và thử lại
BEGIN
DBMS_DATAPUMP.STOP_JOB(
DBMS_DATAPUMP.ATTACH('QLNS_BACKUP_JOB', 'SYS')
);
EXCEPTION WHEN OTHERS THEN NULL;
END;
DBMS_OUTPUT.PUT_LINE('! Job đã tồn tại, vui lòng chạy lại script');
ELSE
DBMS_OUTPUT.PUT_LINE('! Lỗi: ' || SQLERRM);
IF v_handle IS NOT NULL THEN
DBMS_DATAPUMP.DETACH(v_handle);
END IF;
END IF;
END;
/
PROMPT
PROMPT
=========================================================
PROMPT FILE 01 HOÀN THÀNH
PROMPT
=========================================================
PROMPT ✓ Backup thành công
PROMPT
PROMPT BƯỚC TIẾP THEO:
PROMPT 1. Kiểm tra file: C:\oracle_backup\QLNS_BACKUP.dmp
PROMPT 2. Xem log: C:\oracle_backup\QLNS_BACKUP.log
PROMPT 3. Chạy: CAU13_02_RESTORE.sql
PROMPT
=========================================================

-- =========================================================
-- CÂU 13 - FILE 02: RESTORE SCHEMA
-- Sử dụng DBMS_DATAPUMP (không cần CMD)
-- CHẠY AS: SYS (SYSDBA) trong SQL Developer
-- =========================================================
SET SERVEROUTPUT ON SIZE 1000000;
ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT
=========================================================
PROMPT CÂU 13 - FILE 02: RESTORE
SHOW USER;
PROMPT
=========================================================

-- Tạo user QLNS_RESTORE


PROMPT Đang tạo user QLNS_RESTORE...

BEGIN
FOR s IN (SELECT sid, serial# FROM v$session WHERE username =
'QLNS_RESTORE') LOOP
BEGIN
EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' || [Link] || ',' ||
[Link]# || ''' IMMEDIATE';
EXCEPTION WHEN OTHERS THEN NULL;
END;
END LOOP;
END;
/

BEGIN
EXECUTE IMMEDIATE 'DROP USER QLNS_RESTORE CASCADE';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

CREATE USER QLNS_RESTORE IDENTIFIED BY qlns_restore


DEFAULT TABLESPACE QLNS_DATA
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON QLNS_DATA;
GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE
SEQUENCE TO QLNS_RESTORE;
GRANT CREATE PROCEDURE, CREATE TRIGGER, UNLIMITED
TABLESPACE TO QLNS_RESTORE;
GRANT EXECUTE ON DBMS_RLS TO QLNS_RESTORE;
GRANT EXECUTE ON DBMS_SESSION TO QLNS_RESTORE;
GRANT EXECUTE ON DBMS_CRYPTO TO QLNS_RESTORE;
GRANT EXECUTE ON UTL_RAW TO QLNS_RESTORE;

PROMPT ✓ Đã tạo user QLNS_RESTORE

-- RESTORE sử dụng DBMS_DATAPUMP


PROMPT
PROMPT
=========================================================
PROMPT Đang thực hiện RESTORE...
PROMPT
=========================================================

DECLARE
v_handle NUMBER;
v_status VARCHAR2(20);
v_job_state VARCHAR2(30);
BEGIN
-- Mở Data Pump job
v_handle := DBMS_DATAPUMP.OPEN(
operation => 'IMPORT',
job_mode => 'SCHEMA',
job_name => 'QLNS_RESTORE_JOB'
);

-- Chỉ định file dump


DBMS_DATAPUMP.ADD_FILE(
handle => v_handle,
filename => 'QLNS_BACKUP.dmp',
directory => 'BACKUP_DIR',
filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_DUMP_FILE
);

-- File log
DBMS_DATAPUMP.ADD_FILE(
handle => v_handle,
filename => 'QLNS_RESTORE.log',
directory => 'BACKUP_DIR',
filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE
);

-- Remap schema: QLNS -> QLNS_RESTORE


DBMS_DATAPUMP.METADATA_REMAP(
handle => v_handle,
name => 'REMAP_SCHEMA',
old_value => 'QLNS',
value => 'QLNS_RESTORE'
);
-- Bắt đầu job
DBMS_DATAPUMP.START_JOB(v_handle);

-- Đợi job hoàn thành


DBMS_DATAPUMP.WAIT_FOR_JOB(v_handle, v_job_state);

DBMS_OUTPUT.PUT_LINE('✓ Restore hoàn thành!');


DBMS_OUTPUT.PUT_LINE(' Schema: QLNS_RESTORE');
DBMS_OUTPUT.PUT_LINE(' Log: C:\oracle_backup\QLNS_RESTORE.log');

-- Đóng job
DBMS_DATAPUMP.DETACH(v_handle);

EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -31626 THEN
-- Job đã tồn tại, drop và thử lại
BEGIN
DBMS_DATAPUMP.STOP_JOB(
DBMS_DATAPUMP.ATTACH('QLNS_RESTORE_JOB', 'SYS')
);
EXCEPTION WHEN OTHERS THEN NULL;
END;
DBMS_OUTPUT.PUT_LINE('! Job đã tồn tại, vui lòng chạy lại script');
ELSE
DBMS_OUTPUT.PUT_LINE('! Lỗi: ' || SQLERRM);
IF v_handle IS NOT NULL THEN
DBMS_DATAPUMP.DETACH(v_handle);
END IF;
END IF;
END;
/

PROMPT
PROMPT
=========================================================
PROMPT FILE 02 HOÀN THÀNH
PROMPT
=========================================================
PROMPT ✓ Restore thành công
PROMPT
PROMPT BƯỚC TIẾP THEO:
PROMPT 1. Xem log: C:\oracle_backup\QLNS_RESTORE.log
PROMPT 2. Chạy: CAU13_03_KIEM_TRA.sql
PROMPT
=========================================================
-- =========================================================
-- CÂU 13 - FILE 03: KIỂM TRA KẾT QUẢ
-- Kiểm tra backup và restore
-- CHẠY AS: SYS (SYSDBA) trong SQL Developer
-- =========================================================
SET SERVEROUTPUT ON SIZE 1000000;
ALTER SESSION SET CONTAINER = ORCLPDB;
PROMPT
=========================================================
PROMPT CÂU 13 - FILE 03: KIỂM TRA KẾT QUẢ
SHOW USER;
PROMPT
=========================================================

-- Kiểm tra user


PROMPT
PROMPT 1. Kiểm tra user QLNS_RESTORE:
SELECT USERNAME, ACCOUNT_STATUS, CREATED
FROM DBA_USERS
WHERE USERNAME = 'QLNS_RESTORE';

-- So sánh số bảng
PROMPT
PROMPT 2. So sánh số lượng bảng:
SELECT 'QLNS' AS SCHEMA, COUNT(*) AS SO_BANG
FROM DBA_TABLES WHERE OWNER = 'QLNS'
UNION ALL
SELECT 'QLNS_RESTORE', COUNT(*)
FROM DBA_TABLES WHERE OWNER = 'QLNS_RESTORE';

-- So sánh records
PROMPT
PROMPT 3. So sánh số lượng records:
SELECT
'SACH' AS BANG,
(SELECT COUNT(*) FROM [Link]) AS QLNS,
(SELECT COUNT(*) FROM QLNS_RESTORE.SACH) AS RESTORE,
CASE WHEN (SELECT COUNT(*) FROM [Link]) = (SELECT
COUNT(*) FROM QLNS_RESTORE.SACH)
THEN 'OK' ELSE 'SAI' END AS KET_QUA
FROM DUAL
UNION ALL
SELECT 'KHACHHANG',
(SELECT COUNT(*) FROM [Link]),
(SELECT COUNT(*) FROM QLNS_RESTORE.KHACHHANG),
CASE WHEN (SELECT COUNT(*) FROM [Link]) = (SELECT
COUNT(*) FROM QLNS_RESTORE.KHACHHANG)
THEN 'OK' ELSE 'SAI' END
FROM DUAL
UNION ALL
SELECT 'NHANVIEN',
(SELECT COUNT(*) FROM [Link]),
(SELECT COUNT(*) FROM QLNS_RESTORE.NHANVIEN),
CASE WHEN (SELECT COUNT(*) FROM [Link]) = (SELECT
COUNT(*) FROM QLNS_RESTORE.NHANVIEN)
THEN 'OK' ELSE 'SAI' END
FROM DUAL
UNION ALL
SELECT 'HOADON',
(SELECT COUNT(*) FROM [Link]),
(SELECT COUNT(*) FROM QLNS_RESTORE.HOADON),
CASE WHEN (SELECT COUNT(*) FROM [Link]) = (SELECT
COUNT(*) FROM QLNS_RESTORE.HOADON)
THEN 'OK' ELSE 'SAI' END
FROM DUAL
UNION ALL
SELECT 'CHITIETHOADON',
(SELECT COUNT(*) FROM [Link]),
(SELECT COUNT(*) FROM QLNS_RESTORE.CHITIETHOADON),
CASE WHEN (SELECT COUNT(*) FROM [Link]) =
(SELECT COUNT(*) FROM QLNS_RESTORE.CHITIETHOADON)
THEN 'OK' ELSE 'SAI' END
FROM DUAL;

-- Xem dữ liệu mẫu


PROMPT
PROMPT 4. Dữ liệu mẫu SACH:
SELECT MASACH, TENSACH, TACGIA, GIABAN
FROM QLNS_RESTORE.SACH
WHERE ROWNUM <= 3
ORDER BY MASACH;

PROMPT
PROMPT 5. Dữ liệu mẫu NHANVIEN:
SELECT MANV, HOTEN, CHUCVU, TENDANGNHAP
FROM QLNS_RESTORE.NHANVIEN
WHERE ROWNUM <= 3
ORDER BY MANV;
PROMPT
PROMPT 6. Dữ liệu mẫu HOADON:
SELECT MAHD, NGAYLAP, MAKH, MANV, TONGTIEN
FROM QLNS_RESTORE.HOADON
WHERE ROWNUM <= 3
ORDER BY MAHD;

-- So sánh objects
PROMPT
PROMPT 7. So sánh objects:
SELECT
NVL(o1.OBJECT_TYPE, o2.OBJECT_TYPE) AS OBJECT_TYPE,
NVL([Link], 0) AS QLNS,
NVL([Link], 0) AS RESTORE
FROM
(SELECT OBJECT_TYPE, COUNT(*) AS CNT
FROM DBA_OBJECTS
WHERE OWNER = 'QLNS'
AND OBJECT_TYPE IN
('TABLE','VIEW','PROCEDURE','FUNCTION','TRIGGER','SEQUENCE')
GROUP BY OBJECT_TYPE) o1
FULL OUTER JOIN
(SELECT OBJECT_TYPE, COUNT(*) AS CNT
FROM DBA_OBJECTS
WHERE OWNER = 'QLNS_RESTORE'
AND OBJECT_TYPE IN
('TABLE','VIEW','PROCEDURE','FUNCTION','TRIGGER','SEQUENCE')
GROUP BY OBJECT_TYPE) o2
ON o1.OBJECT_TYPE = o2.OBJECT_TYPE
ORDER BY OBJECT_TYPE;

-- Báo cáo tổng kết


PROMPT
PROMPT
=========================================================
PROMPT BAO CAO TONG KET
PROMPT
=========================================================

DECLARE
v_qlns_tables NUMBER;
v_restore_tables NUMBER;
v_match_count NUMBER := 0;
v_qlns_cnt NUMBER;
v_restore_cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO v_qlns_tables FROM DBA_TABLES WHERE
OWNER = 'QLNS';
SELECT COUNT(*) INTO v_restore_tables FROM DBA_TABLES WHERE
OWNER = 'QLNS_RESTORE';

SELECT COUNT(*) INTO v_qlns_cnt FROM [Link];


SELECT COUNT(*) INTO v_restore_cnt FROM QLNS_RESTORE.SACH;
IF v_qlns_cnt = v_restore_cnt THEN v_match_count := v_match_count + 1; END
IF;

SELECT COUNT(*) INTO v_qlns_cnt FROM [Link];


SELECT COUNT(*) INTO v_restore_cnt FROM
QLNS_RESTORE.KHACHHANG;
IF v_qlns_cnt = v_restore_cnt THEN v_match_count := v_match_count + 1; END
IF;

SELECT COUNT(*) INTO v_qlns_cnt FROM [Link];


SELECT COUNT(*) INTO v_restore_cnt FROM QLNS_RESTORE.NHANVIEN;
IF v_qlns_cnt = v_restore_cnt THEN v_match_count := v_match_count + 1; END
IF;

SELECT COUNT(*) INTO v_qlns_cnt FROM [Link];


SELECT COUNT(*) INTO v_restore_cnt FROM QLNS_RESTORE.HOADON;
IF v_qlns_cnt = v_restore_cnt THEN v_match_count := v_match_count + 1; END
IF;

SELECT COUNT(*) INTO v_qlns_cnt FROM [Link];


SELECT COUNT(*) INTO v_restore_cnt FROM
QLNS_RESTORE.CHITIETHOADON;
IF v_qlns_cnt = v_restore_cnt THEN v_match_count := v_match_count + 1; END
IF;

DBMS_OUTPUT.PUT_LINE('======================================
===================');
DBMS_OUTPUT.PUT_LINE('BACKUP:');
DBMS_OUTPUT.PUT_LINE(' Schema: QLNS');
DBMS_OUTPUT.PUT_LINE(' So bang: ' || v_qlns_tables);
DBMS_OUTPUT.PUT_LINE(' File: C:\oracle_backup\QLNS_BACKUP.dmp');
DBMS_OUTPUT.PUT_LINE('');
DBMS_OUTPUT.PUT_LINE('RESTORE:');
DBMS_OUTPUT.PUT_LINE(' Schema: QLNS_RESTORE');
DBMS_OUTPUT.PUT_LINE(' So bang: ' || v_restore_tables);
DBMS_OUTPUT.PUT_LINE(' File: C:\oracle_backup\QLNS_RESTORE.log');
DBMS_OUTPUT.PUT_LINE('');
DBMS_OUTPUT.PUT_LINE('KET QUA:');
DBMS_OUTPUT.PUT_LINE(' Bang khop: ' || v_match_count || '/5');

IF v_match_count = 5 AND v_qlns_tables = v_restore_tables THEN


DBMS_OUTPUT.PUT_LINE(' Trang thai: THANH CONG');
DBMS_OUTPUT.PUT_LINE('');

DBMS_OUTPUT.PUT_LINE('======================================
===================');
DBMS_OUTPUT.PUT_LINE('*** CAU 13 HOAN THANH: BACKUP &
RESTORE THANH CONG! ***');

DBMS_OUTPUT.PUT_LINE('======================================
===================');
ELSE
DBMS_OUTPUT.PUT_LINE(' Trang thai: CAN KIEM TRA LAI');
DBMS_OUTPUT.PUT_LINE('');

DBMS_OUTPUT.PUT_LINE('======================================
===================');
DBMS_OUTPUT.PUT_LINE('! CAU 13 CAN KIEM TRA LAI');

DBMS_OUTPUT.PUT_LINE('======================================
===================');
END IF;
END;
/

PROMPT
PROMPT Tuy chon: Xoa user QLNS_RESTORE sau khi test xong
PROMPT DROP USER QLNS_RESTORE CASCADE;
PROMPT

-- =========================================================
-- CÂU 11: ORACLE LABEL SECURITY - FILE 04
-- Test OLS Policy với nhiều database users
-- CHẠY AS: Tạo nhiều connections riêng biệt
-- Thời gian: 3-5 phút
-- =========================================================

-- =========================================================
-- HƯỚNG DẪN SETUP:
-- =========================================================
-- Trong SQL Developer, tạo 5 connections riêng:
--
-- Connection 1: QLNS
-- Username: QLNS
-- Password: qlns
-- Role: Default
-- Service: ORCLPDB
--
-- Connection 2: ADMIN
-- Username: ADMIN
-- Password: admin
-- Role: Default
-- Service: ORCLPDB
--
-- Connection 3: HOATV (nhân viên kho)
-- Username: HOATV
-- Password: user01
-- Role: Default
-- Service: ORCLPDB
--
-- Connection 4: MAIANH (nhân viên bán hàng)
-- Username: MAIANH
-- Password: user01
-- Role: Default
-- Service: ORCLPDB
--
-- Connection 5: NGUYEN (quản lý)
-- Username: NGUYEN
-- Password: 123
-- Role: Default
-- Service: ORCLPDB
-- =========================================================

PROMPT
=========================================================
PROMPT CÂU 11 - FILE 04: TEST OLS POLICY
PROMPT
=========================================================

SET SERVEROUTPUT ON SIZE 1000000;


ALTER SESSION SET CONTAINER = ORCLPDB;

PROMPT
PROMPT === ĐANG LOGIN AS:
SHOW USER;
PROMPT
=========================================================

-- =========================================================
-- PHẦN 1: KIỂM TRA USER LABEL CỦA MÌNH
-- =========================================================
PROMPT
PROMPT 1. Kiểm tra user label của bạn:
PROMPT
=========================================================

BEGIN
DBMS_OUTPUT.PUT_LINE('User hiện tại: ' || USER);
DBMS_OUTPUT.PUT_LINE('Session user: ' || SYS_CONTEXT('USERENV',
'SESSION_USER'));
DBMS_OUTPUT.PUT_LINE('Max Read Label: ' ||
SA_SESSION.MAX_READ_LABEL('NHANSU_POL'));
DBMS_OUTPUT.PUT_LINE('Current Label: ' ||
SA_SESSION.LABEL('NHANSU_POL'));
END;
/

-- =========================================================
-- PHẦN 2: XEM DỮ LIỆU NHANVIEN (BỊ GIỚI HẠN BỞI OLS)
-- =========================================================
PROMPT
PROMPT 2. Xem dữ liệu NHANVIEN (có OLS policy):
PROMPT
=========================================================

SELECT
MANV,
HOTEN,
CHUCVU,
TENDANGNHAP,
QUYENHAN,
OLS_LABEL,
LABEL_TO_CHAR(OLS_LABEL) AS LABEL_NAME
FROM [Link]
ORDER BY OLS_LABEL DESC, MANV;
PROMPT
PROMPT 3. Đếm số records nhìn thấy:
PROMPT
=========================================================

SELECT COUNT(*) AS SO_NHANVIEN_NHIN_THAY


FROM [Link];

-- =========================================================
-- PHẦN 3: GIẢI THÍCH KẾT QUẢ
-- =========================================================
PROMPT
PROMPT
=========================================================
PROMPT GIẢI THÍCH KẾT QUẢ THEO USER:
PROMPT
=========================================================
PROMPT
PROMPT ** QLNS (owner, label SEC) **
PROMPT → Nhìn thấy: 6/6 nhân viên (tất cả)
PROMPT → Lý do: Owner có quyền cao nhất
PROMPT
PROMPT ** ADMIN (label SEC) **
PROMPT → Nhìn thấy: 6/6 nhân viên (tất cả)
PROMPT → Lý do: Label SEC >= tất cả data labels (PUB, CONF:*, SEC)
PROMPT
PROMPT ** NGUYEN (label SEC) **
PROMPT → Nhìn thấy: 6/6 nhân viên (tất cả)
PROMPT → Lý do: Label SEC >= tất cả data labels
PROMPT
PROMPT ** PHUONG (label SEC) **
PROMPT → Nhìn thấy: 6/6 nhân viên (tất cả)
PROMPT → Lý do: Label SEC >= tất cả data labels
PROMPT
PROMPT ** QUOC (label SEC) **
PROMPT → Nhìn thấy: 6/6 nhân viên (tất cả)
PROMPT → Lý do: Label SEC >= tất cả data labels
PROMPT
PROMPT ** HOATV (label CONF:KHO) **
PROMPT → Nhìn thấy: 1/6 nhân viên (chỉ chính mình)
PROMPT → Lý do:
PROMPT - Có compartment KHO → thấy records có label CONF:KHO (30)
PROMPT - KHÔNG có compartment BH → không thấy CONF:BH (20)
PROMPT - KHÔNG có level SECRET → không thấy SEC (50)
PROMPT - Có level CONFIDENTIAL >= PUBLIC → thấy PUB (10) nếu có
PROMPT
PROMPT ** MAIANH (label CONF:BH) **
PROMPT → Nhìn thấy: 1/6 nhân viên (chỉ chính mình)
PROMPT → Lý do:
PROMPT - Có compartment BH → thấy records có label CONF:BH (20)
PROMPT - KHÔNG có compartment KHO → không thấy CONF:KHO (30)
PROMPT - KHÔNG có level SECRET → không thấy SEC (50)
PROMPT - Có level CONFIDENTIAL >= PUBLIC → thấy PUB (10) nếu có
PROMPT
PROMPT
=========================================================

-- =========================================================
-- PHẦN 4: BẢNG TỔNG HỢP KẾT QUẢ
-- =========================================================
PROMPT
PROMPT
=========================================================
PROMPT BẢNG TỔNG HỢP KẾT QUẢ MONG ĐỢI:
PROMPT
=========================================================
PROMPT
PROMPT +-------------+---------------+---------------------+
PROMPT | User | User Label | Nhìn thấy (records) |
PROMPT +-------------+---------------+---------------------+
PROMPT | QLNS | SEC | 6/6 (tất cả) |
PROMPT | ADMIN | SEC | 6/6 (tất cả) |
PROMPT | NGUYEN | SEC | 6/6 (tất cả) |
PROMPT | PHUONG | SEC | 6/6 (tất cả) |
PROMPT | QUOC | SEC | 6/6 (tất cả) |
PROMPT | HOATV | CONF:KHO | 1/6 (chỉ hoatv) |
PROMPT | MAIANH | CONF:BH | 1/6 (chỉ maianh) |
PROMPT +-------------+---------------+---------------------+
PROMPT
PROMPT Data Labels trong NHANVIEN:
PROMPT - 4 admin users (admin, Nguyen, Phuong, Quoc) → SEC (50)
PROMPT - 1 kho (hoatv) → CONF:KHO (30)
PROMPT - 1 bán hàng (maianh) → CONF:BH (20)
PROMPT
PROMPT
=========================================================

-- =========================================================
-- PHẦN 5: TEST THÊM - THỬ INSERT (CHỈ CHO ADMIN/OWNER)
-- =========================================================
PROMPT
PROMPT
=========================================================
PROMPT PHẦN 5: TEST INSERT (tùy chọn - chỉ chạy nếu là ADMIN/QLNS)
PROMPT
=========================================================
PROMPT
PROMPT LƯU Ý: Nếu bạn là HOATV hoặc MAIANH, INSERT sẽ BỊ LỖI
PROMPT vì không có quyền INSERT trên NHANVIEN
PROMPT
PROMPT Bỏ comment dòng dưới để test INSERT:
PROMPT
-- INSERT INTO [Link] (MANV, HOTEN, CHUCVU,
TENDANGNHAP, SALT, MATKHAU_GOC, OLS_LABEL)
-- VALUES ('NV999', 'Test User', 'Test', 'testuser', 'salt_test', 'test123', 30);
-- ROLLBACK;
PROMPT
PROMPT (Script đã ROLLBACK để không làm thay đổi dữ liệu)
PROMPT
-- =========================================================
-- PHẦN 6: KIỂM TRA CONTEXT
-- =========================================================
PROMPT
PROMPT
=========================================================
PROMPT PHẦN 6: KIỂM TRA CONTEXT (debug info)
PROMPT
=========================================================

SELECT
SYS_CONTEXT('CTX_NHASACH', 'USER_MANV') AS MY_MANV,
SYS_CONTEXT('CTX_NHASACH', 'USER_QUYENHAN') AS
MY_QUYENHAN,
SYS_CONTEXT('USERENV', 'SESSION_USER') AS SESSION_USER,
SYS_CONTEXT('USERENV', 'CURRENT_USER') AS CURRENT_USER
FROM DUAL;

PROMPT
PROMPT
=========================================================
PROMPT === FILE 04 HOÀN THÀNH - KẾT QUẢ TEST OLS ===
PROMPT
=========================================================
PROMPT
PROMPT ĐÃ TEST:
PROMPT ✓ User label của từng user
PROMPT ✓ Số lượng records nhìn thấy trong NHANVIEN
PROMPT ✓ Context values
PROMPT
PROMPT KẾT LUẬN:
PROMPT ✓ OLS Policy hoạt động đúng
PROMPT ✓ Users với SEC thấy tất cả (6/6)
PROMPT ✓ Users với CONF:KHO chỉ thấy KHO (1/6)
PROMPT ✓ Users với CONF:BH chỉ thấy BH (1/6)
PROMPT
PROMPT ==> CÂU 11 HOÀN THÀNH: OLS POLICY HOẠT ĐỘNG ĐÚNG!
PROMPT
=========================================================

You might also like