프론트와 로그인 기능 관련해서 API 연동 중에 도메인이 다름에 따라서 쿠키가 전달이 잘 안 됐다.
Chrome
기본적으로 크롬에서는 쿠키의 samesite 설정을 "Lax"로 해놓기 때문에 현 상황에서는 samesite를 None으로 지정해줄 필요가 있다!
response.set_cookie(
"access", response.headers.get("access", None), httponly=True, samesite=None, secure=True
)
빠르게 구글링을 통해 set_cookie 부분을 작성했다.
그런데 프론트 측에서 확인해본 결과 cookie의 samesite 속성이 제대로 지정되지 않았다. 크롬에서 기본으로 세팅되는 Lax도 안 되어 있었다는 뜻!
이유를 알아보기 위해서 라이브러리를 파고 들어가봅시다.
def set_cookie(
self,
key,
value="",
max_age=None,
expires=None,
path="/",
domain=None,
secure=False,
httponly=False,
samesite=None,
):
"""
Set a cookie.
``expires`` can be:
- a string in the correct format,
- a naive ``datetime.datetime`` object in UTC,
- an aware ``datetime.datetime`` object in any time zone.
If it is a ``datetime.datetime`` object then calculate ``max_age``.
``max_age`` can be:
- int/float specifying seconds,
- ``datetime.timedelta`` object.
"""
self.cookies[key] = value
if expires is not None:
if isinstance(expires, datetime.datetime):
if timezone.is_naive(expires):
expires = timezone.make_aware(expires, datetime.timezone.utc)
delta = expires - datetime.datetime.now(tz=datetime.timezone.utc)
# Add one second so the date matches exactly (a fraction of
# time gets lost between converting to a timedelta and
# then the date string).
delta += datetime.timedelta(seconds=1)
# Just set max_age - the max_age logic will set expires.
expires = None
if max_age is not None:
raise ValueError("'expires' and 'max_age' can't be used together.")
max_age = max(0, delta.days * 86400 + delta.seconds)
else:
self.cookies[key]["expires"] = expires
else:
self.cookies[key]["expires"] = ""
if max_age is not None:
if isinstance(max_age, datetime.timedelta):
max_age = max_age.total_seconds()
self.cookies[key]["max-age"] = int(max_age)
# IE requires expires, so set it if hasn't been already.
if not expires:
self.cookies[key]["expires"] = http_date(time.time() + max_age)
if path is not None:
self.cookies[key]["path"] = path
if domain is not None:
self.cookies[key]["domain"] = domain
if secure:
self.cookies[key]["secure"] = True
if httponly:
self.cookies[key]["httponly"] = True
if samesite:
if samesite.lower() not in ("lax", "none", "strict"):
raise ValueError('samesite must be "lax", "none", or "strict".')
self.cookies[key]["samesite"] = samesite
위 코드는 장고의 HttpResponseBase 클래스의 set_cookie 함수 전문입니다.
인자를 받는 부분에서부터 samesite=None이 default 값이네요. 벌써 쎄하죠?
아래쪽으로 내려와서 samesite에 관련된 부분을 다시 한 번 봅시다.
if samesite:
if samesite.lower() not in ("lax", "none", "strict"):
raise ValueError('samesite must be "lax", "none", or "strict".')
self.cookies[key]["samesite"] = samesite
아하, samesite 속성을 지정해줄 때 None 값으로 넣어서 if문 자체가 통과가 안 됐었네요..
내용을 참고해보니 none을 문자열로 넣어야 했습니다!
여기서도 set_cookie에서 samesite를 어떻게 지정해야하는지 나오네요.
역시 공식 독스..
response.set_cookie(
"access", response.headers.get("access", None), httponly=True, samesite="none", secure=True
)
간단한 수정으로 문제 해결 완료!
역시 가장 확실한 방법은 공식 docs를 확인하거나 직접 라이브러리를 까보는 것..
알량한 구글링이 아니라 내가 직접 체득하는게 최고다!