React-Django의 로그인 UI-API 간에 403 45 CSRF가 발생했습니다.
회원가입 구현 중에는 각 API마다 decorator를 통해 CRSF 검증을 통제하였기 때문에 한동안 만날 일이 없었던 오류였으나
@method_decorator(csrf_exempt, name="dispatch")
로그인 구현 시에는 미처 생각을 못하고 API에 decorator를 적용하지 않았습니다.
decorator를 지정해서 계속 개발을 진행할까하다가 요즘 Session, JWT등등 내용을 정리하고 있던 참이라 CSRF에 대한 내용도 정리해보려합니다!
[05/Jul/2024 05:45:31] "POST /api/login/ HTTP/1.1" 403 45
API를 설정하는 과정에서 403 Forbidden 에러가 발생하는 것은 CSRF(Cross-Site Request Forgery) 토큰 문제와 관련이 있습니다.
현재 로그인은 dj-rest-auth의 LoginAPIView로 구현하고있습니다. dj-rest-auth는 기본적으로 요청에 대한 CSRF 인증을 사용합니다.
해결은 생각보다 간단합니다!
React의 axios의 요청에 CSRF 토큰을 포함시키면 문제는 해결됩니다.
아직까지는 React 사용이 미숙하기 때문에 GPT에게 CSRF 토큰을 포함시키는 코드 생성을 부탁했습니다.
import { Cookies } from 'react-cookie';
// CSRF 토큰을 쿠키에서 가져오는 함수
const getCSRFToken = () => {
const cookies = new Cookies();
return cookies.get('csrftoken');
};
// CSRF 토큰 가져오기
const csrftoken = getCSRFToken();
export const login = async (id, password) => {
try {
const response = await axios.post(
'http://localhost:8000/api/login/',
{email : id, password : password},
{
withCredentials: true,
headers: {
'X-CSRFToken': csrftoken,
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
handleError(error);
}
};
headers에 토큰에 대한 값을 지정해주면 끝!
이번에는 요청에 CRSF 토큰을 포함하는 것으로 문제가 해결되었지만 403 Forbidden 에러가 발생 경우에는 확인해보면 좋은 설정들이 있습니다.
CSRF_COOKIE_NAME = 'csrftoken'
CSRF_COOKIE_HTTPONLY = False
CSRF_TRUSTED_ORIGINS = [
'https://localhost:3000'
]
이 설정은 CSRF 보호를 우회할 수 있는 도메인을 지정합니다. 개발환경에서 필요하겠죠!
CORS(Cross-Origin Resource Sharing) 정책으로 CSRF 토큰 전송 누락될 수 있습니다!
지난 포스팅의 CORS 설정을 참고하면 좋을 것 같습니다!
403 Forbidden 에러가 발생하는 것은 CSRF(Cross-Site Request Forgery) 토큰 문제와 관련이 있다.
해결을 위해 시도할 수 있는 것들