หมวดหมู่: Spring Boot

Spring Security: SecurityConfigSpring Security: SecurityConfig

เพื่อให้ระบบ Spring Security สามารถดึงข้อมูลจากตาราง users, roles, และ permissions ที่เราออกแบบไว้ (สไตล์ Laravel) มาใช้ในการ Login ได้จริง คุณต้องสร้างไฟล์ 2 ส่วนหลัก คือ UserDetails (เพื่อบอก Spring ว่าจะเช็คฟิลด์ไหน) และ SecurityConfig (เพื่อตั้งค่าการเข้าถึง) ครับ


สร้าง CustomUserDetails Service

ไฟล์นี้ทำหน้าที่เหมือน “สะพาน” เชื่อมระหว่างฐานข้อมูล SQL Server กับ Spring Security ครับ
src/main/java/com/example/demo/config/UserDetailsServiceImpl.java

package com.example.demo.config;

import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.*;
import org.springframework.stereotype.Service;
import java.util.stream.Collectors;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

 @Autowired
 private UserRepository userRepository;

 @Override
 public UserDetails loadUserByUsername (String username) throws UsernameNotFoundException {
 // หา User จาก DB (ถ้าไม่เจอให้โยน Error เหมือน Laravel Auth) User user = userRepository.findByUsername (username) .orElseThrow ( () -> new UsernameNotFoundException ("User not found: " + username)) ;

 // แปลง Roles/Permissions ให้เป็น SimpleGrantedAuthority ของ Spring
 return new org.springframework.security.core.userdetails.User (user.getUsername () ,
 user.getPassword () ,
 user.getRoles () .stream () .map (role -> new SimpleGrantedAuthority (role.getName ())) .collect (Collectors.toList ())) ;
 }
}

สร้าง SecurityConfig (Spring Boot 3.x Style)

ไฟล์นี้คือ “ประตูด่านหน้า” ที่คุมสิทธิ์การเข้าถึง API ทั้งหมดครับ
src/main/java/com/example/demo/config/SecurityConfig.java

package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

 @Bean
 public SecurityFilterChain securityFilterChain (HttpSecurity http) throws Exception {
 http
 .csrf (csrf -> csrf.disable ()) // ปิดไว้สำหรับการทำ Stateless API (เหมือน Laravel API) .authorizeHttpRequests (auth -> auth
 .requestMatchers ("/api/auth/**") .permitAll () // เปิดให้ Register/Login ได้
 .requestMatchers ("/api/admin/**") .hasRole ("ADMIN") // เฉพาะ Role ADMIN เท่านั้น
 .anyRequest () .authenticated () // ที่เหลือต้อง Login ทั้งหมด) .httpBasic (Customizer.withDefaults ()) ; // ใช้ Basic Auth ในการทดสอบเบื้องต้น

 return http.build () ;
 }

 // ตัวเข้ารหัส Password (ต้องใช้ตัวนี้ตอนสมัครสมาชิกด้วย เพื่อให้ Match กัน) @Bean
 public PasswordEncoder passwordEncoder () {
 return new BCryptPasswordEncoder () ;
 }

 @Bean
 public AuthenticationManager authenticationManager (AuthenticationConfiguration config) throws Exception {
 return config.getAuthenticationManager () ;
 }
}

สิ่งที่ต้องระวัง (Common Pitfalls)

  • Prefix ของ Role: ใน Spring Security ถ้าคุณใช้ .hasRole ("ADMIN") มันจะมองหาคำว่า ROLE_ADMIN ในฐานข้อมูลโดยอัตโนมัติ ดังนั้นในตาราง roles ของคุณ ควรตั้งชื่อเป็น ROLE_ADMIN ครับ
  • Password Encoding: เวลาคุณเพิ่ม User ลงในฐานข้อมูล (Seed Data) ห้าม ใส่ Password เป็นข้อความธรรมดา (Plain Text) ต้องใช้ BCrypt เท่านั้น มิฉะนั้นจะ Login ไม่ผ่าน