Now.js Framework Documentation
SecurityManager
SecurityManager
ภาพรวม
SecurityManager คือระบบจัดการความปลอดภัยใน Now.js Framework รองรับ CSRF, JWT, Rate Limiting และ Content Security Policy
ใช้เมื่อ:
- ต้องการป้องกัน CSRF attacks
- ต้องการจัดการ JWT tokens
- ต้องการ rate limiting
- ต้องการ input sanitization
- ต้องการ CSP management
ทำไมต้องใช้:
- ✅ CSRF protection (token-based)
- ✅ JWT management (validate, refresh)
- ✅ Rate limiting (per endpoint)
- ✅ Input sanitization (XSS prevention)
- ✅ Content Security Policy
- ✅ HTTP interceptors
- ✅ Form protection
การใช้งานพื้นฐาน
Initialization
await SecurityManager.init({
csrf: {
enabled: true,
tokenName: '_token',
headerName: 'X-CSRF-Token'
},
jwt: {
enabled: true,
storageName: 'auth_token',
autoRefresh: true
},
rateLimit: {
enabled: true,
globalLimit: 100,
windowMs: 15 * 60 * 1000 // 15 minutes
}
});CSRF Protection
Auto-inject in Forms
<form action="/api/submit" method="POST">
<!-- CSRF token จะถูก inject อัตโนมัติ -->
<input type="text" name="email">
<button type="submit">Submit</button>
</form>Get CSRF Token
const token = SecurityManager.getCSRFToken();
console.log(token); // 'abc123...'Manual CSRF in Requests
// SecurityManager จะ inject อัตโนมัติใน ApiService
await ApiService.post('/api/data', {
name: 'John'
});
// Request จะมี X-CSRF-Token header อัตโนมัติRefresh CSRF Token
await SecurityManager.refreshCSRFToken();JWT Management
Get JWT Token
const token = SecurityManager.getJWTToken();Validate Token
const isValid = SecurityManager.validateJWTToken(token);
if (!isValid) {
// Token expired or invalid
redirectToLogin();
}Refresh Token
await SecurityManager.refreshJWTToken();Clear Token (Logout)
SecurityManager.clearJWTToken();Auto-refresh Token
SecurityManager.init({
jwt: {
enabled: true,
autoRefresh: true,
refreshThreshold: 5 * 60 * 1000 // Refresh 5 mins before expiry
}
});Rate Limiting
Check Rate Limit
const result = SecurityManager.checkRateLimit('/api/login');
if (!result.allowed) {
console.log(`Rate limited. Retry after ${result.retryAfter}ms`);
}Per-Endpoint Limits
SecurityManager.init({
rateLimit: {
enabled: true,
globalLimit: 100,
perEndpoint: {
'/api/login': { limit: 5, windowMs: 60000 }, // 5 per minute
'/api/register': { limit: 3, windowMs: 60000 }, // 3 per minute
'/api/upload': { limit: 10, windowMs: 300000 } // 10 per 5 minutes
}
}
});Input Sanitization
Sanitize Input
// ป้องกัน XSS
const safeInput = SecurityManager.sanitizeInput(userInput);
// '<script>alert("xss")</script>' => '<script>alert("xss")</script>'Sanitize Object
const safeData = SecurityManager.sanitizeRequestData({
name: '<script>alert("xss")</script>',
email: 'user@example.com'
});
// { name: '<script>...', email: 'user@example.com' }Content Security Policy
CSP Configuration
SecurityManager.init({
csp: {
enabled: true,
directives: {
'default-src': ["'self'"],
'script-src': ["'self'", "'unsafe-inline'"],
'style-src': ["'self'", "'unsafe-inline'"],
'img-src': ["'self'", "data:", "https:"],
'connect-src': ["'self'"],
'frame-src': ["'none'"],
'object-src': ["'none'"]
}
}
});CSP Violation Reporting
SecurityManager.init({
csp: {
enabled: true,
reportUri: '/api/csp-report'
}
});
// Listen for violations
EventManager.on('csp:violation', (violation) => {
console.log('CSP Violation:', violation);
});การตั้งค่า
await SecurityManager.init({
// CSRF
csrf: {
enabled: true,
tokenName: '_token',
headerName: 'X-CSRF-Token',
cookieName: 'XSRF-TOKEN',
tokenUrl: '/api/auth/csrf-token',
autoRefresh: true,
refreshInterval: 30 * 60 * 1000 // 30 minutes
},
// JWT
jwt: {
enabled: true,
cookieName: 'auth_token',
refreshCookieName: 'refresh_token',
storageKey: 'auth_jwt', // ดูหมายเหตุด้านล่าง
autoRefresh: true,
refreshBeforeExpiry: 5 * 60 * 1000, // 5 นาที
refreshEndpoint: 'api/auth/refresh',
validateSignature: true,
algorithm: 'HS256',
issuer: window.location.hostname,
audience: window.location.hostname
},
// Rate Limiting
rateLimit: {
enabled: true,
storage: 'memory',
globalLimit: 100,
windowMs: 15 * 60 * 1000,
perEndpoint: {}
},
// CSP
csp: {
enabled: false,
directives: {}
}
});
jwt.storageKeyต้องไม่ชนกับtoken.storageKeyของAuthManager
ค่าเริ่มต้นคือ'auth_jwt'เก็บ สตริง JWT ส่วนAuthManagerเก็บ
โปรไฟล์ผู้ใช้ (ออบเจ็กต์ JSON) ไว้ที่'auth_user'เดิมทั้งคู่ตั้งค่า
เริ่มต้นเป็น'auth_user'เหมือนกัน ทำให้initJWT()อ่านโปรไฟล์ขึ้นมา
ตรวจว่าไม่ใช่ JWT แล้วclearJWTToken()ก็ลบทิ้งทุกครั้งที่โหลดหน้า
โปรไฟล์ที่แคชไว้จึงไม่เคยอยู่รอด และแอปเปิดตอนออฟไลน์ไม่ได้
ถ้าแอปของคุณเขียน JWT ลง'auth_user'เอง ให้ย้ายไป'auth_jwt'
(หรือกำหนดstorageKeyเป็นคีย์อื่นของคุณเอง) ตอนอัปเกรด
ทั้งนี้ในการใช้งานปกติ token จริงอยู่ใน httpOnly cookie คีย์นี้จึงแทบไม่ถูกใช้
API อ้างอิง
CSRF Methods
SecurityManager.getCSRFToken()
รับ CSRF token ปัจจุบัน
Returns: string|null
SecurityManager.refreshCSRFToken()
Refresh CSRF token จาก server
Returns: Promise<string>
SecurityManager.injectCSRFIntoForm(form, token?)
Inject CSRF token ใน form
| Parameter | Type | Description |
|---|---|---|
form |
HTMLFormElement | Form element |
JWT Methods
SecurityManager.getJWTToken()
รับ JWT token
Returns: string|null
SecurityManager.validateJWTToken(token)
Validate JWT token
| Parameter | Type | Description |
|---|---|---|
token |
string | JWT token |
Returns: boolean
SecurityManager.refreshJWTToken()
Refresh JWT token
Returns: Promise<string>
SecurityManager.clearJWTToken()
Clear JWT token (logout)
Rate Limit Methods
SecurityManager.checkRateLimit(endpoint, identifier?)
ตรวจสอบ rate limit
| Parameter | Type | Description |
|---|---|---|
endpoint |
string | API endpoint |
identifier |
string | User identifier (optional) |
Returns: Object:
{
allowed: boolean,
remaining: number,
resetTime: number,
retryAfter: number
}Sanitization Methods
SecurityManager.sanitizeInput(value)
Sanitize input string
| Parameter | Type | Description |
|---|---|---|
value |
string | Input value |
Returns: string - Sanitized value
SecurityManager.sanitizeRequestData(data)
Sanitize object/array recursively
| Parameter | Type | Description |
|---|---|---|
data |
object/array | Data to sanitize |
Returns: object/array - Sanitized data
Data Attributes
| Attribute | คำอธิบาย |
|---|---|
data-csrf |
ใส่บน <form> ตั้ง false หรือ disabled เพื่อไม่ให้แนบ CSRF token กับฟอร์มนั้น |
เหตุการณ์
| Event | เมื่อเกิด | Detail |
|---|---|---|
security:initialized |
init() เสร็จ | {csrf, jwt} |
csrf:refreshed |
ได้ CSRF token ใหม่ | {token} |
csrf:retry |
เจอ CSRF ไม่ผ่าน (419) กำลังให้โอกาสส่งซ้ำ | {token} |
jwt:refreshed |
ได้ JWT ใหม่ | {token} |
jwt:cleared |
ลบ JWT ที่เก็บไว้ | ไม่มี |
csp:violation |
เบราว์เซอร์รายงานการละเมิด CSP | {directive, uri, source, line, timestamp} (ส่งตรง ไม่ห่อ) |
security:error |
เกิดข้อผิดพลาดด้านความปลอดภัย | {message, error} |
security:destroyed |
destroy() เสร็จ | ไม่มี |
ตัวอย่างการใช้งานจริง
Protected API Calls
// SecurityManager จะ inject headers อัตโนมัติ
async function saveProfile(data) {
try {
// CSRF และ JWT headers จะถูกเพิ่มอัตโนมัติ
await ApiService.put('/api/profile', data);
NotificationManager.success('บันทึกแล้ว');
} catch (error) {
if (error.status === 419) {
// CSRF token expired
await SecurityManager.refreshCSRFToken();
// Retry
return saveProfile(data);
}
throw error;
}
}Login with Rate Limiting
async function login(email, password) {
// Check rate limit
const limit = SecurityManager.checkRateLimit('/api/login');
if (!limit.allowed) {
throw new Error(`ลองอีกครั้งใน ${Math.ceil(limit.retryAfter / 1000)} วินาที`);
}
const response = await ApiService.post('/api/login', {
email: SecurityManager.sanitizeInput(email),
password
});
return response;
}Form with CSRF Protection
<form id="contact-form" action="/api/contact" method="POST" data-security>
<input type="text" name="name" required>
<input type="email" name="email" required>
<textarea name="message" required></textarea>
<button type="submit">ส่งข้อความ</button>
</form>
<script>
// SecurityManager จะ:
// 1. Inject CSRF token
// 2. Sanitize inputs
// 3. Check rate limit
// ... อัตโนมัติ
</script>ข้อควรระวัง
⚠️ 1. Enable CSRF สำหรับ Production
// ❌ CSRF disabled in production
SecurityManager.init({ csrf: { enabled: false } });
// ✅ Enable CSRF
SecurityManager.init({ csrf: { enabled: true } });⚠️ 2. JWT Token ใน Memory
// ❌ ไม่ควรเก็บ JWT ใน localStorage สำหรับข้อมูลสำคัญมาก
jwt: { storageType: 'localStorage' }
// ✅ ใช้ memory หรือ httpOnly cookie
jwt: { storageType: 'memory' }⚠️ 3. Sanitize User Input
// ❌ ใช้ user input โดยตรง
element.innerHTML = userInput;
// ✅ Sanitize ก่อน
element.innerHTML = SecurityManager.sanitizeInput(userInput);
// หรือใช้ textContent
element.textContent = userInput;เอกสารที่เกี่ยวข้อง
- AuthManager - Authentication
- ApiService - API calls
- HttpClient - HTTP client