24시간 후에 만료되는 고유 토큰을 생성하는 방법은 무엇입니까?
사용자가 유효한지 확인하는 WCF 웹 서비스가 있습니다.
사용자가 유효한 경우 24시간 후에 만료되는 토큰을 생성합니다.
public bool authenticateUserManual(string userName, string password,string language,string token)
{
if (Membership.ValidateUser(userName,password))
{
//////////
string token = ????
//////////
return true;
}
else
{
return false;
}
}
고유한 값을 작성하고 작성 시간과 함께 데이터베이스에 저장하거나 나중에 디코딩하여 작성 시간을 확인할 수 있도록 토큰 내부에 작성 시간을 저장하는 두 가지 방법이 있습니다.
고유 토큰을 만드는 방법
string token = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
타임스탬프가 포함된 고유 토큰을 만드는 기본 예:
byte[] time = BitConverter.GetBytes(DateTime.UtcNow.ToBinary());
byte[] key = Guid.NewGuid().ToByteArray();
string token = Convert.ToBase64String(time.Concat(key).ToArray());
토큰을 디코딩하여 생성 시간을 얻는 방법
byte[] data = Convert.FromBase64String(token);
DateTime when = DateTime.FromBinary(BitConverter.ToInt64(data, 0));
if (when < DateTime.UtcNow.AddHours(-24)) {
// too old
}
참고: 보안을 위해 타임스탬프가 있는 토큰이 필요한 경우 암호화해야 합니다.그렇지 않으면 사용자가 포함된 내용을 파악하여 잘못된 토큰을 만들 수 있습니다.
저는 구파의 답변이 마음에 들고 코멘트할 수 없기 때문에 우딜의 질문에 대한 답변을 여기서 제공하겠습니다.
나는 비슷한 것이 필요했지만, 나는 내 토큰에 특정한 논리를 원했고, 나는 다음을 원했습니다.
- 토큰 만료 보기
- 마스크 검증을 위해 GUID 사용(글로벌 응용 프로그램 GUID 또는 사용자 GUID)
- 토큰이 내가 작성한 목적에 맞게 제공되었는지 확인합니다(재사용 안 함...)
- 토큰을 보내는 사용자가 토큰의 유효성을 검사하는 사용자인지 확인
이제 1-3 지점은 길이가 고정되어 있어서 쉬웠습니다. 여기 제 코드가 있습니다.
토큰을 생성하는 코드는 다음과 같습니다.
public string GenerateToken(string reason, MyUser user)
{
byte[] _time = BitConverter.GetBytes(DateTime.UtcNow.ToBinary());
byte[] _key = Guid.Parse(user.SecurityStamp).ToByteArray();
byte[] _Id = GetBytes(user.Id.ToString());
byte[] _reason = GetBytes(reason);
byte[] data = new byte[_time.Length + _key.Length + _reason.Length+_Id.Length];
System.Buffer.BlockCopy(_time, 0, data, 0, _time.Length);
System.Buffer.BlockCopy(_key , 0, data, _time.Length, _key.Length);
System.Buffer.BlockCopy(_reason, 0, data, _time.Length + _key.Length, _reason.Length);
System.Buffer.BlockCopy(_Id, 0, data, _time.Length + _key.Length + _reason.Length, _Id.Length);
return Convert.ToBase64String(data.ToArray());
}
생성된 토큰 문자열을 가져와서 유효성을 검사하는 내 코드는 다음과 같습니다.
public TokenValidation ValidateToken(string reason, MyUser user, string token)
{
var result = new TokenValidation();
byte[] data = Convert.FromBase64String(token);
byte[] _time = data.Take(8).ToArray();
byte[] _key = data.Skip(8).Take(16).ToArray();
byte[] _reason = data.Skip(24).Take(2).ToArray();
byte[] _Id = data.Skip(26).ToArray();
DateTime when = DateTime.FromBinary(BitConverter.ToInt64(_time, 0));
if (when < DateTime.UtcNow.AddHours(-24))
{
result.Errors.Add( TokenValidationStatus.Expired);
}
Guid gKey = new Guid(_key);
if (gKey.ToString() != user.SecurityStamp)
{
result.Errors.Add(TokenValidationStatus.WrongGuid);
}
if (reason != GetString(_reason))
{
result.Errors.Add(TokenValidationStatus.WrongPurpose);
}
if (user.Id.ToString() != GetString(_Id))
{
result.Errors.Add(TokenValidationStatus.WrongUser);
}
return result;
}
private static string GetString(byte[] reason) => Encoding.ASCII.GetString(reason);
private static byte[] GetBytes(string reason) => Encoding.ASCII.GetBytes(reason);
TokenValidation 클래스는 다음과 같습니다.
public class TokenValidation
{
public bool Validated { get { return Errors.Count == 0; } }
public readonly List<TokenValidationStatus> Errors = new List<TokenValidationStatus>();
}
public enum TokenValidationStatus
{
Expired,
WrongUser,
WrongPurpose,
WrongGuid
}
이제 토큰을 24시간 정도 목록에 보관할 필요 없이 쉽게 유효성을 확인할 수 있습니다.다음은 나의 Good-Case Unit 테스트입니다.
private const string ResetPasswordTokenPurpose = "RP";
private const string ConfirmEmailTokenPurpose = "EC";//change here change bit length for reason section (2 per char)
[TestMethod]
public void GenerateTokenTest()
{
MyUser user = CreateTestUser("name");
user.Id = 123;
user.SecurityStamp = Guid.NewGuid().ToString();
var token = sit.GenerateToken(ConfirmEmailTokenPurpose, user);
var validation = sit.ValidateToken(ConfirmEmailTokenPurpose, user, token);
Assert.IsTrue(validation.Validated,"Token validated for user 123");
}
다른 비즈니스 사례에 맞게 코드를 쉽게 조정할 수 있습니다.
해피 코딩
월터.
사용하다Dictionary<string, DateTime>
토큰을 타임스탬프와 함께 저장하는 방법:
static Dictionary<string, DateTime> dic = new Dictionary<string, DateTime>();
새 토큰을 만들 때마다 타임스탬프가 있는 토큰 추가:
dic.Add("yourToken", DateTime.Now);
만료된 토큰을 dic에서 제거하기 위해 실행 중인 타이머가 있습니다.
timer = new Timer(1000*60); //assume run in 1 minute
timer.Elapsed += timer_Elapsed;
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
var expiredTokens = dic.Where(p => p.Value.AddDays(1) <= DateTime.Now)
.Select(p => p.Key);
foreach (var key in expiredTokens)
dic.Remove(key);
}
따라서 토큰을 인증할 때는 토큰이 dic에 존재하는지 여부만 확인하면 됩니다.
첫 번째 등록을 위해 작성하는 동안 토큰을 저장해야 합니다.로그인 테이블에서 데이터를 검색할 때 입력한 날짜가 1일(24시간) 이상이면 현재 날짜로 구분해야 합니다. 토큰이 만료된 것처럼 메시지를 표시해야 합니다.
키를 생성하려면 여기를 참조하십시오.
저도 비슷하지만 약간 다른 문제가 있었습니다.저는 다른 서버에서 2분 이내에 사용할 수 있는 토큰이 필요했습니다.서버 A와 서버 B는 개인 키를 공유합니다.물론 사용자 브라우저에서는 토큰이 공개되어 있습니다.
A 웹 서버는 날짜가 포함된 문자열을 만듭니다.그런 다음 끈을 해싱합니다.브라우저의 사용자가 토큰을 사용합니다.서버 B가 토큰을 수신하면 동일한 해시를 수행하고 결과를 비교합니다.서버 A와 서버 B는 c# 코드를 실행합니다.
문제는 비슷하지만 같지는 않지만, 어쨌든 코드는 누군가를 도울 수 있습니다.
public class TokenHelper
{
private static byte[] GetHash(string inputString)
{
using (HashAlgorithm algorithm = MD5.Create())
return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
}
private static string GetHashString(string inputString)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in GetHash(inputString))
sb.Append(b.ToString("X2"));
return sb.ToString();
}
public static Guid GetTokenForGuest(EnumWebsiteName website, string privateKey)
{
string datetime = DateTime.Now.ToString("dd/MM/yyyy hh:mm");
var hashString = GetHashString($"{datetime}|{website}|{privateKey}");
return new Guid(hashString);
}
public static bool CheckTokenForGuest(Guid token, EnumWebsiteName website, string privateKey)
{
string datetime = DateTime.Now.ToString("dd/MM/yyyy hh:mm");
var hashString = GetHashString($"{datetime}|{website}|{privateKey}");
var test1 = new Guid(hashString);
if (test1.CompareTo(token)==0) {
return true;
}
string datetime2 = DateTime.Now.AddMinutes(-1).ToString("dd/MM/yyyy hh:mm");
var hashString2 = GetHashString($"{datetime2}|{website}|{privateKey}");
var test2 = new Guid(hashString2);
if (test2.CompareTo(token) == 0)
{
return true;
}
return false;
}
}
이렇게 하면 토큰은 최대 24시간까지 존재합니다.여기 24시간까지 유효한 토큰을 생성하는 코드가 있습니다. 이 코드는 우리가 사용하지만 나는 그것을 구성하지 않았습니다.
public static string GenerateToken()
{
int month = DateTime.Now.Month;
int day = DateTime.Now.Day;
string token = ((day * 100 + month) * 700 + day * 13).ToString();
return token;
}
언급URL : https://stackoverflow.com/questions/14643735/how-to-generate-a-unique-token-which-expires-after-24-hours
'programing' 카테고리의 다른 글
Windows에서 tkinter를 pip 또는 easy_install하는 방법 (0) | 2023.08.24 |
---|---|
엑셀 서버측은 어떻게 사용하나요? (0) | 2023.08.24 |
도커 작성 - 여러 컨테이너 간에 명명된 볼륨 공유 (0) | 2023.08.24 |
SQL 마지막 날짜 시간 레코드 가져오기 (0) | 2023.08.24 |
pycharm 탭을 공백으로 자동 변환 (0) | 2023.08.24 |