Spring Security: Entity

การออกแบบระบบสิทธิ์ (Authorization) ที่แข็งแกร่งเป็นหัวใจสำคัญของแอปพลิเคชันระดับองค์กร ในบริบทของ Spring Boot และ Spring Security การจัดการสิทธิ์ (Role-Based Access Control: RBAC) จำเป็นต้องมีการสร้าง Entity Model ที่มีความสัมพันธ์ซับซ้อน โดยเฉพาะการใช้รูปแบบ Many-to-Many เพื่อเชื่อมโยง Role และ Permission เข้าด้วยกัน

บทความนี้จะเจาะลึกการสร้างโครงสร้าง Entity สำหรับ Role และ Permission โดยเน้นการใช้ JPA (Java Persistence API) ร่วมกับฐานข้อมูล PostgreSQL เพื่อให้ได้ระบบสิทธิ์ที่ยืดหยุ่นและขยายได้ในอนาคต

🏗️ หลักการออกแบบ Entity สำหรับ RBAC

โครงสร้างความสัมพันธ์ที่เหมาะสมที่สุดคือ:

  1. User มีความสัมพันธ์กับ Role (Many-to-Many)
  2. Role มีความสัมพันธ์กับ Permission (Many-to-Many)

ความสัมพันธ์แบบ Many-to-Many นี้จะถูกจัดการโดย JPA โดยการสร้างตาราง Join Table อัตโนมัติ (เช่น role_has_permissions) ซึ่งเป็นแนวทางปฏิบัติที่ดีที่สุดในการทำ Flyway Migration

🛡️ 1. Permission Entity: การกำหนดสิทธิ์ย่อย

Permission Entity ทำหน้าที่เก็บสิทธิ์ย่อย ๆ ที่เป็น atomic unit เช่น post-create, user-delete หรือ dashboard-view

ไฟล์: src/main/java/com/example/demo/entity/Permission.java

Java

package com.example.demo.entity; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; import java.util.Set; @Entity @Table (name = "permissions") @Getter @Setter public class Permission { @Id @GeneratedValue (strategy = GenerationType.IDENTITY) private Long id; @Column (unique = true, nullable = false) private String name; // ตัวอย่าง: "post-create" @Column (name = "guard_name") private String guardName = "web"; @ManyToMany (mappedBy = "permissions") private Set<Role> roles; }

👑 2. Role Entity: การรวมกลุ่มสิทธิ์

Role Entity ทำหน้าที่รวมกลุ่มของ Permission หลาย ๆ ตัวเข้าด้วยกัน และมีความสัมพันธ์กับ User ผ่านตาราง Join Table

ไฟล์: src/main/java/com/example/demo/entity/Role.java

Java

package com.example.demo.entity; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; import java.util.Set; @Entity @Table (name = "roles") @Getter @Setter public class Role { @Id @GeneratedValue (strategy = GenerationType.IDENTITY) private Long id; @Column (unique = true, nullable = false) private String name; // ตัวอย่าง: "ADMIN", "EDITOR" @ManyToMany (cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinTable (name = "role_has_permissions", joinColumn = @JoinColumn(name = "role_id")) private Set<Permission> permissions; }

🔗 3. การจัดการความสัมพันธ์ (Mapping)

การใช้ `@JoinTable` ใน Role Entity จะสร้างตารางเชื่อมโยง role_has_permissions ในฐานข้อมูล PostgreSQL โดยอัตโนมัติ ซึ่งเป็นกลไกที่ทำให้ระบบสามารถจัดการความสัมพันธ์แบบ Many-to-Many ได้อย่างถูกต้องและมีประสิทธิภาพ

SQL

-- ตัวอย่าง SQL สำหรับการสร้างตาราง Role (PostgreSQL) -- CREATE TABLE roles ( id BIGSERIAL PRIMARY KEY, name VARCHAR(255) UNIQUE NOT NULL ); -- ตัวอย่าง SQL สำหรับการสร้างตาราง Join -- CREATE TABLE role_has_permissions ( role_id BIGINT REFERENCES roles(id), permission_id BIGINT REFERENCES permissions(id), PRIMARY KEY (role_id, permission_id) );

✅ บทสรุปและแนวทางปฏิบัติ

การกำหนด Entity Model ด้วย JPA ดังกล่าวข้างต้น ทำให้เราได้โครงสร้าง RBAC ที่สมบูรณ์แบบสำหรับการใช้งานกับ Spring Security และ PostgreSQL การใช้ Lombok ช่วยลด Boilerplate Code ได้อย่างมาก ในการนำไปใช้งานจริง ควรมีการใช้ Flyway หรือ Liquibase เพื่อจัดการ Schema Migration ของตารางเหล่านี้ เพื่อให้มั่นใจว่าโครงสร้างฐานข้อมูลมีความสอดคล้องกับโค้ด Java เสมอ