ASP.NET Core에서 SameSite 쿠키 사용
작성자: Rick Anderson
SameSite는 CSRF(교차 사이트 요청 위조) 공격에 대한 보호를 제공하도록 설계된 IETF 초안 표준입니다. 원래 2016년에 초안이 발표되었고, 2019년에 업데이트되었습니다. 업데이트된 표준은 이전 표준과 호환되지 않으며 다음과 같은 가장 눈에 띄는 차이점이 있습니다.
- SameSite 헤더가 없는 쿠키는 기본적으로 처리
SameSite=Lax
됩니다. SameSite=None
은 사이트 간 cookie 사용을 허용하는 데 사용해야 합니다.- 어설션
SameSite=None
하는 쿠키도 로 표시Secure
되어야 합니다. - 사이트 간 시나리오로
sameSite=Lax
처리되므로 사용하는<iframe>
애플리케이션에 문제가 발생하거나sameSite=Strict
쿠키<iframe>
가 발생할 수 있습니다. - 이 값
SameSite=None
은 2016 표준에서 허용되지 않으며 일부 구현에서 이러한 쿠키를 다음과 같이SameSite=Strict
처리합니다. 이 문서의 이전 브라우저 지원을 참조하세요.
이 설정은 SameSite=Lax
대부분의 애플리케이션 쿠키에서 작동합니다. OIDC(OpenID Connect) 및 WS-Federation과 같은 일부 형태의 인증은 기본적으로 POST 기반 리디렉션으로 설정됩니다. 사후 기반 리디렉션은 SameSite 브라우저 보호를 트리거하므로 이러한 구성 요소에 대해 SameSite를 사용할 수 없습니다. 대부분의 OAuth 로그인은 요청 진행 방법의 차이로 인해 영향을 받지 않습니다.
쿠키를 내보내는 각 ASP.NET Core 구성 요소는 SameSite가 적절한지 여부를 결정해야 합니다.
SameSite 및 Identity
ASP.NET Core Identity 는 고급 시나리오(예IFrames
: 또는 OpenIdConnect
통합)를 제외하고 SameSite 쿠키의 영향을 크게 받지 않습니다.
Identity
를 사용할 때 cookie 공급자 또는 호출 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
을 추가하지 마세요. Identity
가 알아서 처리합니다.
SameSite 테스트 샘플 코드
다음 샘플을 다운로드하고 테스트할 수 있습니다.
Sample | Document |
---|---|
.NET Core Razor Pages | ASP.NET Core 3.1 Razor Pages SameSite cookie 샘플 |
SameSite 특성에 대한 .NET Core 지원
.NET Core는 SameSite에 대한 2019 초안 표준을 지원합니다. 개발자는 HttpCookie.SameSite
속성을 사용하여 SameSite 특성의 값을 프로그래밍 방식으로 제어할 수 있습니다. SameSite
속성을 Strict
, Lax
또는 None
으로 설정하면 해당 값이 cookie로 네트워크에 기록됩니다. SameSiteMode.Unspecified
로 설정하면 cookie를 사용하여 SameSite를 전송하지 않음을 나타냅니다.
var cookieOptions = new CookieOptions
{
// Set the secure flag, which Chrome's changes will require for SameSite none.
// Note this will also require you to be running on HTTPS.
Secure = true,
// Set the cookie to HTTP only which is good practice unless you really do need
// to access it client side in scripts.
HttpOnly = true,
// Add the SameSite attribute, this will emit the attribute with a value of none.
SameSite = SameSiteMode.None
// The client should follow its default cookie policy.
// SameSite = SameSiteMode.Unspecified
};
// Add the cookie to the response cookie collection
Response.Cookies.Append("MyCookie", "cookieValue", cookieOptions);
}
SameSite를 통한 API 사용
HttpContext.Response.Cookies.Append 는 기본값으로 Unspecified
설정됩니다. 즉, SameSite 특성이 추가 cookie 되지 않으며 클라이언트는 기본 동작(새 브라우저의 경우 Lax, 이전 브라우저의 경우 없음)을 사용합니다. 다음 코드에서는 cookie SameSite 값을 SameSiteMode.Lax
로 변경하는 방법을 보여 줍니다.
HttpContext.Response.Cookies.Append(
"name", "value",
new CookieOptions() { SameSite = SameSiteMode.Lax });
쿠키를 내보내는 모든 ASP.NET 핵심 구성 요소는 해당 시나리오에 적합한 설정으로 이전 기본값을 재정의합니다. 재정의된 이전 기본값은 변경되지 않았습니다.
ASP.NET Core 3.1 이상에서는 다음 SameSite 지원을 제공합니다.
SameSite=None
내보내기에 대한SameSiteMode.None
의 동작을 다시 정의합니다.- SameSite 특성을 생략하는 새 값
SameSiteMode.Unspecified
를 추가합니다. - 모든 쿠키 API는 기본적으로
Unspecified
. 쿠키를 사용하는 일부 구성 요소는 해당 시나리오에 보다 구체적인 값을 설정합니다. 예제는 위의 표를 참조하세요.
ASP.NET Core 3.0 이상에서 SameSite 기본값은 일관되지 않은 클라이언트 기본값과 충돌하지 않도록 변경되었습니다. 다음 API는 이러한 쿠키에 -1
대해 SameSite 특성을 내보내지 않도록 기본값 SameSiteMode.Lax
을 변경했습니다.
- CookieOptions HttpContext.Response.Cookies.Append와 함께 사용됨
CookieOptions
에 대한 팩터리로 CookieBuilder 사용- CookiePolicyOptions.MinimumSameSitePolicy
기록 및 변경 내용
SameSite 지원은 2016 초안 표준을 사용하여 ASP.NET Core 2.0에서 처음 구현되었습니다. 2016 표준은 옵트인(opt in)되었습니다. ASP.NET Core는 기본적으로 여러 쿠키를 설정하여 Lax
옵트인했습니다. 인증에 몇 가지 문제가 발생한 후에는 대부분의 SameSite 사용이 사용되지 않도록 설정되었습니다.
2016 표준에서 2019 표준으로 업데이트하기 위한 패치가 2019년 11월에 발급되었습니다. SameSite 사양의 2019 초안은 다음과 같습니다.
- 2016 초안과 이전 버전 호환이 되지 않습니다. 자세한 내용은 이 문서의 이전 브라우저 지원을 참조하세요.
- 쿠키는 기본적으로 처리
SameSite=Lax
됩니다. - 사이트 간 배달을 사용하도록 설정하기 위해 명시적으로 어설션
SameSite=None
하는 쿠키를 다음과 같이Secure
표시합니다.None
은 옵트아웃할 새 항목입니다. - ASP.NET Core 2.1, 2.2 및 3.0에 대해 발급된 패치에 의해 지원됩니다. ASP.NET Core 3.1 이상은 추가 SameSite 지원을 제공합니다.
- 2020년 2월에 기본적으로 Chrome에서 사용하도록 예약됩니다. 브라우저가 2019년의 이 표준으로 이동하기 시작했습니다.
2016 SameSite 초안에서 2019 초안 표준으로 변경되어 영향을 받는 API
- Http.SameSiteMode
- CookieOptions.SameSite
- CookieBuilder.SameSite
- CookiePolicyOptions.MinimumSameSitePolicy
- Microsoft.Net.Http.Headers.SameSiteMode
- Microsoft.Net.Http.Headers.SetCookieHeaderValue.SameSite
이전 브라우저 지원
2016 SameSite 표준에 따라 알 수 없는 값을 SameSite=Strict
값으로 처리합니다. 2016 SameSite 표준을 지원하는 이전 브라우저에서 액세스된 앱은 값이 None
인 SameSite 속성을 가져올 때 손상될 수 있습니다. 웹앱은 이전 브라우저를 지원하려는 경우 브라우저 검색을 구현해야 합니다. ASP.NET Core는 User-Agents 값이 매우 휘발성이며 자주 변경되기 때문에 브라우저 검색을 구현하지 않습니다. Microsoft.AspNetCore.CookiePolicy의 확장 지점은 User-Agent 특정 논리를 연결하는 것을 허용합니다.
에서 Program.cs
호출하기 전에 호출 UseCookiePolicy UseAuthentication 하는 코드 또는 쿠키를 작성하는 메서드 를 추가합니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
}
}
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Program.cs
에서 다음 강조 표시된 코드와 유사한 코드를 추가합니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
}
}
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
위의 샘플에서 MyUserAgentDetectionLib.DisallowsSameSiteNone
은 사용자 에이전트가 SameSite None
을 지원하지 않는지 검색하는 사용자 제공 라이브러리입니다.
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
다음 코드는 샘플 DisallowsSameSiteNone
메서드를 보여 줍니다.
Warning
다음 코드는 데모용으로만 사용할 수 있습니다.
- 완료되지 않은 것으로 간주됩니다.
- 유지 관리되거나 지원되지 않습니다.
public static bool DisallowsSameSiteNone(string userAgent)
{
// Check if a null or empty string has been passed in, since this
// will cause further interrogation of the useragent to fail.
if (String.IsNullOrWhiteSpace(userAgent))
return false;
// Cover all iOS based browsers here. This includes:
// - Safari on iOS 12 for iPhone, iPod Touch, iPad
// - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
// - Chrome on iOS 12 for iPhone, iPod Touch, iPad
// All of which are broken by SameSite=None, because they use the iOS networking
// stack.
if (userAgent.Contains("CPU iPhone OS 12") ||
userAgent.Contains("iPad; CPU OS 12"))
{
return true;
}
// Cover Mac OS X based browsers that use the Mac OS networking stack.
// This includes:
// - Safari on Mac OS X.
// This does not include:
// - Chrome on Mac OS X
// Because they do not use the Mac OS networking stack.
if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
userAgent.Contains("Version/") && userAgent.Contains("Safari"))
{
return true;
}
// Cover Chrome 50-69, because some versions are broken by SameSite=None,
// and none in this range require it.
// Note: this covers some pre-Chromium Edge versions,
// but pre-Chromium Edge does not require SameSite=None.
if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
{
return true;
}
return false;
}
SameSite 문제에 대한 앱 테스트
타사 로그인 등 원격 사이트와 상호 작용하는 앱은 다음 작업을 수행해야 합니다.
- 여러 브라우저에서 상호 작용을 테스트합니다.
- 이 문서에서 설명하는 CookiePolicy 브라우저 검색 및 완화를 적용합니다.
새 SameSite 동작을 옵트인(opt in)할 수 있는 클라이언트 버전을 사용하여 웹앱을 테스트합니다. Chrome, Firefox 및 Chromium Edge에는 테스트에 사용할 수 있는 새 옵트인 기능 플래그가 있습니다. 앱이 SameSite 패치를 적용한 후 이전 클라이언트 버전, 특히 Safari를 사용하여 테스트합니다. 자세한 내용은 이 문서의 이전 브라우저 지원을 참조하세요.
Chrome으로 테스트
Chrome 78+는 일시적인 완화를 제공하기 때문에 잘못된 결과를 제공합니다. Chrome 78 이상 임시 완화를 사용하면 쿠키가 2분 미만인 것을 허용합니다. 적절한 테스트 플래그를 사용하도록 설정하면 Chrome 76 또는 77에서 더 정확한 결과를 얻을 수 있습니다. 새 SameSite 동작을 테스트하려면 chrome://flags/#same-site-by-default-cookies
를 사용으로 설정합니다. Chrome(75 이하) 이전 버전이 새 None
설정에 실패했음이 보고됩니다. 이 문서의 이전 브라우저 지원을 참조하세요.
Google은 이전 Chrome 버전을 사용하도록 설정할 수 없습니다. Chromium 다운로드의 지침에 따라 이전 버전의 Chrome을 테스트합니다. 이전 버전의 Chrome을 검색하여 제공된 링크에서 Chrome을 다운로드하지 마세요.
Canary 버전 80.0.3975.0
부터 Lax+POST 임시 완화를 새 플래그 --enable-features=SameSiteDefaultChecksMethodRigorously
를 사용하여 테스트 목적으로 사용하지 않도록 설정하여 완화가 제거된 기능의 최종 종료 상태에서 사이트 및 서비스를 테스트할 수 있습니다. 자세한 내용은 Chromium 프로젝트 SameSite 업데이트를 참조하세요.
Safari를 사용한 테스트
Safari 12는 이전 초안을 엄격하게 구현했으며 cookie에 새 None
값이 표시되는 경우 실패합니다. None
은 이 문서에서 이전 브라우저를 지원하는 브라우저 검색 코드를 통해 방지됩니다. MSAL, ADAL 또는 사용 중인 라이브러리를 사용하여 Safari 12, Safari 13 및 WebKit 기반 OS 스타일 로그인을 테스트합니다. 문제는 기본 OS 버전에 따라 달라집니다. OSX Mojave(10.14) 및 iOS 12는 새 SameSite 동작에 호환성 문제가 있는 것으로 알려져 있습니다. OS를 OSX Catalina(10.15) 또는 iOS 13으로 업그레이드하면 문제가 해결됩니다. Safari에는 현재 새 사양 동작을 테스트하기 위한 옵트인 플래그가 없습니다.
Firefox로 테스트
새 표준에 대한 Firefox 지원은 기능 플래그 network.cookie.sameSite.laxByDefault
를 사용하여 about:config
페이지에서 옵트인하여 버전 68 이상에서 테스트할 수 있습니다. 이전 버전의 Firefox와의 호환성 문제에 대한 보고서가 없습니다.
Edge 브라우저를 사용한 테스트
Edge는 이전 SameSite 표준을 지원합니다. Edge 버전 44에는 새로운 표준과의 알려진 호환성 문제가 없습니다.
Edge(Chromium)를 사용한 테스트
SameSite 플래그는 edge://flags/#same-site-by-default-cookies
페이지에 설정되어 있습니다. Edge Chromium에서 호환성 문제가 검색되지 않았습니다.
Electron을 사용한 테스트
Electron 버전에는 이전 버전의 Chromium이 포함되어 있습니다. 예를 들어, Teams에서 사용하는 Electron의 버전은 Chromium 66이며, 이는 이전 동작을 수행합니다. 사용자의 제품에서 사용하는 Electron 버전으로 자체 호환성 테스트를 수행해야 합니다. 다음 섹션에서 이전 브라우저 지원을 참조하세요.
추가 리소스
Sample | Document |
---|---|
.NET Core Razor Pages | ASP.NET Core 3.1 Razor Pages SameSite cookie 샘플 |
다음 샘플을 다운로드하고 테스트할 수 있습니다.
Sample | Document |
---|---|
.NET Core Razor Pages | ASP.NET Core 3.1 Razor Pages SameSite cookie 샘플 |
SameSite 특성에 대한 .NET Core 지원
.NET Core 3.1 이상은 SameSite에 대한 2019 초안 표준을 지원합니다. 개발자는 HttpCookie.SameSite
속성을 사용하여 SameSite 특성의 값을 프로그래밍 방식으로 제어할 수 있습니다. SameSite
속성을 Strict, Lax 또는 None으로 설정하면 해당 값이 cookie로 네트워크에 기록됩니다. 이 값을 (SameSiteMode)(-1)
로 설정하면 SameSite 특성이 cookie로 네트워크에 포함되지 않음을 나타냅니다.
var cookieOptions = new CookieOptions
{
// Set the secure flag, which Chrome's changes will require for SameSite none.
// Note this will also require you to be running on HTTPS.
Secure = true,
// Set the cookie to HTTP only which is good practice unless you really do need
// to access it client side in scripts.
HttpOnly = true,
// Add the SameSite attribute, this will emit the attribute with a value of none.
// To not emit the attribute at all set
// SameSite = (SameSiteMode)(-1)
SameSite = SameSiteMode.None
};
// Add the cookie to the response cookie collection
Response.Cookies.Append("MyCookie", "cookieValue", cookieOptions);
.NET Core 3.1 이상에서는 업데이트된 SameSite 값을 지원하고 SameSiteMode
열거형에 추가 열거형 값 SameSiteMode.Unspecified
를 추가합니다.
이 새 값은 cookie를 사용하여 SameSite를 전송하지 않음을 나타냅니다.
SameSite를 통한 API 사용
HttpContext.Response.Cookies.Append 는 기본값으로 Unspecified
설정됩니다. 즉, SameSite 특성이 추가 cookie 되지 않으며 클라이언트는 기본 동작(새 브라우저의 경우 Lax, 이전 브라우저의 경우 없음)을 사용합니다. 다음 코드에서는 cookie SameSite 값을 SameSiteMode.Lax
로 변경하는 방법을 보여 줍니다.
HttpContext.Response.Cookies.Append(
"name", "value",
new CookieOptions() { SameSite = SameSiteMode.Lax });
쿠키를 내보내는 모든 ASP.NET 핵심 구성 요소는 해당 시나리오에 적합한 설정으로 이전 기본값을 재정의합니다. 재정의된 이전 기본값은 변경되지 않았습니다.
ASP.NET Core 3.1 이상에서는 다음 SameSite 지원을 제공합니다.
SameSite=None
내보내기에 대한SameSiteMode.None
의 동작을 다시 정의합니다.- SameSite 특성을 생략하는 새 값
SameSiteMode.Unspecified
를 추가합니다. - 모든 쿠키 API는 기본적으로
Unspecified
. 쿠키를 사용하는 일부 구성 요소는 해당 시나리오에 보다 구체적인 값을 설정합니다. 예제는 위의 표를 참조하세요.
ASP.NET Core 3.0 이상에서 SameSite 기본값은 일관되지 않은 클라이언트 기본값과 충돌하지 않도록 변경되었습니다. 다음 API는 이러한 쿠키에 -1
대해 SameSite 특성을 내보내지 않도록 기본값 SameSiteMode.Lax
을 변경했습니다.
- CookieOptions HttpContext.Response.Cookies.Append와 함께 사용됨
CookieOptions
에 대한 팩터리로 CookieBuilder 사용- CookiePolicyOptions.MinimumSameSitePolicy
기록 및 변경 내용
SameSite 지원은 2016 초안 표준을 사용하여 ASP.NET Core 2.0에서 처음 구현되었습니다. 2016 표준은 옵트인(opt in)되었습니다. ASP.NET Core는 기본적으로 여러 쿠키를 설정하여 Lax
옵트인했습니다. 인증에 몇 가지 문제가 발생한 후에는 대부분의 SameSite 사용이 사용되지 않도록 설정되었습니다.
2016 표준에서 2019 표준으로 업데이트하기 위한 패치가 2019년 11월에 발급되었습니다. SameSite 사양의 2019 초안은 다음과 같습니다.
- 2016 초안과 이전 버전 호환이 되지 않습니다. 자세한 내용은 이 문서의 이전 브라우저 지원을 참조하세요.
- 쿠키는 기본적으로 처리
SameSite=Lax
됩니다. - 사이트 간 배달을 사용하도록 설정하기 위해 명시적으로 어설션
SameSite=None
하는 쿠키를 다음과 같이Secure
표시합니다.None
은 옵트아웃할 새 항목입니다. - ASP.NET Core 2.1, 2.2 및 3.0에 대해 발급된 패치에 의해 지원됩니다. ASP.NET Core 3.1은 추가 SameSite 지원을 제공합니다.
- 2020년 2월에 기본적으로 Chrome에서 사용하도록 예약됩니다. 브라우저가 2019년의 이 표준으로 이동하기 시작했습니다.
2016 SameSite 초안에서 2019 초안 표준으로 변경되어 영향을 받는 API
- Http.SameSiteMode
- CookieOptions.SameSite
- CookieBuilder.SameSite
- CookiePolicyOptions.MinimumSameSitePolicy
- Microsoft.Net.Http.Headers.SameSiteMode
- Microsoft.Net.Http.Headers.SetCookieHeaderValue.SameSite
이전 브라우저 지원
2016 SameSite 표준에 따라 알 수 없는 값을 SameSite=Strict
값으로 처리합니다. 2016 SameSite 표준을 지원하는 이전 브라우저에서 액세스된 앱은 값이 None
인 SameSite 속성을 가져올 때 손상될 수 있습니다. 웹앱은 이전 브라우저를 지원하려는 경우 브라우저 검색을 구현해야 합니다. ASP.NET Core는 User-Agents 값이 매우 휘발성이며 자주 변경되기 때문에 브라우저 검색을 구현하지 않습니다. Microsoft.AspNetCore.CookiePolicy의 확장 지점은 User-Agent 특정 논리를 연결하는 것을 허용합니다.
에서 Startup.Configure
호출하기 전에 호출 UseCookiePolicy UseAuthentication 하는 코드 또는 쿠키를 작성하는 메서드 를 추가합니다.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
Startup.ConfigureServices
에서 다음과 유사한 코드를 추가합니다.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
services.AddRazorPages();
}
private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
}
}
위의 샘플에서 MyUserAgentDetectionLib.DisallowsSameSiteNone
은 사용자 에이전트가 SameSite None
을 지원하지 않는지 검색하는 사용자 제공 라이브러리입니다.
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
다음 코드는 샘플 DisallowsSameSiteNone
메서드를 보여 줍니다.
Warning
다음 코드는 데모용으로만 사용할 수 있습니다.
- 완료되지 않은 것으로 간주됩니다.
- 유지 관리되거나 지원되지 않습니다.
public static bool DisallowsSameSiteNone(string userAgent)
{
// Check if a null or empty string has been passed in, since this
// will cause further interrogation of the useragent to fail.
if (String.IsNullOrWhiteSpace(userAgent))
return false;
// Cover all iOS based browsers here. This includes:
// - Safari on iOS 12 for iPhone, iPod Touch, iPad
// - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
// - Chrome on iOS 12 for iPhone, iPod Touch, iPad
// All of which are broken by SameSite=None, because they use the iOS networking
// stack.
if (userAgent.Contains("CPU iPhone OS 12") ||
userAgent.Contains("iPad; CPU OS 12"))
{
return true;
}
// Cover Mac OS X based browsers that use the Mac OS networking stack.
// This includes:
// - Safari on Mac OS X.
// This does not include:
// - Chrome on Mac OS X
// Because they do not use the Mac OS networking stack.
if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
userAgent.Contains("Version/") && userAgent.Contains("Safari"))
{
return true;
}
// Cover Chrome 50-69, because some versions are broken by SameSite=None,
// and none in this range require it.
// Note: this covers some pre-Chromium Edge versions,
// but pre-Chromium Edge does not require SameSite=None.
if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
{
return true;
}
return false;
}
SameSite 문제에 대한 앱 테스트
타사 로그인 등 원격 사이트와 상호 작용하는 앱은 다음 작업을 수행해야 합니다.
- 여러 브라우저에서 상호 작용을 테스트합니다.
- 이 문서에서 설명하는 CookiePolicy 브라우저 검색 및 완화를 적용합니다.
새 SameSite 동작을 옵트인(opt in)할 수 있는 클라이언트 버전을 사용하여 웹앱을 테스트합니다. Chrome, Firefox 및 Chromium Edge에는 테스트에 사용할 수 있는 새 옵트인 기능 플래그가 있습니다. 앱이 SameSite 패치를 적용한 후 이전 클라이언트 버전, 특히 Safari를 사용하여 테스트합니다. 자세한 내용은 이 문서의 이전 브라우저 지원을 참조하세요.
Chrome으로 테스트
Chrome 78+는 일시적인 완화를 제공하기 때문에 잘못된 결과를 제공합니다. Chrome 78 이상 임시 완화를 사용하면 쿠키가 2분 미만인 것을 허용합니다. 적절한 테스트 플래그를 사용하도록 설정하면 Chrome 76 또는 77에서 더 정확한 결과를 얻을 수 있습니다. 새 SameSite 동작을 테스트하려면 chrome://flags/#same-site-by-default-cookies
를 사용으로 설정합니다. Chrome(75 이하) 이전 버전이 새 None
설정에 실패했음이 보고됩니다. 이 문서의 이전 브라우저 지원을 참조하세요.
Google은 이전 Chrome 버전을 사용하도록 설정할 수 없습니다. Chromium 다운로드의 지침에 따라 이전 버전의 Chrome을 테스트합니다. 이전 버전의 Chrome을 검색하여 제공된 링크에서 Chrome을 다운로드하지 마세요.
Canary 버전 80.0.3975.0
부터 Lax+POST 임시 완화를 새 플래그 --enable-features=SameSiteDefaultChecksMethodRigorously
를 사용하여 테스트 목적으로 사용하지 않도록 설정하여 완화가 제거된 기능의 최종 종료 상태에서 사이트 및 서비스를 테스트할 수 있습니다. 자세한 내용은 Chromium 프로젝트 SameSite 업데이트를 참조하세요.
Safari를 사용한 테스트
Safari 12는 이전 초안을 엄격하게 구현했으며 cookie에 새 None
값이 표시되는 경우 실패합니다. None
은 이 문서에서 이전 브라우저를 지원하는 브라우저 검색 코드를 통해 방지됩니다. MSAL, ADAL 또는 사용 중인 라이브러리를 사용하여 Safari 12, Safari 13 및 WebKit 기반 OS 스타일 로그인을 테스트합니다. 문제는 기본 OS 버전에 따라 달라집니다. OSX Mojave(10.14) 및 iOS 12는 새 SameSite 동작에 호환성 문제가 있는 것으로 알려져 있습니다. OS를 OSX Catalina(10.15) 또는 iOS 13으로 업그레이드하면 문제가 해결됩니다. Safari에는 현재 새 사양 동작을 테스트하기 위한 옵트인 플래그가 없습니다.
Firefox로 테스트
새 표준에 대한 Firefox 지원은 기능 플래그 network.cookie.sameSite.laxByDefault
를 사용하여 about:config
페이지에서 옵트인하여 버전 68 이상에서 테스트할 수 있습니다. 이전 버전의 Firefox와의 호환성 문제에 대한 보고서가 없습니다.
Edge 브라우저를 사용한 테스트
Edge는 이전 SameSite 표준을 지원합니다. Edge 버전 44에는 새로운 표준과의 알려진 호환성 문제가 없습니다.
Edge(Chromium)를 사용한 테스트
SameSite 플래그는 edge://flags/#same-site-by-default-cookies
페이지에 설정되어 있습니다. Edge Chromium에서 호환성 문제가 검색되지 않았습니다.
Electron을 사용한 테스트
Electron 버전에는 이전 버전의 Chromium이 포함되어 있습니다. 예를 들어, Teams에서 사용하는 Electron의 버전은 Chromium 66이며, 이는 이전 동작을 수행합니다. 사용자의 제품에서 사용하는 Electron 버전으로 자체 호환성 테스트를 수행해야 합니다. 다음 섹션에서 이전 브라우저 지원을 참조하세요.
추가 리소스
Sample | Document |
---|---|
.NET Core Razor Pages | ASP.NET Core 3.1 Razor Pages SameSite cookie 샘플 |
다음 샘플을 다운로드하고 테스트할 수 있습니다.
Sample | Document |
---|---|
.NET Core MVC | ASP.NET Core 2.1 MVC SameSite cookie 샘플 |
.NET Core Razor Pages | ASP.NET Core 2.1 Razor Pages SameSite cookie 샘플 |
12월 패치 동작 변경 내용
.NET Framework 및 .NET Core 2.1의 특정 동작 변경 내용은 SameSite
속성이 None
값을 해석하는 방법입니다. 패치 이전 None
의 값은 “특성을 전혀 내보내지 않음”을 의미하고, 패치 이후에는 “값이 None
인 특성을 내보냄”을 의미합니다. 패치 이후에 (SameSiteMode)(-1)
의 SameSite
값은 특성을 내보내지 않습니다.
양식 인증 및 세션 상태 쿠키에 대한 기본 SameSite 값이 .로 None
Lax
변경되었습니다.
SameSite를 통한 API 사용
HttpContext.Response.Cookies.Append 는 기본값으로 Unspecified
설정됩니다. 즉, SameSite 특성이 추가 cookie 되지 않으며 클라이언트는 기본 동작(새 브라우저의 경우 Lax, 이전 브라우저의 경우 없음)을 사용합니다. 다음 코드에서는 cookie SameSite 값을 SameSiteMode.Lax
로 변경하는 방법을 보여 줍니다.
HttpContext.Response.Cookies.Append(
"name", "value",
new CookieOptions() { SameSite = SameSiteMode.Lax });
쿠키를 내보내는 모든 ASP.NET 핵심 구성 요소는 해당 시나리오에 적합한 설정으로 이전 기본값을 재정의합니다. 재정의된 이전 기본값은 변경되지 않았습니다.
기록 및 변경 내용
SameSite 지원은 2016 초안 표준을 사용하여 ASP.NET Core 2.0에서 처음 구현되었습니다. 2016 표준은 옵트인(opt in)되었습니다. ASP.NET Core는 기본적으로 여러 쿠키를 설정하여 Lax
옵트인했습니다. 인증에 몇 가지 문제가 발생한 후에는 대부분의 SameSite 사용이 사용되지 않도록 설정되었습니다.
2016 표준에서 2019 표준으로 업데이트하기 위한 패치가 2019년 11월에 발급되었습니다. SameSite 사양의 2019 초안은 다음과 같습니다.
- 2016 초안과 이전 버전 호환이 되지 않습니다. 자세한 내용은 이 문서의 이전 브라우저 지원을 참조하세요.
- 쿠키는 기본적으로 처리
SameSite=Lax
됩니다. - 사이트 간 배달을 사용하도록 설정하기 위해 명시적으로 어설션
SameSite=None
하는 쿠키를 다음과 같이Secure
표시합니다.None
은 옵트아웃할 새 항목입니다. - ASP.NET Core 2.1, 2.2 및 3.0에 대해 발급된 패치에 의해 지원됩니다. ASP.NET Core 3.1은 추가 SameSite 지원을 제공합니다.
- 2020년 2월에 기본적으로 Chrome에서 사용하도록 예약됩니다. 브라우저가 2019년의 이 표준으로 이동하기 시작했습니다.
2016 SameSite 초안에서 2019 초안 표준으로 변경되어 영향을 받는 API
- Http.SameSiteMode
- CookieOptions.SameSite
- CookieBuilder.SameSite
- CookiePolicyOptions.MinimumSameSitePolicy
- Microsoft.Net.Http.Headers.SameSiteMode
- Microsoft.Net.Http.Headers.SetCookieHeaderValue.SameSite
이전 브라우저 지원
2016 SameSite 표준에 따라 알 수 없는 값을 SameSite=Strict
값으로 처리합니다. 2016 SameSite 표준을 지원하는 이전 브라우저에서 액세스된 앱은 값이 None
인 SameSite 속성을 가져올 때 손상될 수 있습니다. 웹앱은 이전 브라우저를 지원하려는 경우 브라우저 검색을 구현해야 합니다. ASP.NET Core는 User-Agents 값이 매우 휘발성이며 자주 변경되기 때문에 브라우저 검색을 구현하지 않습니다. Microsoft.AspNetCore.CookiePolicy의 확장 지점은 User-Agent 특정 논리를 연결하는 것을 허용합니다.
에서 Startup.Configure
호출하기 전에 호출 UseCookiePolicy UseAuthentication 하는 코드 또는 쿠키를 작성하는 메서드 를 추가합니다.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
Startup.ConfigureServices
에서 다음과 유사한 코드를 추가합니다.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = (SameSiteMode)(-1);
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
services.AddRazorPages();
}
private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = (SameSiteMode)(-1);
}
}
}
위의 샘플에서 MyUserAgentDetectionLib.DisallowsSameSiteNone
은 사용자 에이전트가 SameSite None
을 지원하지 않는지 검색하는 사용자 제공 라이브러리입니다.
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
다음 코드는 샘플 DisallowsSameSiteNone
메서드를 보여 줍니다.
Warning
다음 코드는 데모용으로만 사용할 수 있습니다.
- 완료되지 않은 것으로 간주됩니다.
- 유지 관리되거나 지원되지 않습니다.
public static bool DisallowsSameSiteNone(string userAgent)
{
// Check if a null or empty string has been passed in, since this
// will cause further interrogation of the useragent to fail.
if (String.IsNullOrWhiteSpace(userAgent))
return false;
// Cover all iOS based browsers here. This includes:
// - Safari on iOS 12 for iPhone, iPod Touch, iPad
// - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
// - Chrome on iOS 12 for iPhone, iPod Touch, iPad
// All of which are broken by SameSite=None, because they use the iOS networking
// stack.
if (userAgent.Contains("CPU iPhone OS 12") ||
userAgent.Contains("iPad; CPU OS 12"))
{
return true;
}
// Cover Mac OS X based browsers that use the Mac OS networking stack.
// This includes:
// - Safari on Mac OS X.
// This does not include:
// - Chrome on Mac OS X
// Because they do not use the Mac OS networking stack.
if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
userAgent.Contains("Version/") && userAgent.Contains("Safari"))
{
return true;
}
// Cover Chrome 50-69, because some versions are broken by SameSite=None,
// and none in this range require it.
// Note: this covers some pre-Chromium Edge versions,
// but pre-Chromium Edge does not require SameSite=None.
if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
{
return true;
}
return false;
}
SameSite 문제에 대한 앱 테스트
타사 로그인 등 원격 사이트와 상호 작용하는 앱은 다음 작업을 수행해야 합니다.
- 여러 브라우저에서 상호 작용을 테스트합니다.
- 이 문서에서 설명하는 CookiePolicy 브라우저 검색 및 완화를 적용합니다.
새 SameSite 동작을 옵트인(opt in)할 수 있는 클라이언트 버전을 사용하여 웹앱을 테스트합니다. Chrome, Firefox 및 Chromium Edge에는 테스트에 사용할 수 있는 새 옵트인 기능 플래그가 있습니다. 앱이 SameSite 패치를 적용한 후 이전 클라이언트 버전, 특히 Safari를 사용하여 테스트합니다. 자세한 내용은 이 문서의 이전 브라우저 지원을 참조하세요.
Chrome으로 테스트
Chrome 78+는 일시적인 완화를 제공하기 때문에 잘못된 결과를 제공합니다. Chrome 78 이상 임시 완화를 사용하면 쿠키가 2분 미만인 것을 허용합니다. 적절한 테스트 플래그를 사용하도록 설정하면 Chrome 76 또는 77에서 더 정확한 결과를 얻을 수 있습니다. 새 SameSite 동작을 테스트하려면 chrome://flags/#same-site-by-default-cookies
를 사용으로 설정합니다. Chrome(75 이하) 이전 버전이 새 None
설정에 실패했음이 보고됩니다. 이 문서의 이전 브라우저 지원을 참조하세요.
Google은 이전 Chrome 버전을 사용하도록 설정할 수 없습니다. Chromium 다운로드의 지침에 따라 이전 버전의 Chrome을 테스트합니다. 이전 버전의 Chrome을 검색하여 제공된 링크에서 Chrome을 다운로드하지 마세요.
Canary 버전 80.0.3975.0
부터 Lax+POST 임시 완화를 새 플래그 --enable-features=SameSiteDefaultChecksMethodRigorously
를 사용하여 테스트 목적으로 사용하지 않도록 설정하여 완화가 제거된 기능의 최종 종료 상태에서 사이트 및 서비스를 테스트할 수 있습니다. 자세한 내용은 Chromium 프로젝트 SameSite 업데이트를 참조하세요.
Safari를 사용한 테스트
Safari 12는 이전 초안을 엄격하게 구현했으며 cookie에 새 None
값이 표시되는 경우 실패합니다. None
은 이 문서에서 이전 브라우저를 지원하는 브라우저 검색 코드를 통해 방지됩니다. MSAL, ADAL 또는 사용 중인 라이브러리를 사용하여 Safari 12, Safari 13 및 WebKit 기반 OS 스타일 로그인을 테스트합니다. 문제는 기본 OS 버전에 따라 달라집니다. OSX Mojave(10.14) 및 iOS 12는 새 SameSite 동작에 호환성 문제가 있는 것으로 알려져 있습니다. OS를 OSX Catalina(10.15) 또는 iOS 13으로 업그레이드하면 문제가 해결됩니다. Safari에는 현재 새 사양 동작을 테스트하기 위한 옵트인 플래그가 없습니다.
Firefox로 테스트
새 표준에 대한 Firefox 지원은 기능 플래그 network.cookie.sameSite.laxByDefault
를 사용하여 about:config
페이지에서 옵트인하여 버전 68 이상에서 테스트할 수 있습니다. 이전 버전의 Firefox와의 호환성 문제에 대한 보고서가 없습니다.
Edge 브라우저를 사용한 테스트
Edge는 이전 SameSite 표준을 지원합니다. Edge 버전 44에는 새로운 표준과의 알려진 호환성 문제가 없습니다.
Edge(Chromium)를 사용한 테스트
SameSite 플래그는 edge://flags/#same-site-by-default-cookies
페이지에 설정되어 있습니다. Edge Chromium에서 호환성 문제가 검색되지 않았습니다.
Electron을 사용한 테스트
Electron 버전에는 이전 버전의 Chromium이 포함되어 있습니다. 예를 들어, Teams에서 사용하는 Electron의 버전은 Chromium 66이며, 이는 이전 동작을 수행합니다. 사용자의 제품에서 사용하는 Electron 버전으로 자체 호환성 테스트를 수행해야 합니다. 다음 섹션에서 이전 브라우저 지원을 참조하세요.
추가 리소스
Sample | Document |
---|---|
.NET Core MVC | ASP.NET Core 2.1 MVC SameSite cookie 샘플 |
.NET Core Razor Pages | ASP.NET Core 2.1 Razor Pages SameSite cookie 샘플 |
ASP.NET Core