본문 바로가기

[React, SpringBoot] React에서 api 요청 시 HttpSession 유지 안되는 문제

@suhyeon chae2023. 9. 8. 12:59
문제 발생

기능

- 사용자가 본인인증을 할때 인증 코드 메일 발송을 한다. 

- 메일을 보내기 전에 인증 코드를 랜덤으로 생성하고 생성된 인증 코드를 HttpSession에 저장한다.

- 사용자는 메일에 적혀진 인증코드를 작성하고 인증하기 버튼을 클릭한다.

- 사용자가 입력한 인증 코드와 session에 저장된 인증코드가 같은지 확인한다.

 

문제

- 코드를 저장한 session과 사용자가 인증코드를 확인받는 로직에서 session에서 인증코드를 꺼내는데, 이 두개의 session이 불일치한다.

String storedCode = session.getAttribute("code").toString();  --> 여기서 session에 code 가 없다고 NullPointerException 이 발생한다.

 

문제 확인

- 인증 코드를 저장하는 로직과 인증코드를 확인하는 로직에 로그를 찍어본 결과 session 아이디가 달랐다.

[인증 코드 저장 api session 정보] mail session : org.apache.catalina.session.StandardSessionFacade@4c29be9f [인증 번호 확인 api session 정보] valid session : org.apache.catalina.session.StandardSessionFacade@3f1f206c

 

원인 분석

첫번째 (실패)

- react에서 인증코드를 보내는 화면과 인증코드를 확인받는 화면이 달라서 생기는 문제점인줄 알았다. (무식하게 생각) 

- 따라서 react에서 화면 이동 없이 해당 로직을 처리하는 것으로 수정했다. 하지만 되지 않았다,,,

 

두번째(성공)

- 검색한 결과 브라우저는 기본적으로 서로 다른 도메인의 리소스를 요청할 때 보안상의 이유로 요청에 대해 인증 정보를 포함시키지 않는다고 한다. (same-origin-policy)

 

 

해결 방법

REACT

- session을 유지해야하는 api 통신에 withCredentials: true 옵션 추가

/**
 * @description 인증 코드 이메일 발송
 */
const sendCodeEmail = async (params: { email: string }) => {
    const url = `/user/send`;
    const { data } = await request.post(url, params, {
        withCredentials: true,
    });
    return data;
};

/**
 * @description 인증 코드 확인
 */
const validInputCode = async (code: string) => {
    const url = `/user/code/valid?code=${code}`;
    const { data } = await request.get(url, {
        withCredentials: true,
    });
    return data;
};

 

SPRING BOOT

- cors origin 설정에서 allowCredentials(true)로 설정한다.

@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {
    private final long MAX_AGE_SECS = 3600;
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 모든 경로에 대해
        registry.addMapping("/**")
                // Origin이 localhost:3000에 대해
                .allowedOrigins("http://localhost:3000")
                // GET, POST, PUT, PATCH, DELETE, OPTIONS 메서드를 허용한다.
                .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true) // 이부분 설정
                .maxAge(MAX_AGE_SECS);
    }
  }

 

suhyeon chae
@suhyeon chae :: 번아웃을 이겨내는중

신입 개발자 입니다 😃 github 주소 : https://github.com/chaesuhyeon

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차