.net mvc JWT 令牌更改 utf-8 字符
.net mvc JWT token changes utf-8 chars
我有一个用于身份验证的 JWT 令牌。在我的数据库中,我有一个包含 firstName: Tim
和 lastName: Børge
的 customerUser,但是在我的代码从我的数据库中读取并创建 JWT 之后,令牌中的结构使它成为
"firstName":"Tim"
"lastName":"Børge"
这是我存储在本地存储中的内容。当我在我的网页上打印出用户名时,这是一个问题。我检查了我的源代码,一切似乎都归结为这一行:
try
{
var user = Membership.GetUser(username, true);
var jwt = GetJwtFromMembershipAccountId((int)(user?.ProviderUserKey??0));
return this.Request.CreateResponse(
HttpStatusCode.OK,
jwt,
new TextMediaTypeFormatter()
);
}
catch
{
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Error logging in!");
}
直到那时我的数据包含我的 UTF-8 字符。有什么想法吗?
编辑
智威汤逊:
eyJpc3MiOiJLb2xsZWN0by5pbyA0LjAiLCJpYXQiOjE1NzQzMzA3MTguMCwiZXhwIjoxNTc1NTQwMzE4LjAsInN1YmplY3QiOiJtYW5kQG5pcmFzLmRrIiwiYXVkIjoiS29sbGVjdG8uaW8gNC4wIiwidHlwIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJjdXN0b21lcl9pZCI6IjU5YTkyYWFmYWU3YTcxMWIzODkwMTc2MSIsImFwaV9rZXkiOiI1Y2M4MTE2MDdmYTlkNjg3ZDI2NTkyZmUiLCJjdXN0b21lclVzZXJfaWQiOiI1ZDljM2FmNGY3MThiNDRlOTBiYmJkMzMiLCJhY2NvdW50X2lkIjoxMDQ0LCJlbWFpbCI6Im1hbmRAbmlyYXMuZGsiLCJyb2xlcyI6WyJNb2JpbGVVc2VyIiwiTmlyYXNBZG1pbiIsIkFkbWluIl0sImdpdmVuX25hbWUiOiJNYWRzIiwiZmFtaWx5X25hbWUiOiJCw7h0a2VyIEFuZGVyc2VuIn0.OMx8VZesjvd92ZrfoSpAdICvl9bGP2UTQrFjYWDWpKY
我的函数:
private string GetJwtFromMembershipAccountId(int accountId)
{
var account = DBHelper.membershipAccountCollection.FindOneById(accountId);
var customerUser = DBHelper.customerUserCollection.AsQueryable().FirstOrDefault(x => x.UserId == accountId);
var customer = DBHelper.customerCollection.AsQueryable().FirstOrDefault(x => x.CustomerId == customerUser.CustomerId);
var timeSinceEpoch = (DateTime.UtcNow - JwtValidator.UnixEpoch);
var expirationTime = timeSinceEpoch.Add(new TimeSpan(14, 0, 0, 0)); /* 14 days from now */
var kollectoAppHeader = WebConfigurationManager.AppSettings["App.Name"] + " " + WebConfigurationManager.AppSettings["App.Version"];
//var kollectoAppHeader = "SmartInspect";
var headers = new Dictionary<string, object>
{
{ "iss", kollectoAppHeader },
{ "iat", Math.Round(timeSinceEpoch.TotalSeconds) },
{ "exp", Math.Round(expirationTime.TotalSeconds) },
{ "subject", account.Username },
{ "aud", kollectoAppHeader }
};
var payload = new Dictionary<string, object>
{
{ "customer_id", customer.CustomerId.ToString() },
{ "api_key", customer.ApiKey.ToString() },
{ "customerUser_id", customerUser.CustomerUserId.ToString() },
{ "account_id", account.AccountId },
{ "email", customerUser.Email },
{ "roles", account.Roles },
{ "given_name", customerUser?.FirstName ?? string.Empty },
{ "family_name", customerUser?.LastName ?? string.Empty }
};
var algorithm = new HMACSHA256Algorithm();
var serializer = new JsonNetSerializer();
var urlEncoder = new JwtBase64UrlEncoder();
var encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
return encoder.Encode(headers, payload, _ssoJwtPsk);
}
令牌中的编码没有问题!
您的 JWT 编码方法正确地以 base64url
编码对您的 UTF-8 字符进行编码,并且 jwt.io 正确显示解码后的 UTF-8 字符。
您的客户端和 jstoolset.com/jwt 将解码后的字符解释为 ISO-8859-1 或 Windows-1252 字符集。
很容易证明编码是正确的
出于说明目的,我制作了一个更简单的令牌,其中包含丹麦语 UTF-8 字符 ø
作为有效负载:
eyJhbGciOiJIUzI1NiJ9.eyLDuCI6IjEifQ.RR8UPmBsMqH-huDVtfRWK4FSrmBuNEDtoMPxE7hJWt8
有效载荷是:
{"ø":"1"}
如果您获取有效负载 eyLDuCI6IjEifQ
,您首先必须将其转换回二进制。 base64 字符 e
代表 6 位 011110
,y
代表 110010
等等(完整编码请查看 Wikipedia base64 table) .现在我们必须将它转换回 8 位,所以取前 6 位加上下一个字符的前 2 位,将得到 01111011
或十六进制 7B
,[= 的 ASCII 值19=] 后跟 00100010
(十六进制 22
,ASCII "
)等等。
第一个字符的完全转换产生以下十六进制代码:
7B 22 C3 B8 22
在 UTF-8 encoder/decoder 上你可以看到 ø
有 UTF-8 代码 C3 B8
,所有其他代码都可以在任何常见的 ASCII-table 上轻松找到:
{ " ø "
所以你看,令牌包含正确编码的 UTF-8 字符。将结果解释为 UTF-8 而不是任何其他字符集取决于您的客户。
我有一个用于身份验证的 JWT 令牌。在我的数据库中,我有一个包含 firstName: Tim
和 lastName: Børge
的 customerUser,但是在我的代码从我的数据库中读取并创建 JWT 之后,令牌中的结构使它成为
"firstName":"Tim"
"lastName":"Børge"
这是我存储在本地存储中的内容。当我在我的网页上打印出用户名时,这是一个问题。我检查了我的源代码,一切似乎都归结为这一行:
try
{
var user = Membership.GetUser(username, true);
var jwt = GetJwtFromMembershipAccountId((int)(user?.ProviderUserKey??0));
return this.Request.CreateResponse(
HttpStatusCode.OK,
jwt,
new TextMediaTypeFormatter()
);
}
catch
{
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Error logging in!");
}
直到那时我的数据包含我的 UTF-8 字符。有什么想法吗?
编辑 智威汤逊:
eyJpc3MiOiJLb2xsZWN0by5pbyA0LjAiLCJpYXQiOjE1NzQzMzA3MTguMCwiZXhwIjoxNTc1NTQwMzE4LjAsInN1YmplY3QiOiJtYW5kQG5pcmFzLmRrIiwiYXVkIjoiS29sbGVjdG8uaW8gNC4wIiwidHlwIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJjdXN0b21lcl9pZCI6IjU5YTkyYWFmYWU3YTcxMWIzODkwMTc2MSIsImFwaV9rZXkiOiI1Y2M4MTE2MDdmYTlkNjg3ZDI2NTkyZmUiLCJjdXN0b21lclVzZXJfaWQiOiI1ZDljM2FmNGY3MThiNDRlOTBiYmJkMzMiLCJhY2NvdW50X2lkIjoxMDQ0LCJlbWFpbCI6Im1hbmRAbmlyYXMuZGsiLCJyb2xlcyI6WyJNb2JpbGVVc2VyIiwiTmlyYXNBZG1pbiIsIkFkbWluIl0sImdpdmVuX25hbWUiOiJNYWRzIiwiZmFtaWx5X25hbWUiOiJCw7h0a2VyIEFuZGVyc2VuIn0.OMx8VZesjvd92ZrfoSpAdICvl9bGP2UTQrFjYWDWpKY
我的函数:
private string GetJwtFromMembershipAccountId(int accountId)
{
var account = DBHelper.membershipAccountCollection.FindOneById(accountId);
var customerUser = DBHelper.customerUserCollection.AsQueryable().FirstOrDefault(x => x.UserId == accountId);
var customer = DBHelper.customerCollection.AsQueryable().FirstOrDefault(x => x.CustomerId == customerUser.CustomerId);
var timeSinceEpoch = (DateTime.UtcNow - JwtValidator.UnixEpoch);
var expirationTime = timeSinceEpoch.Add(new TimeSpan(14, 0, 0, 0)); /* 14 days from now */
var kollectoAppHeader = WebConfigurationManager.AppSettings["App.Name"] + " " + WebConfigurationManager.AppSettings["App.Version"];
//var kollectoAppHeader = "SmartInspect";
var headers = new Dictionary<string, object>
{
{ "iss", kollectoAppHeader },
{ "iat", Math.Round(timeSinceEpoch.TotalSeconds) },
{ "exp", Math.Round(expirationTime.TotalSeconds) },
{ "subject", account.Username },
{ "aud", kollectoAppHeader }
};
var payload = new Dictionary<string, object>
{
{ "customer_id", customer.CustomerId.ToString() },
{ "api_key", customer.ApiKey.ToString() },
{ "customerUser_id", customerUser.CustomerUserId.ToString() },
{ "account_id", account.AccountId },
{ "email", customerUser.Email },
{ "roles", account.Roles },
{ "given_name", customerUser?.FirstName ?? string.Empty },
{ "family_name", customerUser?.LastName ?? string.Empty }
};
var algorithm = new HMACSHA256Algorithm();
var serializer = new JsonNetSerializer();
var urlEncoder = new JwtBase64UrlEncoder();
var encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
return encoder.Encode(headers, payload, _ssoJwtPsk);
}
令牌中的编码没有问题!
您的 JWT 编码方法正确地以 base64url
编码对您的 UTF-8 字符进行编码,并且 jwt.io 正确显示解码后的 UTF-8 字符。
您的客户端和 jstoolset.com/jwt 将解码后的字符解释为 ISO-8859-1 或 Windows-1252 字符集。
很容易证明编码是正确的
出于说明目的,我制作了一个更简单的令牌,其中包含丹麦语 UTF-8 字符 ø
作为有效负载:
eyJhbGciOiJIUzI1NiJ9.eyLDuCI6IjEifQ.RR8UPmBsMqH-huDVtfRWK4FSrmBuNEDtoMPxE7hJWt8
有效载荷是:
{"ø":"1"}
如果您获取有效负载 eyLDuCI6IjEifQ
,您首先必须将其转换回二进制。 base64 字符 e
代表 6 位 011110
,y
代表 110010
等等(完整编码请查看 Wikipedia base64 table) .现在我们必须将它转换回 8 位,所以取前 6 位加上下一个字符的前 2 位,将得到 01111011
或十六进制 7B
,[= 的 ASCII 值19=] 后跟 00100010
(十六进制 22
,ASCII "
)等等。
第一个字符的完全转换产生以下十六进制代码:
7B 22 C3 B8 22
在 UTF-8 encoder/decoder 上你可以看到 ø
有 UTF-8 代码 C3 B8
,所有其他代码都可以在任何常见的 ASCII-table 上轻松找到:
{ " ø "
所以你看,令牌包含正确编码的 UTF-8 字符。将结果解释为 UTF-8 而不是任何其他字符集取决于您的客户。