Bỏ qua, đến nội dung

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ứcRegex áp dụngMô tả
noneKhô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_43 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ả
historyCount0Tắt — không kiểm tra lịch sử
historyCount3 (mặc định)Không được trùng 3 mật khẩu gần nhất
historyCount1–24Tố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 = 0Không khóa — chỉ báo lỗi "thử lại sau"
lockoutDuration > 0Khó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):

  1. Bản ghi lockedUsers bị xóa
  2. Counter đăng nhập sai được reset về 0
  3. 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 ms
validityPeriodÝ nghĩa
0Mật khẩu không bao giờ hết hạn
30Hết hạn sau 30 ngày
90Hết hạn sau 90 ngày
180Hết hạn sau 180 ngày
365Hế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 ý: publicList chỉ trả về thông tin cần cho client-side validation, không expose các tham số bảo mật như maxSignInAttempts hay lockoutDuration.

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