在ASP.NET中,使用JWT(JSON Web Token)進行身份驗證時,令牌撤銷是一個重要的安全措施。以下是實現JWT令牌撤銷的幾種方法:
將JWT的過期時間設置得較短,例如幾分鐘或幾小時。這樣即使Token被泄露,攻擊者也只能在有限的時間內使用它。
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes("your_secret_key");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, "John Doe"),
new Claim(ClaimTypes.Email, "john.doe@example.com")
}),
Expires = DateTime.UtcNow.AddMinutes(30),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
引入一個刷新Token的概念,用于在訪問Token過期后獲取新的訪問Token。刷新Token應該存儲在安全的地方,例如HttpOnly Cookie。
var refreshTokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes("your_refresh_secret_key");
var refreshTokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, "John Doe"),
new Claim(ClaimTypes.Email, "john.doe@example.com")
}),
Expires = DateTime.UtcNow.AddDays(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var refreshToken = refreshTokenHandler.CreateToken(refreshTokenDescriptor);
var refreshTokenString = refreshTokenHandler.WriteToken(refreshToken);
維護一個黑名單,存儲所有需要撤銷的Token。每次驗證Token時,首先檢查該Token是否在黑名單中。
public class JwtTokenRevocationService
{
private readonly IList<string> _revokedTokens = new List<string>();
public void RevokeToken(string token)
{
_revokedTokens.Add(token);
}
public bool IsTokenRevoked(string token)
{
return _revokedTokens.Contains(token);
}
}
在驗證Token時,使用JwtTokenRevocationService
檢查Token是否被撤銷:
public class JwtTokenValidator
{
private readonly JwtTokenRevocationService _revocationService;
public JwtTokenValidator(JwtTokenRevocationService revocationService)
{
_revocationService = revocationService;
}
public bool ValidateToken(string token)
{
if (_revocationService.IsTokenRevoked(token))
{
return false;
}
// 其他驗證邏輯
var tokenHandler = new JwtSecurityTokenHandler();
try
{
var validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_secret_key")),
ValidateIssuer = false,
ValidateAudience = false
};
var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
return principal != null;
}
catch (Exception ex)
{
// 處理異常
return false;
}
}
}
將需要撤銷的Token存儲在數據庫或緩存中,以便快速查找和驗證。
public class JwtTokenRevocationService
{
private readonly IDatabaseContext _databaseContext;
public JwtTokenRevocationService(IDatabaseContext databaseContext)
{
_databaseContext = databaseContext;
}
public void RevokeToken(string token)
{
_databaseContext.RevokedTokens.Add(new RevokedToken { Token = token, Expiry = DateTime.UtcNow });
_databaseContext.SaveChanges();
}
public bool IsTokenRevoked(string token)
{
return _databaseContext.RevokedTokens.Any(rt => rt.Token == token);
}
}
以上方法各有優缺點,選擇哪種方法取決于具體的應用場景和安全需求。短期Token、刷新Token和黑名單機制是比較常見的解決方案,而使用數據庫或緩存則可以提供更高級別的安全性。