인프런 커뮤니티 질문&답변

이강민님의 프로필 이미지
이강민

작성한 질문수

Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)

Users Microservice - Routes 테스트

Spring Security 최신버전(Spring Boot 3.X.X 대)의 WebSecurity 설정 공유드립니다.

작성

·

12K

·

수정됨

18

최신버전으로 진행하다보니 막혔었는데요. 구글링, ChatGPT 등을 통해서 동작하는 코드 공유드립니다.

정확한 구현은 아닐 수 있겠지만, 강의를 진행하는 데는 문제 없는 것 같습니다. 참고만 부탁드려요~

 

package com.example.userservice.security;

import com.example.userservice.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.IpAddressMatcher;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurity {

    private final UserService userService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final ObjectPostProcessor<Object> objectPostProcessor;

    private static final String[] WHITE_LIST = {
            "/users/**",
            "/",
            "/**"
    };

    @Bean
    protected SecurityFilterChain config(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.headers().frameOptions().disable();
        http.authorizeHttpRequests(authorize -> {
                    try {
                        authorize
                                .requestMatchers(WHITE_LIST).permitAll()
                                .requestMatchers(PathRequest.toH2Console()).permitAll()
                                .requestMatchers(new IpAddressMatcher("127.0.0.1")).permitAll()
                                .and()
                                .addFilter(getAuthenticationFilter());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
        );
        return http.build();
    }

    public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder);
        return auth.build();
    }

    private AuthenticationFilter getAuthenticationFilter() throws Exception {
        AuthenticationFilter authenticationFilter = new AuthenticationFilter();
        AuthenticationManagerBuilder builder = new AuthenticationManagerBuilder(objectPostProcessor);
        authenticationFilter.setAuthenticationManager(authenticationManager(builder));
        return authenticationFilter;
    }

}

 

이렇게 하시고 중요한 것이, Login Form을 사용하지 않기 때문에 AuthenticationFilter 클래스의 Override 메소드 중 successfulAuthentication 메소드 내부에super.successfulAuthentication(request, response, chain, authResult);

코드가 작성되어 있다면, 아래처럼 제거 또는 주석 처리를 꼭 해야 합니다! (다른 질문 글에서 발견하였습니다, 공유 감사드립니다.)

하지 않은 경우 에러가 발생하며 login 요청이 제대로 동작하지 않습니다.

 

package com.example.userservice.security;

import com.example.userservice.vo.RequestLogin;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.IOException;
import java.util.ArrayList;

public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {
        try {
            RequestLogin creds = new ObjectMapper().readValue(request.getInputStream(), RequestLogin.class);
            return getAuthenticationManager().authenticate(
                    new UsernamePasswordAuthenticationToken(
                            creds.getEmail(),
                            creds.getPassword(),
                            new ArrayList<>()
                    )
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        //super.successfulAuthentication(request, response, chain, authResult);
    }
}

답변 5

2

도움 감사합니다 ^^

2

Dowon Lee님의 프로필 이미지
Dowon Lee
지식공유자

안녕하세요, 이도원입니다.

공유 감사드립니다.

강의를 시작한지 2년정도 되어 가고 있습니다. 강의 업데이트를 준비 중인데, 해당 부분도 참고하겠습니다.

감사합니다.

이강민님의 프로필 이미지
이강민
질문자

저야말로 좋은 지식 공유해주셔서 감사드립니다.

0

감사합니다!

0

하루종일 순환참조부터 오만 시달림 당했는데 감사합니다.. 다음부턴 맘편히 버전 맞춰야겠네요 ㅠ. 감사합니다

0

감사합니다!!

이강민님의 프로필 이미지
이강민

작성한 질문수

질문하기