- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试为 Windows 上的 C# .NET 编写自定义 JWT token 生成器,以便在 Google Firebase 中使用。我从 StackOverflow 上的几个不同地方提取的源代码(我试图重新发现它们,这样我就可以归功于原作者并问几个额外的问题),所以它有点像大杂烩。
在大多数情况下它似乎可以工作,但它似乎没有按预期生成有效的 (firebase) token 。这可能完全是因为我一开始不了解它应该如何工作,但如果我能从这里得到第二双世界级的优秀工程师的眼睛来指出我做错了什么并让事情正常进行,那就太好了。
代码如下:
// Token generator setup
using Newtonsoft.Json;
using System;
using System.IO;
using System.Web;
using System.Web.Configuration;
namespace myapp.Utils
{
public class GoogleJsonWebToken
{
public static string Encode(string uid)
{
var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var issueTime = DateTime.Now;
var iat = (int)issueTime.Subtract(utc0).TotalSeconds;
var exp = (int)issueTime.AddMinutes(60).Subtract(utc0).TotalSeconds;
var firebaseInfPath = HttpContext.Current.Server.MapPath(WebConfigurationManager.AppSettings["firebaseInf"]);
var firebaseInfJsonContent = File.ReadAllText(firebaseInfPath);
var firebaseInf = JsonConvert.DeserializeObject<dynamic>(firebaseInfJsonContent);
var privateKey = (string)firebaseInf.private_key;
var payload = new
{
iss = firebaseInf.client_email,
scope = firebaseInf.client_email,
aud = "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
exp = exp,
uid = uid,
iat = iat,
claims = new { premium_account = true }
};
return myapp.Utils.JsonWebToken.Encode(payload, privateKey, JwtHashAlgorithm.RS256);
}
}
}
JWT哈希算法代码如下:
// JsonWebToken.cs
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
namespace myapp.Utils
{
public enum JwtHashAlgorithm
{
RS256,
HS384,
HS512
}
public class JsonWebToken
{
private static Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>> HashAlgorithms;
static JsonWebToken()
{
HashAlgorithms = new Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>>
{
{ JwtHashAlgorithm.RS256, (key, value) => { using (var sha = new HMACSHA256(key)) { return sha.ComputeHash(value); } } },
{ JwtHashAlgorithm.HS384, (key, value) => { using (var sha = new HMACSHA384(key)) { return sha.ComputeHash(value); } } },
{ JwtHashAlgorithm.HS512, (key, value) => { using (var sha = new HMACSHA512(key)) { return sha.ComputeHash(value); } } }
};
}
public static string Encode(object payload, string key, JwtHashAlgorithm algorithm)
{
var keyBytes = Encoding.UTF8.GetBytes(key);
return Encode(payload, keyBytes, algorithm);
}
public static string Encode(object payload, byte[] keyBytes, JwtHashAlgorithm algorithm)
{
var segments = new List<string>();
var header = new { alg = algorithm.ToString(), typ = "JWT" };
byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None));
byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None));
//byte[] payloadBytes = Encoding.UTF8.GetBytes(@"{"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com","scope":"https://www.googleapis.com/auth/prediction","aud":"https://accounts.google.com/o/oauth2/token","exp":1328554385,"iat":1328550785}");
segments.Add(Base64UrlEncode(headerBytes));
segments.Add(Base64UrlEncode(payloadBytes));
var stringToSign = string.Join(".", segments.ToArray());
var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
byte[] signature = HashAlgorithms[algorithm](keyBytes, bytesToSign);
segments.Add(Base64UrlEncode(signature));
return string.Join(".", segments.ToArray());
}
public static string Decode(string token, string key)
{
return Decode(token, key, true);
}
public static string Decode(string token, string key, bool verify)
{
var parts = token.Split('.');
var header = parts[0];
var payload = parts[1];
byte[] crypto = Base64UrlDecode(parts[2]);
var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));
var headerData = JObject.Parse(headerJson);
var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload));
var payloadData = JObject.Parse(payloadJson);
if (verify)
{
var bytesToSign = Encoding.UTF8.GetBytes(string.Concat(header, ".", payload));
var keyBytes = Encoding.UTF8.GetBytes(key);
var algorithm = (string)headerData["alg"];
var signature = HashAlgorithms[GetHashAlgorithm(algorithm)](keyBytes, bytesToSign);
var decodedCrypto = Convert.ToBase64String(crypto);
var decodedSignature = Convert.ToBase64String(signature);
if (decodedCrypto != decodedSignature)
{
throw new ApplicationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature));
}
}
return payloadData.ToString();
}
private static JwtHashAlgorithm GetHashAlgorithm(string algorithm)
{
switch (algorithm)
{
case "RS256": return JwtHashAlgorithm.RS256;
case "HS384": return JwtHashAlgorithm.HS384;
case "HS512": return JwtHashAlgorithm.HS512;
default: throw new InvalidOperationException("Algorithm not supported.");
}
}
// from JWT spec
private static string Base64UrlEncode(byte[] input)
{
var output = Convert.ToBase64String(input);
output = output.Split('=')[0]; // Remove any trailing '='s
output = output.Replace('+', '-'); // 62nd char of encoding
output = output.Replace('/', '_'); // 63rd char of encoding
return output;
}
// from JWT spec
private static byte[] Base64UrlDecode(string input)
{
var output = input;
output = output.Replace('-', '+'); // 62nd char of encoding
output = output.Replace('_', '/'); // 63rd char of encoding
switch (output.Length % 4) // Pad with trailing '='s
{
case 0: break; // No pad chars in this case
case 2: output += "=="; break; // Two pad chars
case 3: output += "="; break; // One pad char
default: throw new System.Exception("Illegal base64url string!");
}
var converted = Convert.FromBase64String(output); // Standard base64 decoder
return converted;
}
}
}
最佳答案
token 被拒绝的原因是因为它使用错误的算法签名:您使用的是 HMAC-SHA256(对称 key 加密算法),而正确的 token 使用 RSA-SHA256(非对称或公钥/私钥)算法)。您可以在示例 token 的 header 中看到这一点:"alg": "RS256"
我建议使用 System.IdentityModel.Tokens.Jwt
中的类来大大简化您的代码:
public class GoogleJsonWebToken
{
public static string Encode(string uid)
{
var firebaseInfPath = HttpContext.Current.Server.MapPath(WebConfigurationManager.AppSettings["firebaseInf"]);
var firebaseInfJsonContent = File.ReadAllText(firebaseInfPath);
var firebaseInf = JsonConvert.DeserializeObject<dynamic>(firebaseInfJsonContent);
// NOTE: Replace this with your actual RSA public/private keypair!
var provider = new RSACryptoServiceProvider(2048);
var parameters = provider.ExportParameters(true);
// Build the credentials used to sign the JWT
var signingKey = new RsaSecurityKey(parameters);
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256);
// Create a collection of optional claims
var now = DateTimeOffset.UtcNow;
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, firebaseInf.client_email),
new Claim(JwtRegisteredClaimNames.Iat, now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64),
new Claim("uid", uid, ClaimValueTypes.String),
new Claim("premium_account", "true", ClaimValueTypes.Boolean)
};
// Create and sign the JWT, and write it to a string
var jwt = new JwtSecurityToken(
issuer: firebaseInf.client_email,
audience: "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
claims: claims,
expires: now.AddMinutes(60).DateTime,
signingCredentials: signingCredentials);
return new JwtSecurityTokenHandler().WriteToken(jwt);
}
}
使用虚拟 key ,此代码创建一个与您的示例 token 的 header 和有效负载模式相匹配的 token :
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmaXJlYmFzZS1hdXRoLXRva2VuQHNheWVyLWNoYXQuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJpYXQiOjE0Njc4MzgwODUsInVpZCI6IjUyMTQiLCJwcmVtaXVtX2FjY291bnQiOnRydWUsImV4cCI6MTQ2Nzg2Njg4NSwiaXNzIjoiZmlyZWJhc2UtYXV0aC10b2tlbkBzYXllci1jaGF0LmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYXVkIjoiaHR0cHM6Ly9pZGVudGl0eXRvb2xraXQuZ29vZ2xlYXBpcy5jb20vZ29vZ2xlLmlkZW50aXR5LmlkZW50aXR5dG9vbGtpdC52MS5JZGVudGl0eVRvb2xraXQifQ.yMSGRpm4r3mPqiA9KnKVILVb8jT2Vbqcy4gvoLIugXnzLlw45F-GepAaBJK-j0-EN34WLsiLiLCRDJwW15TMasbrB1ZX3H4zd1by2GjZ1VmcUL8LITglICvs8CXkamjPjHeQUc4q--jhveKmTby8WHsH4b-HeiYoVl8JhxrAF13buNbiTq66dfvkl9q6mnyuKS_oyFB6_9WNphzHRa2BdJ51olq4qQsUNZ-nzOe4moHHjxpEzQfQpIe-QMJHdqojp9ukOW5eTMhFkQRPs3Bme4jpxIHPknC9j8YRvx_i0FbEJ8qAY2ujWcq80aC6YBKox55iP-AwfX_mEV7Tz14PBQ
您应该能够输入公钥/私钥对并使用上述代码生成有效的 JWT。
关于c# - 为 Firebase 生成 JWT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38230779/
1. JWT 简介 JSON Web Token(JWT) 是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。该信息可以被验证和信
关于JWT(json web token)的一些问题: 可以在手机上使用吗? 在我看来,它适用于移动设备,但它是否是一个很好的身份验证解决方案?如果不是,还有哪些其他解决方案可用于移动应用程序和服务器
我无法清楚地掌握 JWT 是如何工作的,尤其是。签名部分。 一旦客户端提交正确的用户名和密码,身份验证服务器就会创建一个 JWT token ,其中包含 header 、有效负载/声明和签名。 问题
我正在通过 jwt.io(在调试器部分)解码 JWT token 以查看标题、有效负载。令人惊讶的是,它还验证了,我可以看到它(jwt.io 调试器)也能够检索公钥。 所以我的问题是:JWT toke
我尝试使用 validate-jwt 策略限制使用 JWT token 对 REST API 的访问。以前从来没有这样做过。 这是我的入站策略(取自简单 token 验证here):
我们有一个微服务架构,使用 JWT 在服务之间进行身份验证。我希望轻松地从 JWT 中获取更多字段。目前实际上只有权限由 Spring Security 直接公开。 我们的边缘服务/API 网关创建以
我正在尝试在 .NET 中生成 JWT token 。起初,我尝试使用“System.IdentityModel.Tokens.Jwt”,但它在 token 验证期间引起了问题,所以我切换到“jose
我已经阅读了很多关于 stackOverflow 和 jwt 文档的问题。据我了解,现在我应该如何计算 token : header = { "alg": "HS256", "typ": "J
我想知道我可以设置的 JWT token 到期的最大值是多少。 谢谢! 最佳答案 没有关于过期时间的规定。它主要取决于使用 token 的上下文。 RFC7519 section 4 : The se
我在子域上托管了单独的身份验证应用程序和多个 spa 应用程序,我想将生成的 JWT token (当用户从身份验证应用程序登录时生成)从身份验证应用程序共享到子域下托管的其他应用程序。我怎样才能
据我所知,验证 JWT 签名是一个直接的过程。但是当我使用一些在线工具为我执行此操作时,它不匹配。如何在不使用 JWT 库的情况下手动验证 JWT 签名?我需要一种快速方法(使用可用的在线工具)来演示
我的 JSON 网络 token (JWT): eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6InU0T2ZORlBId0VCb3NIanRyYXVPYlY4
我是 JWT 的新手。我对 JWT 进行了一些研究,并了解到它的框架是“header.claims.signature”。 考虑一个简单的场景,如下所示: 客户通过身份验证 客户可能具有(一个或多个)
我需要知道的最大长度 JSON Web Token (JWT) 在规范中没有相关信息。难道,长度没有限制? 最佳答案 我也一直在努力寻找这个。 我想说 - 尝试确保它低于 7kb。 虽然 JWT 在规
我看到 JWT token 由 A-Z、a-Z、0-9 和特殊字符 - 和 _ 组成。我想知道 JWT token 中允许的字符列表? 最佳答案 来自JWT introduction :“输出是三个用
我正在使用 Jhipster 创建一个应用程序。为此,我想使用 Keycloak 身份验证服务器。但是,一旦我登录,就会收到以下消息:Statut : Internal Server Error (内
我正在使用 Jhipster 创建一个应用程序。为此,我想使用 Keycloak 身份验证服务器。但是,一旦我登录,就会收到以下消息:Statut : Internal Server Error (内
我在我的网站上使用 MEAN 堆栈,用户可以在其中将带有玩家信息的事件(2-4/事件)添加到购物车。有时他们会购买多个事件。我希望此信息不会受到用户操纵(如果他们使用控制台,则在结帐前更改信息),并且
一个 JSON Web token (JWT) 被分成三个 Base-64 编码的部分,这些部分由句点 (“.”) 连接起来。前两部分对 JSON 对象进行编码,第一部分是详细说明签名和散列算法的 h
我正在使用 django rest 框架 JWT 库 http://getblimp.github.io/django-rest-framework-jwt/ JWT token 过期有两个设置 JW
我是一名优秀的程序员,十分优秀!