เนื้อหา › ผู้ใช้และการยืนยันตัวตน
เริ่มต้น
เนื้อหา
Plugins
การดูแลระบบ
สูตรสำเร็จ
ผู้ใช้และการยืนยันตัวตน
หน้านี้สอนอะไร
ใคร login เข้าหน้า admin ได้ บทบาททำงานอย่างไร การสร้างผู้ใช้ และ session กับ token ยืนยันตัวตน request จาก browser และแอปอื่นอย่างไร
ควรอ่านก่อน: เริ่มใช้งาน
collection users ที่มีในตัวเก็บคนที่ใช้หน้า admin เช่น บรรณาธิการ ผู้เขียน นักพัฒนา แยกจากลูกค้า
หรือสมาชิกของเว็บคุณ ซึ่งควรเก็บใน collection หรือระบบ auth ของคุณเอง
Collection users
| Field | |
|---|---|
email | ไม่ซ้ำกัน ใช้ login จัดเก็บเป็นตัวพิมพ์เล็ก |
name | แสดงในหน้า admin (ไม่บังคับ) |
role | หนึ่งใน auth.roles มีแต่ admin ที่เปลี่ยนได้ |
active | ถ้าเอาเครื่องหมายออก จะ login ไม่ได้และทุก session ของคนนั้นจะหมดอายุ มีแต่ admin ที่เปลี่ยนได้ |
password | เขียนได้อย่างเดียว: รับตอนสร้างและแก้ ไม่ถูกส่งคืน ยาวอย่างน้อย 8 ตัวอักษร |
เพิ่ม field กฎสิทธิ์ หรือ hook ของคุณเองได้โดยประกาศ collection users ระบบจะรวมเข้ากับของเดิม:
collections: [
{
slug: 'users',
fields: [
{ name: 'phone', type: 'text' },
{ name: 'avatar', type: 'upload' },
],
},
]ค่าเริ่มต้น: ผู้ใช้ที่ login อ่านรายชื่อผู้ใช้ได้ admin สร้างและลบผู้ใช้ และผู้ใช้แก้ข้อมูลตัวเองได้
(แต่แก้ role หรือ active ของตัวเองไม่ได้)
บทบาท
auth: { roles: ['admin', 'editor', 'author'] } // ค่าเริ่มต้น: ['admin', 'editor']ต้องมี admin เสมอ admin ทำได้ทุกอย่างรวมถึงจัดการผู้ใช้ บทบาทอื่นมีความหมายตาม
กฎสิทธิ์ ที่คุณเขียน เช่น:
{
slug: 'posts',
access: {
read: () => true,
// author สร้างได้, editor และ admin เผยแพร่ได้ทุกบทความ, author แก้ได้เฉพาะของตัวเอง
create: ({ user }) => !!user,
update: ({ user }) =>
user?.role === 'author' ? { author: { equals: user.id } } : !!user,
delete: ({ user }) => user?.role === 'admin' || user?.role === 'editor',
},
}ผู้ใช้ใหม่จะได้บทบาท editor ถ้ามีบทบาทนี้ (ไม่อย่างนั้นได้บทบาทสุดท้าย)
ถ้าต้องการให้ admin เพิ่มบทบาทและติ๊กเลือกสิทธิ์ของแต่ละบทบาทในหน้า admin ได้เองโดยไม่ต้องเขียนโค้ด ให้เปิด
บทบาทและสิทธิ์จากหน้า admin (auth: { rbac: true }) ส่วนการเข้าสู่ระบบด้วย Google, Microsoft,
GitHub หรือผู้ให้บริการ OpenID Connect อื่น ดูที่ Single sign-on
Easy CMS ไม่ยอมให้เปลี่ยนแปลงที่ทำให้ไม่เหลือ admin ที่ใช้งานอยู่ (ลบ ลดบทบาท หรือปิดใช้งาน admin คนสุดท้าย) จึงไม่มีใครถูกล็อกออกจากระบบ
สร้างผู้ใช้
- admin คนแรก: ถ้ายังไม่มีผู้ใช้ หน้า admin จะแสดงฟอร์มให้สร้าง ถ้าทำจาก terminal หรือใน CI ให้รัน
npx easy-cms create-admin(ดู CLI) - คนอื่นๆ: admin เพิ่มผู้ใช้ได้ที่ ตั้งค่า → ผู้ใช้ ในหน้า admin หรือในโค้ด:
await cms.create('users', { email: 'ann@example.com', password: 'at least 8 chars', role: 'editor' })รหัสผ่าน hash ด้วย scrypt และไม่ถูกส่งคืน
ลืมรหัสผ่านและคำเชิญ


เมื่อตั้งค่า อีเมล แล้ว CMS จะส่งลิงก์สำหรับตั้งรหัสผ่านได้
- ลืมรหัสผ่าน? ในหน้า login ส่งลิงก์ที่ใช้ได้ครั้งเดียวภายใน 1 ชั่วโมง หน้านี้ตอบเหมือนกันทุกครั้ง ไม่ว่าอีเมลนั้นจะมีบัญชีหรือไม่ จึงใช้ตรวจไม่ได้ว่าใครมีบัญชี และรับคำขอได้ไม่กี่ครั้งต่ออีเมลและ IP ที่เกินจะถูกเพิกเฉย
- คำเชิญ: admin สร้างผู้ใช้โดยเว้นรหัสผ่านว่างไว้ ผู้ใช้จะได้อีเมลให้ตั้งรหัสผ่านเอง (ลิงก์ใช้ได้ 7 วัน) จึงไม่มีใครอื่นรู้รหัส
- ส่งลิงก์ตั้งรหัสผ่านทางอีเมล ในหน้าของผู้ใช้ จะส่งคำเชิญ หรือส่งลิงก์ตั้งรหัสใหม่ถ้ามีรหัสผ่านแล้ว
การตั้งรหัสผ่านจะออกจากระบบทุกเครื่องของบัญชีนั้น และ login ให้ในเบราว์เซอร์นี้ ส่วนการตั้งรหัสใหม่ จะตามด้วยอีเมลแจ้งว่า "รหัสผ่านของคุณถูกเปลี่ยนแล้ว"
ลิงก์จะชี้ไปที่ serverURL (เช่น https://cms.example.com) ซึ่ง production ต้องตั้ง เพราะ Host ของ
request ปลอมได้ และลิงก์ที่สร้างจาก Host อาจส่ง token ไปให้คนอื่น ตอนพัฒนาจะใช้ที่อยู่ของ request เอง
ถ้าไม่มี email หรือเป็น production ที่ไม่มี serverURL หน้า admin จะไม่แสดงลิงก์เหล่านี้ admin ตั้งรหัสให้เอง
export default defineConfig({
serverURL: 'https://cms.example.com',
email: smtp(),
auth: {
resetPasswordExpiration: 60 * 60, // วินาที ค่าเริ่มต้น 1 ชั่วโมง
inviteExpiration: 7 * 24 * 60 * 60, // ค่าเริ่มต้น 7 วัน
// ข้อความของคุณเอง ค่าเริ่มต้นเป็นภาษาอังกฤษหรือไทย (ตามภาษาของหน้า admin)
emails: {
invite: ({ user, url }) => ({
subject: 'ยินดีต้อนรับสู่ทีมเนื้อหาของ Acme',
text: `สวัสดี ${user.name ?? user.email} ตั้งรหัสผ่านได้ที่: ${url}`,
}),
},
},
})ผ่าน REST: POST /api/cms/users/forgot-password พร้อม { email } แล้ว
POST /api/cms/users/reset-password พร้อม { token, password } (ซึ่ง login ให้ด้วย)
ส่วน GET /api/cms/users/reset-password?token=… ใช้ตรวจลิงก์ก่อน admin ส่งลิงก์ด้วย
POST /api/cms/users/:id/password-link ในโค้ดใช้ cms.auth.requestPasswordReset({ email }) และ
cms.auth.sendPasswordLink(userId)
Session
การ login จะสร้าง session:
POST /api/cms/users/loginพร้อม{ email, password }จะตั้ง session cookie แบบ HttpOnly (ใช้ได้ 7 วัน ปรับด้วยauth.tokenExpirationเป็นวินาที) และคืน CSRF token- browser ส่ง cookie ไปเอง การเขียนข้อมูลต้องส่ง CSRF token ใน header
x-csrf-tokenด้วย (ดู REST API) POST /api/cms/users/logoutปิด session
การ logout การเปลี่ยนรหัสผ่าน หรือการปิดใช้งานผู้ใช้ จะปิดทุก session ของคนนั้น
Token สำหรับแอปอื่น
สคริปต์และแอปบน origin อื่นส่ง session token แทน cookie ได้:
curl -s -X POST https://example.com/api/cms/users/login \
-H 'content-type: application/json' \
-d '{"email":"bot@example.com","password":"…"}' -c cookies.txt
# ใช้ค่า ecms-session จาก cookies.txt:
curl https://example.com/api/cms/posts?draft=true -H "Authorization: Bearer $TOKEN"request ที่ใช้ Authorization: Bearer ไม่ต้องใช้ CSRF token สำหรับสคริปต์และแอป ควรใช้
API key แทน เพราะไม่หมดอายุตาม session และจำกัดสิทธิ์ให้เท่าที่แอปต้องใช้ได้
จำกัดการ login
ถ้า login ล้มเหลวครบ auth.maxLoginAttempts ครั้ง (5) ภายใน auth.lockWindow วินาที (15 นาที) ต่อ email
(และ IP ถ้า adapter รู้) การ login จะตอบ 429 และปลดล็อกเองเมื่อครบเวลา
ผู้ใช้ในหน้าเว็บ
const user = await useEasyCMSUser(event) // Nuxt ใน server route
const user = await getEasyCMSUser(config) // Next.js ใน server component หรือ routeทั้งสองคืนผู้ใช้ของหน้า admin ที่ login อยู่ หรือ null ส่งให้ Local API เพื่อใช้สิทธิ์ของคนนั้น
เช่น ให้บรรณาธิการเห็นฉบับร่าง:
const { docs } = await cms.find('posts', { user, overrideAccess: false, draft: user !== null })การตั้งค่า
| ตัวเลือก | ค่าเริ่มต้น | |
|---|---|---|
auth.roles | ['admin', 'editor'] | บทบาทที่ผู้ใช้มีได้ ต้องมี admin |
auth.tokenExpiration | 7 วัน | อายุของ session เป็นวินาที |
auth.maxLoginAttempts | 5 | จำนวนครั้งที่ login ผิดได้ภายใน lockWindow |
auth.lockWindow | 15 นาที | เป็นวินาที |
auth.trustedOrigins | [] | origin อื่นที่ส่ง request ด้วย cookie ได้ |
auth.resetPasswordExpiration | 1 ชั่วโมง | ลิงก์ "ลืมรหัสผ่าน" ใช้ได้นานเท่าไร หน่วยวินาที |
auth.inviteExpiration | 7 วัน | ลิงก์คำเชิญใช้ได้นานเท่าไร หน่วยวินาที |
auth.emails | — | { resetPassword, invite, passwordChanged }: ข้อความอีเมลของคุณเอง |
ขั้นต่อไป
- การควบคุมสิทธิ์: แต่ละบทบาทอ่านและแก้อะไรได้
- ความปลอดภัย: ระบบป้องกันอะไรให้ และเช็กลิสต์ก่อนขึ้นระบบจริง