Giao diện
Cấu hình chi tiết — Password Policy
Cấu trúc dữ liệu chính sách
Chính sách mật khẩu được lưu trong bảng passwordPolicy dưới dạng JSONB (field options):
typescript
interface PasswordPolicy {
minLength: number; // Độ dài tối thiểu (mặc định: 6)
complexity: // Mức độ phức tạp
| 'alpha_numeric'
| 'alpha_numeric_special'
| 'numbers_upper_lower'
| 'numbers_upper_lower_special'
| '3_of_4'
| 'none';
cantIncludeUsername: boolean; // Cấm chứa username (mặc định: true)
validityPeriod: 30 | 90 | 180 | 365 | 0; // Thời hạn (ngày, 0 = vĩnh viễn)
expirationNotificationChannel: string[]; // Kênh thông báo hết hạn
historyCount: number; // Số mật khẩu cũ không được trùng (mặc định: 3)
maxSignInAttempts: 3 | 5 | 10 | 0; // Số lần đăng nhập sai tối đa (0 = không giới hạn)
maxSignInAttemptsInterval: number; // Khoảng thời gian đếm (giây, mặc định: 600)
lockoutDuration: number; // Thời gian khóa (giây, 0 = không khóa)
}Các quy tắc mật khẩu
Quy tắc độ phức tạp chi tiết
| Mức | Regex áp dụng | Mô tả |
|---|---|---|
none | Không có | Chỉ kiểm tra độ dài |
alpha_numeric | /[a-zA-Z]/ + /\d/ | Chữ cái + số |
alpha_numeric_special | /[a-zA-Z]/ + /\d/ + /[^\w\s]/ | Chữ cái + số + ký tự đặc biệt |
numbers_upper_lower | /[a-z]/ + /[A-Z]/ + /\d/ | Chữ thường + chữ hoa + số |
numbers_upper_lower_special | /[a-z]/ + /[A-Z]/ + /\d/ + /[^\w\s]/ | Chữ thường + chữ hoa + số + ký tự đặc biệt |
3_of_4 | 3 trong 4: /[a-z]/, /[A-Z]/, /\d/, /[^\w\s]/ | Linh hoạt — đạt ít nhất 3 loại |
Luồng kiểm tra khi đổi mật khẩu
Lịch sử mật khẩu
| Tham số | Giá trị | Mô tả |
|---|---|---|
historyCount | 0 | Tắt — không kiểm tra lịch sử |
historyCount | 3 (mặc định) | Không được trùng 3 mật khẩu gần nhất |
historyCount | 1–24 | Tối đa 24 (hard limit trong code: MAX_HISTORY_COUNT = 24) |
Plugin kiểm tra bằng cách lấy N bản ghi gần nhất từ userPasswordHistory, rồi dùng PasswordField.verify() để so sánh hash.
Bảo mật đăng nhập
Cơ chế đếm lần đăng nhập sai
Plugin sử dụng Counter từ @digiforce-nc/cache để đếm số lần đăng nhập sai:
Cơ chế khóa tài khoản
| Tham số | Ý nghĩa |
|---|---|
lockoutDuration = 0 | Không khóa — chỉ báo lỗi "thử lại sau" |
lockoutDuration > 0 | Khóa tài khoản trong N giây, ghi vào bảng lockedUsers |
Plugin dùng BloomFilter để kiểm tra nhanh user có bị khóa không trước khi truy vấn database, giảm tải cho các hệ thống có nhiều request.
Tự động mở khóa
Khi unlockTs đã qua (hết thời gian khóa):
- Bản ghi
lockedUsersbị xóa - Counter đăng nhập sai được reset về 0
- User có thể đăng nhập bình thường
Cấu hình hết hạn mật khẩu
Cách tính thời hạn
expirationTs = createdTs (lần đổi gần nhất) + validityPeriod × 24 × 60 × 60 × 1000 msvalidityPeriod | Ý nghĩa |
|---|---|
0 | Mật khẩu không bao giờ hết hạn |
30 | Hết hạn sau 30 ngày |
90 | Hết hạn sau 90 ngày |
180 | Hết hạn sau 180 ngày |
365 | Hết hạn sau 365 ngày |
Thông báo cảnh báo
Khi mật khẩu còn ≤ 10 ngày trước khi hết hạn, plugin gửi thông báo in-app qua plugin-notification-manager mỗi lần user đăng nhập thành công.
Cấu hình qua API
Cập nhật chính sách
typescript
await api.resource('passwordPolicy').update({
values: {
options: {
minLength: 10,
complexity: 'numbers_upper_lower_special',
cantIncludeUsername: true,
validityPeriod: 90,
historyCount: 5,
maxSignInAttempts: 5,
maxSignInAttemptsInterval: 600,
lockoutDuration: 1800,
},
},
});Đọc chính sách hiện tại (admin)
typescript
const result = await api.resource('passwordPolicy').list();Đọc chính sách công khai (client-side validation)
typescript
const result = await api.resource('passwordPolicy').publicList();
// Trả về: { minLength, complexity, cantIncludeUsername }Lưu ý:
publicListchỉ trả về thông tin cần cho client-side validation, không expose các tham số bảo mật nhưmaxSignInAttemptshaylockoutDuration.
Tích hợp với workflow
Có thể kết hợp với workflow để:
- Gửi email nhắc đổi mật khẩu khi sắp hết hạn
- Tự động khóa tài khoản khi phát hiện hành vi bất thường
- Thông báo admin khi có nhiều lần đăng nhập thất bại