跨伺服器交換資料,用JWT就對了,安全可靠。
認識JWT,請參考以下文章:
有了基本的認識後,HS開頭的簽章方式是用secret(密語),把secret給其他伺服器就能驗證簽章,本案例使用asp.net,請參考以下Code(要用NuGet下載System.JdentityModel.Tokens.Jwt)。
// header
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("db3OIsj+BXE9NZDy0t8W3TcNekrF+2d/1sFnWG4HnV8TZY30iTOdtVWJG8abWvB1GlOgJuQZdcF2Luqm/hccMw=="));
var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var header = new JwtHeader(signingCredentials);
// payload
IReadOnlyDictionary<string, string> payloadContents = new Dictionary<string, string>
{
{ "username","Mika" },
{ "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
{ "exp", DateTimeOffset.UtcNow.AddMinutes(5).ToUnixTimeSeconds()},
};
var payloadClaims = payloadContents.Select(c => new Claim(c.Key, c.Value));
var payload = new JwtPayload(payloadClaims);
// signature
var securityToken = new JwtSecurityToken(header, payload);
// return
var tokenHandler = new JwtSecurityTokenHandler();
return tokenHandler.WriteToken(securityToken);
但是secret難保不會洩漏,所以更安全的方式就是用非對稱式金鑰(RS開頭),建議使用NuGet下載jose-jwt與BouncyCastle,會簡單很多,首先要製作一對非對稱式金鑰,公鑰可以任意給人,但私鑰只能安全的放在Server上,使用指令如下。
openssl genrsa -out privateKey.pem 2048
openssl rsa -in privateKey.pem -pubout -out publicKey.pem
如果找不到Openssl指令,可以自己上網抓並安裝,但是其實一般有使用到Git,就已經安裝在電腦中了,Windows可以在以下位置找到 C:\Program Files\Git\usr\bin\
接著是Code的部分,可以參考以下,如果要驗證,產生的token對不對可以至官網驗證 https://jwt.io/ 。
public string Test()
{
var claims = new List<Claim>();
claims.Add(new Claim("username", "Mika"));
claims.Add(new Claim("iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()));
claims.Add(new Claim("exp", DateTimeOffset.UtcNow.AddMinutes(5).ToUnixTimeSeconds().ToString()));
var token = CreateToken(claims);
return token;
}
public static string CreateToken(List<Claim> claims)
{
string privateRsaKey = File.ReadAllText(Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, @"App_Data\JwtKey\private_Key.pem"));
RSAParameters rsaParams;
using (var tr = new StringReader(privateRsaKey))
{
var pemReader = new PemReader(tr);
var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
if (keyPair == null)
{
throw new Exception("Could not read RSA private key");
}
var privateRsaParams = keyPair.Private as RsaPrivateCrtKeyParameters;
rsaParams = DotNetUtilities.ToRSAParameters(privateRsaParams);
}
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(rsaParams);
Dictionary<string, object> payload = claims.ToDictionary(k => k.Type, v => (object)v.Value);
return Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);
}
}
參考網址: