Azure 函数在不使用 Active Directory 的情况下创建和读取 JWT
Azure Function create and read JWT without using Active Directory
我正在尝试使用 C# 在 Azure 函数中创建和读取(验证)JSON Web 令牌 (JWT)。我遇到了这个 post:
https://www.codeproject.com/Tips/1208535/Create-And-Consume-JWT-Tokens-in-csharp
它很好地概述了这个过程。作为 Azure Functions 的新手,我将 "System.IdentityModel.Tokens.Jwt" 的引用放在我的 project.json 文件中,如下所示:
{
"frameworks": {
"net46":{
"dependencies": {
"System.IdentityModel.Tokens.Jwt" : "5.0"
}
}
}
}
我使用的版本来自这个 post: ,它在 2016 年讨论了版本控制问题。
不幸的是,这没有用。对 SecurityAlgorithms、JwtHeader、JwtPayload、JwtSecurityToken 和 JwtSecurityTokenHandler 的引用均报告,“[run.csx] 找不到类型或命名空间名称 'class name'(是否缺少 using 指令或程序集引用?) ".
进一步研究,我发现了这个页面:https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/,其中显示了 System.IdentityModel.Tokens.Jwt 的 Nuget 版本信息。在尝试了多个版本后(通过更改我的 project.json 文件中的版本),我仍然无法让 Function App 识别我需要的 类。
我认为这是一个版本控制问题。如果是这样,我可以去哪里确定哪个版本的 "System.IdentityModel.Tokens.Jwt" 与 "net46" 兼容?我已经很多年没有编写 C# 代码了(我是一名 Java 开发人员),所以我对版本控制的假设可能是错误的。
顺便说一句,这是我函数中的代码,它看起来与 https://www.codeproject.com/Tips/1208535/Create-And-Consume-JWT-Tokens-in-csharp 中的代码示例完全一样。唯一的区别是我将它包装在一个函数应用程序中。
using System.Net;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using System.IdentityModel;
using System.Security;
using System.Text;
using System.IdentityModel.Tokens;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
// Define const Key this should be private secret key stored in some safe place
string key = "401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1";
// Create Security key using private key above:
// not that latest version of JWT using Microsoft namespace instead of System
var securityKey = new Microsoft
.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
// Also note that securityKey length should be >256b
// so you have to make sure that your private key has a proper length
//
var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials
(securityKey, SecurityAlgorithms.HmacSha256Signature);
// Finally create a Token
var header = new JwtHeader(credentials);
//Some PayLoad that contain information about the customer
var payload = new JwtPayload
{
{ "some ", "hello "},
{ "scope", "http://dummy.com/"},
};
//
var secToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
// Token to String so you can use it in your client
var tokenString = handler.WriteToken(secToken);
// And finally when you received token from client
// you can either validate it or try to read
var token = handler.ReadJwtToken(tokenString);
return req.CreateResponse(HttpStatusCode.Created, "test");
}
所以,我的问题是:
- 我的项目文件中 "net46" 应该使用哪个 System.IdentityModel.Tokens 版本?
- 下次发生这种情况时,我如何确定哪些版本可以一起工作?
我刚试过这个,看到了同样的事情。您缺少对 System.IdentityModel
和 using System.IdentityModel.Tokens.Jwt;
的引用
改成这个得到东西建设:
#r "System.IdentityModel"
using System.Net;
using System.IdentityModel;
using System.Security;
using System.Text;
using System.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
我还建议您将 JWT 包参考升级到 5.2.4,这是该包的最新版本。
我明白了。从各种站点和数百种版本组合,它都有效。
我希望我能解释原因,但我将 post 此处的工作代码列出适当的库。如果其他人遇到这个问题,我希望它有所帮助。感谢您查看此 brettsam!
功能应用程序如下所示:
using System;
using System.Net;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.Configuration;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
string token = JwtManager.GenerateToken("rbivens@mydomain.com", 60);
ClaimsPrincipal simplePrinciple = JwtManager.GetPrincipal(token);
var identity = simplePrinciple.Identity as ClaimsIdentity;
log.Info(identity.IsAuthenticated.ToString());
var usernameClaim = identity.FindFirst(ClaimTypes.Name);
var username = usernameClaim ? .Value;
log.Info(username);
return req.CreateResponse(HttpStatusCode.Created, token);
}
public static class JwtManager
{
private static string secret = ConfigurationManager.AppSettings["FunctionsJwtSecret"];
public static string GenerateToken(string username, int expireMinutes = 60)
{
var symmetricKey = Convert.FromBase64String(secret);
var tokenHandler = new JwtSecurityTokenHandler();
var now = DateTime.UtcNow;
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, username)
}),
Expires = now.AddMinutes(Convert.ToInt32(expireMinutes)),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(symmetricKey), SecurityAlgorithms.HmacSha256Signature)
};
var stoken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(stoken);
return token;
}
public static ClaimsPrincipal GetPrincipal(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var jwtToken = tokenHandler.ReadToken(token) as JwtSecurityToken;
if (jwtToken == null)
return null;
var symmetricKey = Convert.FromBase64String(secret);
var validationParameters = new TokenValidationParameters()
{
RequireExpirationTime = true,
ValidateIssuer = false,
ValidateAudience = false,
IssuerSigningKey = new SymmetricSecurityKey(symmetricKey)
};
SecurityToken securityToken;
var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);
// log.Info(securityToken.ToString());
return principal;
}
catch (Exception)
{
return null;
}
}
}
project.json 看起来像这样:
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.IdentityModel.Logging" : "1.0.0.127",
"Microsoft.IdentityModel.Tokens" : "5.0.0.127",
"Newtonsoft.Json" : "9.0.0.0",
"System.IdentityModel.Tokens.Jwt" : "5.0.0.127"
}
}
}
}
同样,我不知道为什么这种版本组合可以一起工作,但我希望这可以为其他人节省 20 个小时的繁琐试验和错误。
我正在尝试使用 C# 在 Azure 函数中创建和读取(验证)JSON Web 令牌 (JWT)。我遇到了这个 post:
https://www.codeproject.com/Tips/1208535/Create-And-Consume-JWT-Tokens-in-csharp
它很好地概述了这个过程。作为 Azure Functions 的新手,我将 "System.IdentityModel.Tokens.Jwt" 的引用放在我的 project.json 文件中,如下所示:
{
"frameworks": {
"net46":{
"dependencies": {
"System.IdentityModel.Tokens.Jwt" : "5.0"
}
}
}
}
我使用的版本来自这个 post:
不幸的是,这没有用。对 SecurityAlgorithms、JwtHeader、JwtPayload、JwtSecurityToken 和 JwtSecurityTokenHandler 的引用均报告,“[run.csx] 找不到类型或命名空间名称 'class name'(是否缺少 using 指令或程序集引用?) ".
进一步研究,我发现了这个页面:https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/,其中显示了 System.IdentityModel.Tokens.Jwt 的 Nuget 版本信息。在尝试了多个版本后(通过更改我的 project.json 文件中的版本),我仍然无法让 Function App 识别我需要的 类。
我认为这是一个版本控制问题。如果是这样,我可以去哪里确定哪个版本的 "System.IdentityModel.Tokens.Jwt" 与 "net46" 兼容?我已经很多年没有编写 C# 代码了(我是一名 Java 开发人员),所以我对版本控制的假设可能是错误的。
顺便说一句,这是我函数中的代码,它看起来与 https://www.codeproject.com/Tips/1208535/Create-And-Consume-JWT-Tokens-in-csharp 中的代码示例完全一样。唯一的区别是我将它包装在一个函数应用程序中。
using System.Net;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using System.IdentityModel;
using System.Security;
using System.Text;
using System.IdentityModel.Tokens;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
// Define const Key this should be private secret key stored in some safe place
string key = "401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1";
// Create Security key using private key above:
// not that latest version of JWT using Microsoft namespace instead of System
var securityKey = new Microsoft
.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
// Also note that securityKey length should be >256b
// so you have to make sure that your private key has a proper length
//
var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials
(securityKey, SecurityAlgorithms.HmacSha256Signature);
// Finally create a Token
var header = new JwtHeader(credentials);
//Some PayLoad that contain information about the customer
var payload = new JwtPayload
{
{ "some ", "hello "},
{ "scope", "http://dummy.com/"},
};
//
var secToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
// Token to String so you can use it in your client
var tokenString = handler.WriteToken(secToken);
// And finally when you received token from client
// you can either validate it or try to read
var token = handler.ReadJwtToken(tokenString);
return req.CreateResponse(HttpStatusCode.Created, "test");
}
所以,我的问题是:
- 我的项目文件中 "net46" 应该使用哪个 System.IdentityModel.Tokens 版本?
- 下次发生这种情况时,我如何确定哪些版本可以一起工作?
我刚试过这个,看到了同样的事情。您缺少对 System.IdentityModel
和 using System.IdentityModel.Tokens.Jwt;
改成这个得到东西建设:
#r "System.IdentityModel"
using System.Net;
using System.IdentityModel;
using System.Security;
using System.Text;
using System.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
我还建议您将 JWT 包参考升级到 5.2.4,这是该包的最新版本。
我明白了。从各种站点和数百种版本组合,它都有效。 我希望我能解释原因,但我将 post 此处的工作代码列出适当的库。如果其他人遇到这个问题,我希望它有所帮助。感谢您查看此 brettsam!
功能应用程序如下所示:
using System;
using System.Net;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.Configuration;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
string token = JwtManager.GenerateToken("rbivens@mydomain.com", 60);
ClaimsPrincipal simplePrinciple = JwtManager.GetPrincipal(token);
var identity = simplePrinciple.Identity as ClaimsIdentity;
log.Info(identity.IsAuthenticated.ToString());
var usernameClaim = identity.FindFirst(ClaimTypes.Name);
var username = usernameClaim ? .Value;
log.Info(username);
return req.CreateResponse(HttpStatusCode.Created, token);
}
public static class JwtManager
{
private static string secret = ConfigurationManager.AppSettings["FunctionsJwtSecret"];
public static string GenerateToken(string username, int expireMinutes = 60)
{
var symmetricKey = Convert.FromBase64String(secret);
var tokenHandler = new JwtSecurityTokenHandler();
var now = DateTime.UtcNow;
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, username)
}),
Expires = now.AddMinutes(Convert.ToInt32(expireMinutes)),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(symmetricKey), SecurityAlgorithms.HmacSha256Signature)
};
var stoken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(stoken);
return token;
}
public static ClaimsPrincipal GetPrincipal(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var jwtToken = tokenHandler.ReadToken(token) as JwtSecurityToken;
if (jwtToken == null)
return null;
var symmetricKey = Convert.FromBase64String(secret);
var validationParameters = new TokenValidationParameters()
{
RequireExpirationTime = true,
ValidateIssuer = false,
ValidateAudience = false,
IssuerSigningKey = new SymmetricSecurityKey(symmetricKey)
};
SecurityToken securityToken;
var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);
// log.Info(securityToken.ToString());
return principal;
}
catch (Exception)
{
return null;
}
}
}
project.json 看起来像这样:
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.IdentityModel.Logging" : "1.0.0.127",
"Microsoft.IdentityModel.Tokens" : "5.0.0.127",
"Newtonsoft.Json" : "9.0.0.0",
"System.IdentityModel.Tokens.Jwt" : "5.0.0.127"
}
}
}
}
同样,我不知道为什么这种版本组合可以一起工作,但我希望这可以为其他人节省 20 个小时的繁琐试验和错误。