Cookie SameSite 설정하기

Wonjun Seo·2023년 6월 18일
1

2020년 2월 4일 릴리즈된 구글 크롬(Google Chrome) 80버전부터 새로운 쿠키 정책이 적용 되어 Cookie의 SameSite 속성의 기본값이 "None"에서 "Lax"로 변경되었습니다.

SameSite 를 None 으로 설정할 경우 모든 도메인에서 쿠키를 전송하고 사용할 수 있지만 사용자가 사이트 간 요청 위조(CSRF - Cross-site request forgery) 및 의도하지 않은 정보 유출에 취약해질 가능성이 있습니다. 이러한 취약점을 방지하기 위해 지금까지는 별도의 SameSite 속성 명시 없이 쿠키를 생성했을 때 "SameSite=None" 으로 설정한 것과 동일하게 동작 했지만 Chrome80 버전 이후에는 SameSite 속성 설정이 없는 쿠키는 "SameSite=Lax" 로 명시한 것과 동일하게 동작한다는 것입니다.

Specify SameSite=None and Secure if the cookie should be sent in cross-site requests. This enables third-party use.


SameSite

SameSite 속성은 서로 다른 도메인간의 쿠키 전송에 대한 보안을 설정한다.

A cookie with "SameSite=Strict" will only be sent with a same-site request.
A cookie with "SameSite=Lax" will be sent with a same-site request, or a cross-site top-level navigation with a "safe" HTTP method.
A cookie with "SameSite=None" will be sent with both same-site and cross-site requests.
  • "None"으로 설정할 경우, 동일 사이트와 크로스 사이트에 모두 쿠키 전송이 가능합니다.
  • "Strict"로 설정할 경우, 서로 다른 도메인에서는 아예 전송이 불가능해 집니다. 따라서, CSRF를 완전히 방지할 수는 있지만, 사용자 편의성을 많이 해치게 됩니다.
  • "Lax"로 설정할 경우, Strict 설정에 일부 예외(HTTP GET method/a href/link href)를 두어 적용되는 설정입니다.

SameSite 설정하기

1. JavaScript

document.cookie="safeCookie1=foo;SameSite=Lax";
document.cookie="safeCookie2=foo";
document.cookie="crossCookie=bar;SameSite=None;Secure";

JavaScript 사용시, 스크립트 상단에 해당 코드를 선언하면 간단하게 해결할 수 있다.


2. Java Application

response.setHeader("Set-Cookie", "Test1=TestCookieValue1;   Secure; SameSite=None");
response.addHeader("Set-Cookie", "Test2=TestCookieValue2;  Secure;  SameSite=None");
response.addHeader("Set-Cookie", "Test3=TestCookieValue3;   Secure; SameSite=None");

3. Filter/Interceptor

위의 소스처럼 하나하나 일일이 처리하기 힘든 경우 Filter(필터)나 Interceptor(인터셉터) 등을 사용하여 response를 가로채 Secure; SameSite=None 속성을 추가하여 일괄 변경도 가능하다.

import java.io.IOException;
import java.util.Collection;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpHeaders;

public class CookieAttributeFilter implements Filter{
	
	@Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
		HttpServletResponse httpServletResponse = (HttpServletResponse) response;
		chain.doFilter(request, response);
		addSameSite(httpServletResponse , "None"); 	
	}
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
	}
	
	@Override
	public void destroy() {
		// TODO Auto-generated method stub	
	}	
	
    private void addSameSite(HttpServletResponse response, String sameSite) {
	    Collection<String> headers = response.getHeaders(HttpHeaders.SET_COOKIE);
	    boolean firstHeader = true;
	    for (String header : headers) { // there can be multiple Set-Cookie attributes
	        if (firstHeader) {
	            response.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; Secure; %s", header, "SameSite=" + sameSite));
	            firstHeader = false;
	            continue;
	        }
	        response.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; Secure; %s", header, "SameSite=" + sameSite));
	    }  
    }
	
}

References

https://re-man.tistory.com/210
https://ifuwanna.tistory.com/223

0개의 댓글