package com.openisle.config; import com.openisle.service.JwtService; import com.openisle.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.filter.OncePerRequestFilter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @Configuration @RequiredArgsConstructor public class SecurityConfig { private final JwtService jwtService; private final UserRepository userRepository; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public UserDetailsService userDetailsService() { return username -> userRepository.findByUsername(username) .map(user -> org.springframework.security.core.userdetails.User .withUsername(user.getUsername()) .password(user.getPassword()) .authorities("USER") .build()) .orElseThrow(() -> new UsernameNotFoundException("User not found")); } @Bean public AuthenticationManager authenticationManager(HttpSecurity http, PasswordEncoder passwordEncoder, UserDetailsService userDetailsService) throws Exception { return http.getSharedObject(AuthenticationManagerBuilder.class) .userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder) .and() .build(); } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf(csrf -> csrf.disable()) .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers(HttpMethod.POST, "/api/auth/**").permitAll() .anyRequest().authenticated() ) .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public OncePerRequestFilter jwtAuthenticationFilter() { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { String token = authHeader.substring(7); try { String username = jwtService.validateAndGetSubject(token); UserDetails userDetails = userDetailsService().loadUserByUsername(username); UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); org.springframework.security.core.context.SecurityContextHolder.getContext().setAuthentication(authToken); } catch (Exception ignored) { } } filterChain.doFilter(request, response); } }; } }