Skip to content

27 - Role USER และ ADMIN

บทนี้จะวางแนวคิดเรื่อง role ให้ชัด ก่อนสร้าง admin endpoint จริงในบทถัดไป

หลังจบบทนี้ผู้อ่านควรเข้าใจ:

  • role ใช้ควบคุมสิทธิ์อย่างไร
  • ทำไม user ใหม่ต้องได้ role USER เสมอ
  • ทำไม client ห้ามส่ง role ตอน register
  • JWT ต้องมี role claim เพื่อให้ Spring Security ตรวจสิทธิ์ได้
  • hasRole("ADMIN") ต่างจาก authority ROLE_ADMIN อย่างไร

ระบบนี้เริ่มจาก 2 role:

package com.example.backendapi.model;
public enum Role {
USER,
ADMIN
}

ความหมาย:

Roleใช้กับใคร
USERผู้ใช้ทั่วไป
ADMINผู้ดูแลระบบที่จัดการผู้ใช้ได้

ตอนนี้ยังไม่เพิ่ม role อื่น เช่น MANAGER, SUPER_ADMIN เพราะจะทำให้หนังสือช่วงนี้ซับซ้อนเกินไป

ใน User entity ควรเก็บ role เป็น enum string:

@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 20)
private Role role = Role.USER;

เหตุผลที่ใช้ EnumType.STRING:

  • database อ่านง่าย เช่น USER, ADMIN
  • ไม่เสี่ยงพังเมื่อเปลี่ยนลำดับ enum
  • debug ง่ายกว่าเลข 0, 1

User ใหม่ต้องเป็น USER

Section titled “User ใหม่ต้องเป็น USER”

ตอน register ห้ามรับ role จาก request body

request ที่ถูกต้องควรมีแค่นี้:

{
"username": "john",
"email": "john@example.com",
"password": "password123"
}

ไม่ควรมี:

{
"username": "john",
"email": "john@example.com",
"password": "password123",
"role": "ADMIN"
}

ถ้า backend ยอมรับ role จาก client ผู้ใช้สามารถแก้ request แล้วสมัครเป็น admin เองได้

ในบท JWT เราใส่ claim:

.claim("roles", List.of(user.getRole().name()))

payload ที่ได้จะมี:

{
"sub": "john@example.com",
"roles": ["USER"]
}

Spring Security จะใช้ claim นี้ตัดสินว่า request มีสิทธิ์เข้า admin endpoint หรือไม่

ใน Spring Security:

.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")

แปลว่า Spring จะมองหา authority:

ROLE_ADMIN

ดังนั้นถ้า JWT เก็บ role เป็น ADMIN เราต้อง map ให้มี prefix ROLE_

grantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");

สร้าง admin คนแรกอย่างไร

Section titled “สร้าง admin คนแรกอย่างไร”

ในช่วงเรียน วิธีง่ายสุดคือสร้าง user ปกติด้วย register แล้วแก้ role ใน database เป็น ADMIN

ตัวอย่าง SQL:

UPDATE users
SET role = 'ADMIN'
WHERE email = 'admin@example.com';

ในงานจริงควรมี seed/migration หรือระบบ invite admin ที่ควบคุมได้ ไม่ควรแก้ database มือใน production

  • อย่าให้ register รับ role
  • อย่าส่ง role จาก frontend แล้วเชื่อทันที
  • role ต้องถูกตรวจที่ backend เสมอ
  • menu frontend ซ่อน admin page ได้ แต่ไม่ใช่ security หลัก
  • backend ต้องเป็นคนปฏิเสธ request ที่สิทธิ์ไม่พอ

แบบฝึกหัดท้ายบท

Section titled “แบบฝึกหัดท้ายบท”
  1. ตรวจว่า Role enum มี USER, ADMIN
  2. ตรวจว่า User entity ตั้ง default role เป็น USER
  3. login แล้ว decode JWT เพื่อดู claim roles
  4. แก้ user คนหนึ่งใน database ให้เป็น ADMIN
  5. login ใหม่แล้วดูว่า JWT เปลี่ยน role เป็น ADMIN