ป้ายกำกับ: SecurityConfig

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 ไม่ผ่าน