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

이강민님의 프로필 이미지

작성한 질문수

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

Users Microservice - Routes 테스트

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

23.03.13 12:03 작성

·

11K

·

수정됨

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

JungHyo Go님의 프로필 이미지

2023. 03. 17. 13:11

도움 감사합니다 ^^

2

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

2023. 03. 14. 12:44

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

공유 감사드립니다.

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

감사합니다.

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

2023. 03. 14. 14:07

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

0

KR KHS님의 프로필 이미지

2023. 07. 24. 15:38

감사합니다!

0

sec님의 프로필 이미지

2023. 05. 20. 17:45

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

0

system.out.println님의 프로필 이미지

2023. 05. 07. 18:54

감사합니다!!