ASP.NET 쿠키 는 어떻게 생 성 되 나 요(추천)
.NET Core 에서 ASP.NET Cookie 를 사용 해 야 한다 면 본 고 에서 언급 할 내용 도 필수 적 인 길이 될 것 이다.
실 을 뽑 아 고 치 를 벗 기 고 한 걸음 한 걸음 분석 하 다.
우선 사용 자 는 AccountController->Login 을 통 해 로그 인 합 니 다.
//
// POST: /Account/Login
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
// ......
}
}
이것 은 SignInManager 의 PasswordSignInAsync 방법 을 호출 했 습 니 다.이 방법 코드 는 다음 과 같 습 니 다(삭제 되 었 습 니 다).
public virtual async Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout)
{
// ...
if (await UserManager.CheckPasswordAsync(user, password).WithCurrentCulture())
{
if (!await IsTwoFactorEnabled(user))
{
await UserManager.ResetAccessFailedCountAsync(user.Id).WithCurrentCulture();
}
return await SignInOrTwoFactor(user, isPersistent).WithCurrentCulture();
}
// ...
return SignInStatus.Failure;
}
원본 코드 를 찾 으 려 면 공식 Github 링크 를 참조 하 십시오.https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.Owin/SignInManager.cs#L235-L276
암 호 를 먼저 검증 해 야 한 다 는 것 을 알 수 있 습 니 다.암호 검증 이 정확 한 후에 SignInOrTwo Factor 방법 을 호출 했 습 니 다.이 방법 코드 는 다음 과 같 습 니 다.
private async Task<SignInStatus> SignInOrTwoFactor(TUser user, bool isPersistent)
{
var id = Convert.ToString(user.Id);
if (await IsTwoFactorEnabled(user) && !await AuthenticationManager.TwoFactorBrowserRememberedAsync(id).WithCurrentCulture())
{
var identity = new ClaimsIdentity(DefaultAuthenticationTypes.TwoFactorCookie);
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, id));
AuthenticationManager.SignIn(identity);
return SignInStatus.RequiresVerification;
}
await SignInAsync(user, isPersistent, false).WithCurrentCulture();
return SignInStatus.Success;
}
이 코드 는 이중 검증 이 필요 한 지 여 부 를 판단 할 뿐 이중 검증 이 필요 한 상황 에서 AuthenticationManager 의 SignIn 방법 을 호출 했다.그렇지 않 으 면 SignInAsync 방법 을 호출 합 니 다.SignInAsync 의 소스 코드 는 다음 과 같 습 니 다.
public virtual async Task SignInAsync(TUser user, bool isPersistent, bool rememberBrowser)
{
var userIdentity = await CreateUserIdentityAsync(user).WithCurrentCulture();
// Clear any partial cookies from external or two factor partial sign ins
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.TwoFactorCookie);
if (rememberBrowser)
{
var rememberBrowserIdentity = AuthenticationManager.CreateTwoFactorRememberBrowserIdentity(ConvertIdToString(user.Id));
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, userIdentity, rememberBrowserIdentity);
}
else
{
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, userIdentity);
}
}
이 를 통 해 알 수 있 듯 이 최종 적 으로 모든 코드 는 AuthenticationManager.SignIn 방법 을 호출 했 기 때문에 이 방법 은 Cookie 를 만 드 는 관건 입 니 다.AuthenticationManager 의 구현 정 의 는 Microsoft.Owin 에 있 기 때문에 ASP.NET Identity 에서 원본 코드 를 찾 을 수 없습니다.따라서 Microsoft.Owin 의 소스 코드 를 열 어 계속 추적 합 니 다(삭제 되 었 습 니 다).
public void SignIn(AuthenticationProperties properties, params ClaimsIdentity[] identities)
{
AuthenticationResponseRevoke priorRevoke = AuthenticationResponseRevoke;
if (priorRevoke != null)
{
// ...
AuthenticationResponseRevoke = new AuthenticationResponseRevoke(filteredSignOuts);
}
AuthenticationResponseGrant priorGrant = AuthenticationResponseGrant;
if (priorGrant == null)
{
AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identities), properties);
}
else
{
// ...
AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(mergedIdentities), priorGrant.Properties);
}
}
AuthenticationManager 의 Github 링크 는 다음 과 같 습 니 다https://github.com/aspnet/AspNetKatana/blob/c33569969e79afd9fb4ec2d6bdff877e376821b2/src/Microsoft.Owin/Security/AuthenticationManager.csAuthentication Response Grant 를 사용 한 것 을 알 수 있 습 니 다.계속 추적 하면 실제 속성 을 볼 수 있 습 니 다.
public AuthenticationResponseGrant AuthenticationResponseGrant
{
// get
set
{
if (value == null)
{
SignInEntry = null;
}
else
{
SignInEntry = Tuple.Create((IPrincipal)value.Principal, value.Properties.Dictionary);
}
}
}
이것 은 사실 SignInEntry 를 설 치 했 음 을 발견 하고 계속 추적 합 니 다.
public Tuple<IPrincipal, IDictionary<string, string>> SignInEntry
{
get { return _context.Get<Tuple<IPrincipal, IDictionary<string, string>>>(OwinConstants.Security.SignIn); }
set { _context.Set(OwinConstants.Security.SignIn, value); }
}
그 중context 의 유형 은 IOwinContext 이 고 OwinConstants.Security.SignIn 의 상수 값 은"security.SignIn"입 니 다.추적 완료...
뭐?이렇게 오랫동안 미행 하 다가 놓 쳤 다 니!?
당연히 없 지!하지만 이제 어느 정도 기술 이 필요 합 니 다.
원래 ASP.NET 은 미들웨어(Middleware)모델 로 이 예 에서 MVC 미들웨어 를 먼저 처리 합 니 다.이 미들웨어 처리 절 차 는 Authentication Response Grant/SignInEntry 를 설정 할 때 까지 입 니 다.그러나 다음 에 CookieAuthentication 미들웨어 를 계속 실행 할 것 입 니 다.이 미들웨어 의 핵심 코드 는 aspnet/AspnetKatana 창고 에서 볼 수 있 습 니 다.관건 적 인 종 류 는 CookieAuthentication Handler 입 니 다.핵심 코드 는 다음 과 같 습 니 다.
protected override async Task ApplyResponseGrantAsync()
{
AuthenticationResponseGrant signin = Helper.LookupSignIn(Options.AuthenticationType);
// ...
if (shouldSignin)
{
var signInContext = new CookieResponseSignInContext(
Context,
Options,
Options.AuthenticationType,
signin.Identity,
signin.Properties,
cookieOptions);
// ...
model = new AuthenticationTicket(signInContext.Identity, signInContext.Properties);
// ...
string cookieValue = Options.TicketDataFormat.Protect(model);
Options.CookieManager.AppendResponseCookie(
Context,
Options.CookieName,
cookieValue,
signInContext.CookieOptions);
}
// ...
}
이 원시 함 수 는 200 줄 이 넘 는 코드 가 있 습 니 다.여 기 는 제 가 많이 생략 했 지만 관건 적 이 고 핵심 적 인 부분 을 보류 하 였 습 니 다.원시 코드 를 찾 으 려 면 Github 링크 를 옮 길 수 있 습 니 다https://github.com/aspnet/AspNetKatana/blob/0fc4611e8b04b73f4e6bd68263e3f90e1adfa447/src/Microsoft.Owin.Security.Cookies/CookieAuthenticationHandler.cs#L130-L313여기 서 가장 중요 한 것 을 몇 가지 고 르 세 요.
MVC 와 관 계 를 맺다
관계 구축 의 핵심 코드 는 첫 번 째 줄 입 니 다.위 에서 언급 한 위치 에서 Authentication Response Grant 를 되 찾 았 습 니 다.이 Grant 는 Claims,AuthenticationTicket 등 쿠키 의 중요 한 구성 부분 을 저장 합 니 다.
AuthenticationResponseGrant signin = Helper.LookupSignIn(Options.AuthenticationType);
LookupSignIn 소스 코드 를 계속 찾 아 보면 위의 AuthenticationManager 에서 AuthenticationResponse Grant 를 되 찾 았 습 니 다.(삭제 되 었 습 니 다)
public AuthenticationResponseGrant LookupSignIn(string authenticationType)
{
// ...
AuthenticationResponseGrant grant = _context.Authentication.AuthenticationResponseGrant;
// ...
foreach (var claimsIdentity in grant.Principal.Identities)
{
if (string.Equals(authenticationType, claimsIdentity.AuthenticationType, StringComparison.Ordinal))
{
return new AuthenticationResponseGrant(claimsIdentity, grant.Properties ?? new AuthenticationProperties());
}
}
return null;
}
이렇게 되자 유암 화 명 은 또 한 마을 에 있 고 모든 단 서 는 곧 밝 아 졌 다.쿠키 생 성
AuthenticationTicket 에서 Cookie 바이트 문자열 로 바 뀌 었 습 니 다.가장 중요 한 단 계 는 다음 과 같 습 니 다.
string cookieValue = Options.TicketDataFormat.Protect(model);
다음 코드 에 서 는 CookieManager 를 사용 하여 이 Cookie 바이트 문자열 을 Http 응답 에 추가 하 는 것 만 언급 합 니 다.CookieManager 를 뒤 져 보면 다음 코드 를 볼 수 있 습 니 다.
public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (options == null)
{
throw new ArgumentNullException("options");
}
IHeaderDictionary responseHeaders = context.Response.Headers;
// “1 ” chunk
responseHeaders.AppendValues(Constants.Headers.SetCookie, chunks);
}
관심 있 는 분 들 은 Github 을 방문 하여 원본 버 전의 코드 를 볼 수 있 습 니 다https://github.com/aspnet/AspNetKatana/blob/0fc4611e8b04b73f4e6bd68263e3f90e1adfa447/src/Microsoft.Owin/Infrastructure/ChunkingCookieManager.cs#L125-L215이 를 통 해 알 수 있 듯 이 이 실현 은 비교적......................................................................
점점 밝 아 져
이 방법의 원본 코드 는 다음 과 같다.
public string Protect(TData data)
{
byte[] userData = _serializer.Serialize(data);
byte[] protectedData = _protector.Protect(userData);
string protectedText = _encoder.Encode(protectedData);
return protectedText;
}
이 를 통 해 알 수 있 듯 이serializer、_protector、_encoder 세 가지 종류,그 중,serializer 의 핵심 코드 는 다음 과 같 습 니 다.
public virtual byte[] Serialize(AuthenticationTicket model)
{
using (var memory = new MemoryStream())
{
using (var compression = new GZipStream(memory, CompressionLevel.Optimal))
{
using (var writer = new BinaryWriter(compression))
{
Write(writer, model);
}
}
return memory.ToArray();
}
}
그 본질은 바 이 너 리 서열 화 를 한 번 하고 이 어 gzip 압축 을 실시 하여 쿠키 크기 가 통 제 력 을 잃 지 않도록 확보 하 는 것 이다(.NET 의 바 이 너 리 서열 화 결과 가 비교적 크 고 마이크로소프트 는 xml 를 좋아 하기 때문에 더욱 크다.😂)。그리고 보 겠 습 니 다encoder 소스 코드:
public string Encode(byte[] data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
return Convert.ToBase64String(data).TrimEnd('=').Replace('+', '-').Replace('/', '_');
}
이 를 통 해 알 수 있 듯 이 간단 한 base64-url 인 코딩 을 진 행 했 습 니 다.이 인 코딩 은=번 호 를 삭 제 했 기 때문에 base64-url 인 코딩 을 할 때=번 호 를 보충 해 야 합 니 다.이 두 가 지 는 모두 비교적 간단 하 다.약간 복잡 한 것 은 이다.protector,그것 의 유형 은 IDataProtector 입 니 다.
IDataProtector
쿠키 Authentication Middleware 에서 초기 화 되 었 습 니 다.코드 와 인 자 는 다음 과 같 습 니 다.
IDataProtector dataProtector = app.CreateDataProtector(
typeof(CookieAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v1");
세 개의 인 자 를 전 달 했 습 니 다.첫 번 째 인 자 는 CookieAuthenticationMiddleware 의 FullName 입 니 다.즉,"Microsoft.Owin.security.Cookies.CookieAuthenticationMiddleware"입 니 다.두 번 째 인 자 는 정의 되 지 않 으 면 기본 값 은 CookieAuthenticationDefaults.AuthenticationType 입 니 다.이 값 은"Cookies"로 정 의 됩 니 다.단,기본 으로 생 성 된 ASP.NET MVC 템 플 릿 항목 에서 이 값 은 ASP.NET Identity 의 기본 값 인'ApplicationCookie'로 재 정의 되 므 로 주의해 야 합 니 다.
그리고 CreateDataProtector 의 소스 코드 를 살 펴 보 겠 습 니 다.
public static IDataProtector CreateDataProtector(this IAppBuilder app, params string[] purposes)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
IDataProtectionProvider dataProtectionProvider = GetDataProtectionProvider(app);
if (dataProtectionProvider == null)
{
dataProtectionProvider = FallbackDataProtectionProvider(app);
}
return dataProtectionProvider.Create(purposes);
}
public static IDataProtectionProvider GetDataProtectionProvider(this IAppBuilder app)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
object value;
if (app.Properties.TryGetValue("security.DataProtectionProvider", out value))
{
var del = value as DataProtectionProviderDelegate;
if (del != null)
{
return new CallDataProtectionProvider(del);
}
}
return null;
}
이 를 통 해 알 수 있 듯 이 IAppBuilder 의"security.DataProtection Provider"속성 에서 IDataProtection Provider 를 가 져 옵 니 다.그렇지 않 으 면 DpapiDataProtection Provider 를 사용 합 니 다.코드 를 뒤 져 보면 OwinAppContext 에서 볼 수 있 습 니 다.이 값 은 MachineKeyDataProtection Provider 로 지정 되 었 습 니 다.
builder.Properties[Constants.SecurityDataProtectionProvider] = new MachineKeyDataProtectionProvider().ToOwinFunction();
글 속 의 Constants.Security DataProtection Provider 는 마침'security.DataProtection Provider'로 정의 되 었 다.
우 리 는 MachineKeyDataProtector 의 소스 코드 를 뒤 져 보 았 는데,마침 MachineKey 에 의존 하 는 것 을 보 았 다.
internal class MachineKeyDataProtector
{
private readonly string[] _purposes;
public MachineKeyDataProtector(params string[] purposes)
{
_purposes = purposes;
}
public virtual byte[] Protect(byte[] userData)
{
return MachineKey.Protect(userData, _purposes);
}
public virtual byte[] Unprotect(byte[] protectedData)
{
return MachineKey.Unprotect(protectedData, _purposes);
}
}
결국 우리 의 오 랜 친구 인 Machine Key 에 도착 했다.역 추진 과정,쿠키 해독
먼저 이 과정 을 정리 하고 Mvc 에서 요청 한 절차 에 있어 이 코드 들 은 ASP.NET Identity 에 집중 되 어 있 습 니 다.이 과정 은 다음 과 같 습 니 다.
그리고 CookieAuthentication 프로 세 스에 들 어 갑 니 다.이 코드 들 은 Owin 에 집중 되 어 있 습 니 다.
CookieAuthenticationMiddleware(AuthenticationResponseGrant 읽 기)
ISecureDataFormat(구현 클래스:SecureDataFormat
IDataSerializer(구현 클래스:TicketSerializer)
IDataProtector(구현 클래스:MachineKeyDataProtector)
ITextEncoder(구현 클래스:Base64UrlTextEncoder)
이런 과정 에서 상기 에서 찾 은 모든 매개 변수의 값 은 제 가 정리 한'조상 해독 코드'는 다음 과 같 습 니 다.
string cookie = "nZBqV1M-Az7yJezhb6dUzS_urj1urB0GDufSvDJSa0pv27CnDsLHRzMDdpU039j6ApL-VNfrJULfE85yU9RFzGV_aAGXHVkGckYqkCRJUKWV8SqPEjNJ5ciVzW--uxsCBNlG9jOhJI1FJIByRzYJvidjTYABWFQnSSd7XpQRjY4lb082nDZ5lwJVK3gaC_zt6H5Z1k0lUFZRb6afF52laMc___7BdZ0mZSA2kRxTk1QY8h2gQh07HqlR_p0uwTFNKi0vW9NxkplbB8zfKbfzDj7usep3zAeDEnwofyJERtboXgV9gIS21fLjc58O-4rR362IcCi2pYjaKHwZoO4LKWe1bS4r1tyzW0Ms-39Njtiyp7lRTN4HUHMUi9PxacRNgVzkfK3msTA6LkCJA3VwRm_UUeC448Lx5pkcCPCB3lGat_5ttGRjKD_lllI-YE4esXHB5eJilJDIZlEcHLv9jYhTl17H0Jl_H3FqXyPQJR-ylQfh";
var bytes = TextEncodings.Base64Url.Decode(cookie);
var decrypted = MachineKey.Unprotect(bytes,
"Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware",
"ApplicationCookie",
"v1");
var serializer = new TicketSerializer();
var ticket = serializer.Deserialize(decrypted);
ticket.Dump(); // Dump LINQPad , ,
실행 하기 전에 app.config/web.config 의 machineKey 노드 를 설정 하고 NuGet 패키지:Microsoft.Owin.security 를 설치 하 십시오.실행 결 과 는 다음 과 같 습 니 다(완벽 한 해결).총결산
학습 방식 은 여러 가지 가 있 는데 그 중에서 코드 를 보 는 것 은 제 가 개인 적 으로 매우 좋아 하 는 방식 입 니 다.모든 코드 가 평탄 한 것 은 아 닙 니 다.이 예 와 같이 ASP.NET 지식 배경 이 필요 할 수도 있 습 니 다.
이'조상 코드'는.NET Framework 를 기반 으로 한 것 으로 MachineKey 를 사 용 했 기 때문에.NET Core 에서 실행 할 수 없습니다.저 는 잠시 후에 MachineKey 라 는 종 류 를 깊이 있 게 이야기 할 것 입 니 다.바 텀 코드 가 어떻게 작 동 하 는 지 본 다음 에.NET Core 에서 ASP.NET Identity 중의 Cookie 를 직접 풀 수 있 습 니 다.기대 하 세 요!
위 에서 기술 한 것 은 편집장 이 여러분 에 게 소개 한 ASP.NET Cookie 가 어떻게 생 성 되 었 는 지 여러분 에 게 도움 이 되 기 를 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
부트스트랩 ASP.NET에서 설정하는 법1) _Layout.cshtml 內 link로 bootstrap 참조 2) Nuget 패키지에서 BootStrap 다운로드 3) 하단 부트스트랩 예제 사이트 참고해서 프로젝트 개발 참고 :...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.