c# - 统一解码 JWT
问题描述
我有一个问题,我现在完全不知所措。我有一个身份验证服务器,可以创建 JWT 并将其发送到统一应用程序(android/VR)。
身份验证服务器这样创建令牌
private string GenerateJwtToken(User user)
{
var symmetricKey = Convert.FromBase64String(_tokenSettings.Secret);
var expires = DateTime.Now.AddMinutes(Convert.ToInt32(15));
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.PrimarySid, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Username),
new Claim(ClaimTypes.GivenName, user.FirstName),
new Claim(ClaimTypes.Surname, user.LastName),
new Claim("company", user.Company),
new Claim(ClaimTypes.Role, "api_user"),
new Claim(ClaimTypes.Expiration, $"{expires.ToShortDateString() + " " + expires.ToShortTimeString()}"),
}),
Expires = expires,
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(symmetricKey),
SecurityAlgorithms.HmacSha256Signature)
};
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(securityToken);
return token;
}
我对此进行解码并在控制台应用程序中提出声明没有任何问题。这就是混乱的来源。当我尝试在 Unity 中执行相同的任务并将应用程序构建到 VR 耳机时,我遇到了问题,即
"IDX10729: Unable to decode the header 'header' as Base64Url encoded string. jwtEncodedString: 'Token here'."
unity auth 服务看起来像这样
public async Task<string> GetAccessToken(string username, string password)
{
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage())
{
//TODO: Replace this hardcoded URL value here.
request.RequestUri = new Uri("{{URL Emmited}}");
request.Method = HttpMethod.Post;
var body = new AuthRequest()
{
Username = username,
Password = password
};
var content = new StringContent(JsonConvert.SerializeObject(body), encoding: Encoding.UTF8, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
var responseContent = await response.Content.ReadAsStringAsync();
var tokenContent = JsonConvert.DeserializeObject<Response>(responseContent);
var token = tokenContent.Token;
return token;
}
}
}
并检索索赔,我尝试了两种不同的方法
public string GetUserName(string token)
{
try
{
var securityToken = new JwtSecurityToken(token);
return securityToken?.Claims.First(claim => claim.Type == "given_name").Value;
}
catch (Exception exception)
{
//log exception here
return string.Empty;
}
}
和
public string GetUserName(string token)
{
try
{
var handler = new JwtSecurityTokenHandler();
var securityToken = handler.ReadJwtToken(token);
return securityToken?.Claims.First(claim => claim.Type == "given_name").Value;
}
catch (Exception exception)
{
//log exception here
return string.Empty;
}
}
ReadJwtToken 在内部只是创建了一个新的 JwtSecurityToken 对象,所以我认为我缺少一些东西。
这两个都抛出相同的“无法将标头'header'解码为Base64Url编码字符串”错误,但是,如果我这样做handler.CanReadToken(token);
返回true,这让我更加困惑。
任何人都知道为什么会发生这种情况以及如何解决它的任何线索。
一些进一步的信息;我检索到的令牌可以在 JWT.io 和控制台应用程序中解码,我使用 System.IdentityModel、System.IdentityModel.Tokens.JWT、System.IdentityModel.Tokens、System.IdentityModel.Logging 的 dotnet 标准 2.0 程序集和 Newtonsoft.Json
解决方案
推荐阅读
- python - 如何在 Python 中将某个 RGB 值分配给“最近”的一些其他 RGB 值
- r - 如何为多个变量创建堆积条形图
- javascript - 在 JavaScript 中使用原型添加函数
- reactjs - REACT 上下文 API 提供程序返回未定义
- qt - 从 QWebSocketServer 实时向客户端发送一系列消息
- rust - Rust 的内置目标规范在哪里定义?
- python - 尝试使用 Flask-SQLAlchemy 创建数据库
- python - ValueError:无法将 NumPy 数组转换为张量(不支持的对象类型 numpy.ndarray)。当给出数组数组时
- javascript - 如何在字符串中找到匹配单词的确切数量?
- c# - 使用 2d 数组来跟踪“d”在该位置的时间