Spring

SameSite 및 Secure 속성을 JSESSIONID 쿠키로 설정하는 방법 물어보다

기록만이살길 2022. 11. 5. 15:29
반응형

SameSite 및 Secure 속성을 JSESSIONID 쿠키로 설정하는 방법 물어보다

1. 질문(문제점):

Spring Boot 웹 애플리케이션(Spring boot 버전 2.0.3.RELEASE)이 있고 Apache Tomcat 8.5.5 서버에서 실행 중입니다.

최근 구글 크롬에서 시행한 Security 정책(80.0 이후 출시 SameSite)에 따라 CSRF 대신 Cross-site 쿠키에 보다 안전한 방식으로 접근할 수 있도록 새로운 속성을 적용해 줄 것을 요청하고 있다. 관련 작업을 수행한 적이 없고 Chrome이 SameSite=Lax자사 쿠키에 대한 기본값을 설정했기 때문에 타사 서비스 통합 중 하나가 타사 서비스 통합에 실패합니다 SameSite=Lax. POST요청 에서 응답이 옵니다 (절차가 완료되면 요청 과 함께 타사 서비스 리디렉션POST ). 거기에 Tomcat이 세션을 찾을 수 없으므로 새 항목을 추가합니다.JSESSIONID(새 세션과 함께 이전 세션이 종료됨) URL 끝에 있습니다. JSESSIONID따라서 Spring은 새 추가 에 의해 도입된 세미콜론이 포함된 URL을 거부합니다 .

그래서 JSESSIONID쿠키 속성( SameSite=None; Secure)을 변경하고 WebFilters를 비롯한 여러 방법으로 시도해야 합니다. Stackoverflow에서 동일한 질문과 답변을 보았고 대부분 시도했지만 아무데도 없었습니다.

누군가 Spring Boot에서 해당 헤더를 변경하는 솔루션을 제안할 수 있습니까?

2. 해결방안:

나는 전에 같은 상황에 있었다. 클래스 SameSite같은 것이 없으므로 추가할 수 없습니다.javax.servlet.http.Cookie

1부: 그래서 내가 한 것은 필요한 제3자 요청만 가로채는 필터를 작성하는 것입니다.

public class CustomFilter implements Filter {

    private static final String THIRD_PARTY_URI = "/third/party/uri";


    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        if(THIRD_PARTY_URI.equals(request.getRequestURI())) {
            chain.doFilter(request, new CustomHttpServletResponseWrapper(response));
        } else {
            chain.doFilter(request, response);
        }
    }
enter code here
    // ... init destroy methods here
    
}

파트 2: 쿠키는 Set-Cookie응답 헤더로 전송됩니다. 따라서 이것은 메서드를 CustomHttpServletResponseWrapper재정의하고 addCookie필요한 쿠키인지 확인합니다( JSESSIONID). 쿠키에 추가하는 대신 속성 이 있는 응답 헤더 Set-Cookie에 직접 추가합니다.SameSite=None

public class CustomHttpServletResponseWrapper extends HttpServletResponseWrapper {

    public CustomHttpServletResponseWrapper(HttpServletResponse response) {
        super(response);
    }

    @Override
    public void addCookie(Cookie cookie) {
        if ("JSESSIONID".equals(cookie.getName())) {
            super.addHeader("Set-Cookie", getCookieValue(cookie));
        } else {
            super.addCookie(cookie);
        }
    }

    private String getCookieValue(Cookie cookie) {

        StringBuilder builder = new StringBuilder();
        builder.append(cookie.getName()).append('=').append(cookie.getValue());
        builder.append(";Path=").append(cookie.getPath());
        if (cookie.isHttpOnly()) {
            builder.append(";HttpOnly");
        }
        if (cookie.getSecure()) {
            builder.append(";Secure");
        }
        // here you can append other attributes like domain / max-age etc.
        builder.append(";SameSite=None");
        return builder.toString();
    }
}
63939078
반응형