안녕하세요. 현재 개발중인 spring security 설정 문의 드립니다.

23.08.17 11:44 작성 23.08.17 11:51 수정 조회수 752

0

안녕하세요 현재 java17 + spring boot 3.0 + gradle 7.7.6 + mybatis로 개발셋팅중인데..

spring security 설정에서 삽질중인데...

http://localhost:8088/twinadm/login => 로그인,로그아웃 , 권한체크 잘됨.

http://192.168.1.46:8088/twinadm/login => 로그인,로그아웃 안됨. 로그인 하면

org.springframework.security.web.csrf.MissingCsrfTokenException: Could not verify the provided CSRF token because no token was found to compare.

이런에러가 떨어짐.

 

위와 같이 로컬은 잘되는데 IP 접근시에는 저런에러가 떨어집니다 ㅠㅠ..

 

소스 설정은 아래와 같습니다.

 

public class AdminSecurityConfig {

    private final AdminAccessDeniedHandler adminAccessDeniedHandler;

    @Autowired
    public AdminSecurityConfig(AdminAccessDeniedHandler adminAccessDeniedHandler) {
        this.adminAccessDeniedHandler = adminAccessDeniedHandler;
    }

    @Bean
    public UserDetailsService adminDetailsService(){
        return new AdminDetailService();
    }

    @Bean
    public PasswordEncoder adminPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider adminAuthenticationProvider(){
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(adminDetailsService());
        provider.setPasswordEncoder(adminPasswordEncoder());
        return provider;
    }

    @Bean
    public SecurityFilterChain adminFilterChain(HttpSecurity http) throws Exception {	
        String[] AnyAuthority = {"ROLE_ADMIN","ROLE_ADMININ"};
        http.headers().frameOptions().sameOrigin(); // security 설정 추가 [url x-frame-options : cro]
        http.headers(headers -> headers.cacheControl(cache -> cache.disable()));

        http.csrf()
        .ignoringAntMatchers()
        .ignoringRequestMatchers();
        
        http
        // .antMatcher("/admin/**")
        .authenticationProvider(adminAuthenticationProvider())
        // .authorizeHttpRequests().antMatchers("/admin/site/**").hasAnyAuthority("ROLE_ADMIN") // url 마다 권한 처리
        .antMatcher("/admin/**")
                .authorizeRequests(authorize -> authorize
                        .anyRequest()
                        // .hasAuthority("ROLE_ADMIN")) // 단일 권한
                        .hasAnyAuthority(AnyAuthority)) // 여러권한
			  .formLogin(login -> login
				.loginPage("/admin/login")    // GET 요청 (login form을 보여줌)
				.loginProcessingUrl("/admin/adminLoginProc")    // POST 요청 (login 창에 입력한 데이터를 처리)
        .failureUrl("/admin/login?error=true")
				.usernameParameter("email")	// login에 필요한 id 값을 email로 설정 (default는 username)
				.passwordParameter("password")	// login에 필요한 password 값을 password(default)로 설정
				.defaultSuccessUrl("/admin").permitAll());
        http.exceptionHandling().accessDeniedHandler(adminAccessDeniedHandler);
        http
			.logout(logout -> logout
					.logoutUrl("/admin/adminLogout")
                    .addLogoutHandler((request, response, authentication) -> { 
                        HttpSession session = request.getSession();
                        session.removeAttribute("SPRING_SECURITY_CONTEXT");
                    })
                    .invalidateHttpSession(false)
					.logoutSuccessUrl("/admin/login")); // logout에 성공하면 /로 redirect	
        // 인증 거부 관련 처리
        return http.build();
    }

    // @Bean
    // public AdminSecurityCustomizer adminSecurityCustomizer() {
    //     return (web) -> web.ignoring().antMatchers("/h2-console/**");
    // }
 }

 

여기서 제가 잘못 설정한게 있을까요?

 

고수님들께 질문드립니다.. 조언 및 소스 수정의 키워드좀 알려주세요 ㅠㅠ

 

답변 1

답변을 작성해보세요.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2023.08.18

안녕하세요, 인프런 AI 인턴이에요. Spring Security 설정에 관한 질문이시군요.

로그인, 로그아웃과 권한 체크는 로컬 접근 시 정상적으로 작동하지만, IP로 접근할 때는 CSRF 토큰 에러가 발생한다고 하셨네요. CSRF 토큰 에러는 보안을 위해 Spring Security에서 추가하는 토큰으로, 요청을 보낼 때마다 해당 토큰을 함께 전송하여 요청의 신뢰성을 보장하는 역할을 한답니다.

해당 에러가 발생하는 이유는 CSRF 토큰이 IP 주소로 요청을 보낼 때 전달되지 않기 때문입니다. 해당 문제를 해결하기 위해서는 CSRF 토큰을 IP 주소로 접근하는 경우에도 전송되도록 설정해야 합니다.

해당 설정은 SecurityConfig 클래스의 configure 메서드에서 해줄 수 있어요. 아래의 예시 코드처럼 csrf().csrfTokenRepository() 메서드를 사용하여 토큰을 저장하고 전송해주면 됩니다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .and()
            // 다른 설정들
    }
}

위의 코드에서는 CSRF 토큰을 쿠키에 저장하고, HTTP 통신에서도 해당 토큰을 사용할 수 있도록 설정한 예시입니다. 이렇게 설정을 추가하면 IP 주소로 접근하는 경우에도 CSRF 토큰이 정상적으로 전송되어 에러가 발생하지 않을 거에요.

추가로, 예시 코드는 CSRF 토큰을 쿠키에 저장하는 방식이기 때문에 쿠키를 사용할 수 있는지 확인해야 합니다. 쿠키를 사용할 수 없는 경우에는 다른 방식으로 CSRF 토큰을 저장하도록 설정해야 해요.

이렇게 설정을 추가한 뒤에는 다시 해당 페이지로 접근하여 로그인, 로그아웃을 시도해보시고, 에러가 해결되었는지 확인해보세요. 문제가 해결되지 않는다면 댓글로 알려주세요. 이전에 제공된 소스 코드에 대한 정보가 더 필요하다면 추가로 알려주세요. 많은 도움이 되길 바랄게요!