asp net core 2.1 에서 jwt 를 어떻게 사용 하 는 지(원리 부터 정통 까지)
최근 모 바 일 개발 의 열기 가 점점 커지 고 있 습 니 다.학교 에서 개최 하 는 각종 경 기 는 모 바 일 앱 으로 장면 을 지탱 해 야 하기 때문에 백 엔 드 를 쓰 는 사람 으로서 예전 의 세 션 기반 인증 방식 을 개선 할 필요 가 있 습 니 다.이 유 는 다음 과 같 습 니 다.
다음은 Jwt 를 사용 하 는 시스템 의 인증 절차 입 니 다.
이 를 통 해 알 수 있 듯 이 사용자 의 정 보 는 Token 에 저장 되 고 Token 은 사용자 의 장치 에 분포 되 어 있 기 때문에 서버 는 더 이상 메모리 에 사용자 정 보 를 저장 할 필요 가 없습니다.
인증 한 Token 이 전달 할 때 상당히 간단 한 형식 으로 header 에 저장 되 어 클 라 이언 트 가 이 를 조작 하 는 데 편리 합 니 다.
의 원리
jwt 는 모든 언어 에 통용 되 며,비밀 키 만 알 면 다른 언어 는 jwt 의 유효성 을 판단 할 수 있 습 니 다.
jwt 의 구성;Header 부분 Base 64 전환.Payload 부분 Base 64 전환.HS 256 방식 으로 비밀 키 에 따라 앞의 두 부분 을 암호 화한 다음 Base 64 로 전환 합 니 다.그 중에서 사용 하 는 hs 256 암호 화 는 header 부분 에서 지정 한 것 이 고 홈 페이지 를 통 해서 도 볼 수 있 습 니 다.다음 그림:
원 리 는 이렇게 간단 하 다.그렇다면 도대체 C\#를 어떻게 사용 하여 실현 할 것 인가?그 정확성 을 어떻게 확정 할 것 인가?계속 하 세 요.
C\#구현 사용 하기
Microsoft.Identity Model.Tokens.dll,asp.net core 2.1 에 사용 할 오늘 의 방법 을 정의 합 니 다.다른 버 전이 없 으 면 nuget 라 이브 러 리 가 필요 합 니 다.
/// <summary>
/// jwttoken,
/// </summary>
/// <param name="payLoad"></param>
/// <param name="header"></param>
/// <returns></returns>
public static string CreateToken(Dictionary<string, object> payLoad,int expiresMinute, Dictionary<string, object> header = null)
{
if (header == null)
{
header = new Dictionary<string, object>(new List<KeyValuePair<string, object>>() {
new KeyValuePair<string, object>("alg", "HS256"),
new KeyValuePair<string, object>("typ", "JWT")
});
}
// jwt ( )
var now = DateTime.UtcNow;
payLoad["nbf"] = ToUnixEpochDate( now);//
payLoad["exp"] = ToUnixEpochDate(now.Add(TimeSpan.FromMinutes(expiresMinute)));//
var encodedHeader = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(header));
var encodedPayload = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(payLoad));
var hs256 = new HMACSHA256(Encoding.ASCII.GetBytes(securityKey));
var encodedSignature = Base64UrlEncoder.Encode(hs256.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(encodedHeader, ".", encodedPayload))));
var encodedJwt = string.Concat(encodedHeader, ".", encodedPayload, ".", encodedSignature);
return encodedJwt;
}
public static long ToUnixEpochDate(DateTime date) => (long)Math.Round((date.ToUniversalTime() - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds);
이 방법 은 매우 간단 합 니 다.header 키 쌍 과 pay Load 키 쌍 을 입력 한 다음 원리 에 따라 Base 64 변환 과 hs 256 암호 화 를 진행 합 니 다.그 다음 에 테스트 클래스 를 사용 하여 테스트 합 니 다.코드 는 다음 과 같 습 니 다.
[TestMethod]
public void TokenValidateTest()
{
Dictionary<string, object> payLoad = new Dictionary<string, object>();
payLoad.Add("sub", "rober");
payLoad.Add("jti", "09e572c7-62d0-4198-9cce-0915d7493806");
payLoad.Add("nbf", null);
payLoad.Add("exp", null);
payLoad.Add("iss", "roberIssuer");
payLoad.Add("aud", "roberAudience");
payLoad.Add("age", 30);
var encodeJwt = TokenContext.CreateToken(payLoad, 30);
var result = TokenContext.Validate(encodeJwt, (load) => { return true; });
Assert.IsTrue(result);
}
우선 뒤의 검증 을 상관 하지 않 고,이 가운데 생 성 된 encodeJwt 의 값 을 살 펴 보 자.3VLciIsImF1ZCI6InJVYmVyQXVkaWVuY2UiLCJhZ2UiOjMwQ.7Is2KYHAtSr5fW2gPU1jGeH Pzz2ULCZJGCWb40LSYyw첫 번 째 부분 과 두 번 째 부분 은 암호 화 된 것 이 아니 라 Base 64 변환 일 뿐 입 니 다.우 리 는 다른 언어 를 통 해 쉽게 변환 할 수 있 습 니 다.다음 과 같이 javascript 을 사용 하여 전환 할 수 있 습 니 다.window.atob(base 64 암호 화)window.btoa(base 64 복호화)
var header=JSON.parse(window.atob('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9'))
다음 그림:나 는 다시 payLoa 를 바 꾸 었 다
var payLoad=JSON.parse(window.atob('eyJzdWIiOiJyb2JlciIsImp0aSI6IjY0OWMyYjUxLTE4ZGQtNDEzYy05Yzc5LTI4NWNhMDAxODU2NSIsIm5iZiI6MTU0MDYxMDY2NSwiZXhwIjoxNTQwNjEyNDY1LCJpc3MiOiJyb2Jlcklzc3VlciIsImF1ZCI6InJvYmVyQXVkaWVuY2UiLCJhZ2UiOjMwfQ'))
다음 그림:따라서 여기 서 알 수 있 듯 이 Base 64 는 암호 화 에 속 하 는 것 이 아니 라 간단하게 전환 되 기 때문에 payLoad 에 중요 한 내용 을 저장 할 수 없습니다.예 를 들 어 비밀번호 등 입 니 다.
aspnetcore 에서 자체 가지 고 있 는 클래스 를 사용 하여 jwt 생 성
aspnet core 에서 jwt 도움말 류 를 가 져 왔 습 니 다.사실은 원리 와 같이 위 에 포장 을 하고 내용 을 풍부 화 시 켰 습 니 다.우 리 는 정태 적 인 방법 을 계속 사용 합 니 다.다음 과 같 습 니 다.
/// <summary>
/// jwtToken, , HS256 , ,
/// CreateToken
/// </summary>
/// <param name="payLoad"></param>
/// <param name="expiresMinute"> </param>
/// <returns></returns>
public static string CreateTokenByHandler(Dictionary<string, object> payLoad, int expiresMinute)
{
var now = DateTime.UtcNow;
// Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims.
// You can add other claims here, if you want:
var claims = new List<Claim>();
foreach (var key in payLoad.Keys)
{
var tempClaim = new Claim(key, payLoad[key]?.ToString());
claims.Add(tempClaim);
}
// Create the JWT and write it to a string
var jwt = new JwtSecurityToken(
issuer: null,
audience: null,
claims: claims,
notBefore: now,
expires: now.Add(TimeSpan.FromMinutes(expiresMinute)),
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(securityKey)), SecurityAlgorithms.HmacSha256));
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
return encodedJwt;
}
이 효 과 는 위 와 똑 같 습 니 다.같은 header,payload,비밀 키 를 사용 하면 jwt 가 생 성 된 것 과 같 습 니 다.여기 서 보 여 주지 않 고 관심 있 는 것 은 스스로 시도 할 수 있 습 니 다.aspntcore 에서 사용자 정의 jwt 인증 을 어떻게 사용 합 니까?
위 에서 그렇게 많은 이 야 기 를 했 습 니 다.다만 jwt 를 어떻게 사용 하여 검증 하 는 지 더 잘 이해 하기 위해 서 입 니 다.그것 은 jwt 가 어떻게 검증 하 는 것 입 니까?http 요청 이 오 면 http 요청 머리의 Authorization 에 jwt 가 지 니 고 있 습 니 다.먼저 어떻게 얻 는 지 보지 않 고 그 가 어떻게 검증 하 는 지 먼저 보 자.우 리 는 정적 방법 을 정의 한다.다음 과 같다.
/// <summary>
/// ,
/// </summary>
/// <param name="encodeJwt"></param>
/// <param name="validatePayLoad"> ; , , </param>
/// :payLoad["aud"]?.ToString() == "roberAuddience";
/// :
/// <returns></returns>
public static bool Validate(string encodeJwt,Func<Dictionary<string,object>,bool> validatePayLoad)
{
var success = true;
var jwtArr = encodeJwt.Split('.');
var header = JsonConvert.DeserializeObject<Dictionary<string, object>>(Base64UrlEncoder.Decode(jwtArr[0]));
var payLoad = JsonConvert.DeserializeObject<Dictionary<string, object>>(Base64UrlEncoder.Decode(jwtArr[1]));
var hs256 = new HMACSHA256(Encoding.ASCII.GetBytes(securityKey));
// ( )
success = success && string.Equals(jwtArr[2], Base64UrlEncoder.Encode(hs256.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(jwtArr[0], ".", jwtArr[1])))));
if (!success)
{
return success;//
}
// ( )
var now = ToUnixEpochDate(DateTime.UtcNow);
success = success && (now >= long.Parse(payLoad["nbf"].ToString()) && now < long.Parse(payLoad["exp"].ToString()));
//
success = success && validatePayLoad(payLoad);
return success;
}
그 중에서 vaidatePayLoad 인 자 는 사용자 정의 검증 Fun 입 니 다.이 Fun 방법 을 실행 할 때 복호화 한 payload 를 매개 변수 로 입력 합 니 다.우 리 는 검증 을 통 해 두 부분 으로 나 누 었 다.
첫째,필요 하 다.
jwt 서명 이 정확 한 지 여 부 는 상기 코드 의 실현 을 보십시오jwt 가 가능 한 시간 내 에 상기 코드 의 실현 여 부 를 보십시오둘째,사용자 정의(각 복잡 한 원 리 는 pay Load 의 특정한 값 을 얻 은 다음 에 이 값 에 대해 각종 판독 을 하 는 것 입 니 다.
[TestMethod]
public void TokenCustomerValidateTest()
{
Dictionary<string, object> payLoad = new Dictionary<string, object>();
payLoad.Add("sub", "rober");
payLoad.Add("jti", Guid.NewGuid().ToString());
payLoad.Add("nbf", null);
payLoad.Add("exp", null);
payLoad.Add("iss", "roberIssuer");
payLoad.Add("aud", "roberAudience");
payLoad.Add("age", 30);
var encodeJwt = TokenContext.CreateToken(payLoad, 30);
var result = TokenContext.Validate(encodeJwt, (load) => {
var success = true;
// aud roberAudience
success = success&& load["aud"]?.ToString() == "roberAudience";
// age>20
int.TryParse(load["age"].ToString(), out int age);
Assert.IsTrue(age > 30);
// jwt jti
return success;
});
Assert.IsTrue(result);
}
위 와 같이 우 리 는 jwt 중의 payload 를 분석 한 다음 에 각종 복잡 한 원 하 는 검증 을 할 수 있다.사실,aspnet core 의 역할,사용자,전략,사용자 정의 정책 에 대한 검증 은 이곳 의 사용자 정의 검증 에 해당 합 니 다.장 에서 상세 한 설명 과 대 비 를 할 것 입 니 다.여 기 는 잠시 설명 하지 않 습 니 다.
위 를 보고 jwt 가 간단 하 다 고 생각 하 시 죠?주로 두 편 이에 요.
jwt 만 들 기;jwt 검증;전체 코드 는 다음 과 같 습 니 다:
/// <summary>
/// Token , token
/// </summary>
public class TokenContext
{
/// <summary>
/// ,
/// </summary>
public static string securityKey = "GQDstclechengroberbojPOXOYg5MbeJ1XT0uFiwDVvVBrk";
/// <summary>
/// jwttoken,
/// </summary>
/// <param name="payLoad"></param>
/// <param name="header"></param>
/// <returns></returns>
public static string CreateToken(Dictionary<string, object> payLoad,int expiresMinute, Dictionary<string, object> header = null)
{
if (header == null)
{
header = new Dictionary<string, object>(new List<KeyValuePair<string, object>>() {
new KeyValuePair<string, object>("alg", "HS256"),
new KeyValuePair<string, object>("typ", "JWT")
});
}
// jwt ( )
var now = DateTime.UtcNow;
payLoad["nbf"] = ToUnixEpochDate( now);//
payLoad["exp"] = ToUnixEpochDate(now.Add(TimeSpan.FromMinutes(expiresMinute)));//
var encodedHeader = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(header));
var encodedPayload = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(payLoad));
var hs256 = new HMACSHA256(Encoding.ASCII.GetBytes(securityKey));
var encodedSignature = Base64UrlEncoder.Encode(hs256.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(encodedHeader, ".", encodedPayload))));
var encodedJwt = string.Concat(encodedHeader, ".", encodedPayload, ".", encodedSignature);
return encodedJwt;
}
/// <summary>
/// jwtToken, , HS256 , ,
/// CreateToken
/// </summary>
/// <param name="payLoad"></param>
/// <param name="expiresMinute"> </param>
/// <returns></returns>
public static string CreateTokenByHandler(Dictionary<string, object> payLoad, int expiresMinute)
{
var now = DateTime.UtcNow;
// Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims.
// You can add other claims here, if you want:
var claims = new List<Claim>();
foreach (var key in payLoad.Keys)
{
var tempClaim = new Claim(key, payLoad[key]?.ToString());
claims.Add(tempClaim);
}
// Create the JWT and write it to a string
var jwt = new JwtSecurityToken(
issuer: null,
audience: null,
claims: claims,
notBefore: now,
expires: now.Add(TimeSpan.FromMinutes(expiresMinute)),
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(securityKey)), SecurityAlgorithms.HmacSha256));
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
return encodedJwt;
}
/// <summary>
/// ,
/// </summary>
/// <param name="encodeJwt"></param>
/// <param name="validatePayLoad"> ; , , </param>
/// :payLoad["aud"]?.ToString() == "roberAuddience";
/// :
/// <returns></returns>
public static bool Validate(string encodeJwt,Func<Dictionary<string,object>,bool> validatePayLoad)
{
var success = true;
var jwtArr = encodeJwt.Split('.');
var header = JsonConvert.DeserializeObject<Dictionary<string, object>>(Base64UrlEncoder.Decode(jwtArr[0]));
var payLoad = JsonConvert.DeserializeObject<Dictionary<string, object>>(Base64UrlEncoder.Decode(jwtArr[1]));
var hs256 = new HMACSHA256(Encoding.ASCII.GetBytes(securityKey));
// ( )
success = success && string.Equals(jwtArr[2], Base64UrlEncoder.Encode(hs256.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(jwtArr[0], ".", jwtArr[1])))));
if (!success)
{
return success;//
}
// ( )
var now = ToUnixEpochDate(DateTime.UtcNow);
success = success && (now >= long.Parse(payLoad["nbf"].ToString()) && now < long.Parse(payLoad["exp"].ToString()));
//
success = success && validatePayLoad(payLoad);
return success;
}
/// <summary>
/// jwt payLoad
/// </summary>
/// <param name="encodeJwt"></param>
/// <returns></returns>
public static Dictionary<string ,object> GetPayLoad(string encodeJwt)
{
var jwtArr = encodeJwt.Split('.');
var payLoad = JsonConvert.DeserializeObject<Dictionary<string, object>>(Base64UrlEncoder.Decode(jwtArr[1]));
return payLoad;
}
public static long ToUnixEpochDate(DateTime date) =>
(long)Math.Round((date.ToUniversalTime() - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds);
}
이상 은 jwt 의 기본 내용 입 니 다.그것 은 정말 간단 합 니 다.aspnet core 의 각종 쓰기 방법 에 의 해 어 지 럽 히 지 마 세 요.jwt 와 관련 된 검증 이 라면 모두 위 에 있 는 것들 을 바탕 으로 합 니 다.다음 장 에 서 는 다음 과 같이 설명 할 것 이다.
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Shadows: Spooktober in Answer Set ProgrammingASP can be viewed as an extension of Prolog. Pure Prolog rules are based on definite clauses, that is Horn clauses which...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.