使用 OWIN 的 webapi 中的复杂 JSON Web 令牌数组
Complex JSON Web Token Array in webapi with OWIN
我正在尝试学习 JWT 和 ouath。我遇到了 JWT 的形式,它可以帮助我开发我的授权服务器。
我遇到的格式如下:
{
iat: 1416929061,
jti: "802057ff9b5b4eb7fbb8856b6eb2cc5b",
scopes: {
users: {
actions: ['read', 'create']
},
users_app_metadata: {
actions: ['read', 'create']
}
}
}
然而,由于在添加声明时我们只能添加简单的字符串,如何实现这样的事情呢?
到目前为止我看到的唯一方法是使用 JSON.serialization - 来自
new Claim(someClass,JsonConvert.SerializeObject(result)
任何指南将不胜感激!谢谢!
用于测试的代码
Class 我想在 JWT 中使用
public class MyTes
{
public string area { get; set; }
public List<string> areapermissions { get; set; }
}
然后我使用以下代码生成令牌
var identity = new ClaimsIdentity("JWT");
var cos = new List<string>();
cos.Add("aaa");
cos.Add("bbb");
MyTes vario = new MyTes()
{
area = "someregion",
areapermissions = cos
};
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "Manager"));
identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));
identity.AddClaim(new Claim("scope", "xyz1"));
identity.AddClaim(new Claim("scope", "xyz2"));
identity.AddClaim(new Claim("scope", "xyz3"));
identity.AddClaim(new Claim("APIs", JsonConvert.SerializeObject(cos)));
identity.AddClaim(new Claim("APIs2", JsonConvert.SerializeObject(vario)));
这没有错误,当我解码我现在得到的票时:
{
"unique_name": "Rafski",
"sub": "Rafski",
"role": [
"Manager",
"Supervisor"
],
"scope": [
"xyz1",
"xyz2",
"xyz3"
],
"APIs": "[\"aaa\",\"bbb\"]",
"APIs2": "{\"area\":\"someregion\",\"areapermissions\":[\"aaa\",\"bbb\"]}",
"iss": "http://kurwa.mac",
"aud": "7aaa70ed8f0b4807a01596e2abfbd44d",
"exp": 1429351056,
"nbf": 1429349256
}
所以这个问题的关键是理解:) 首先要注意的是下面的escape characters。
这基本上让我明白我所需要的只是适当的 serialization/deserialization 自定义数组对象。
所以我创建了以下内容作为每个范围的基础
Dictionary<string, List<string>> xx3 = new Dictionary<string, List<string>>()
{
{
"s3",new List<string>()
{
"access1" , "access2"
}
}
};
然后简单地序列化这个对象并添加为声明
var cos3 = JsonConvert.SerializeObject(xx3, Formatting.Indented);
identity.AddClaim(new Claim("scopes", cos1));
现在剩下的挑战是对我的 resources.So 的适当授权 我添加了自定义的 AuthorizationFilterAttribute
在那里我使用来自 here
的代码反序列化声明
对于那些想要寻找更多代码的人来说,这是我的自定义过滤器的片段:
// Check if we have scopes
var AllScopes = principal.Claims.Where(p => p.Type == "scopes");
// Check if we have desired scope
foreach (var singlescope in AllScopes)
{
Dictionary<string, List<string>> userscopes = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(singlescope.Value);
if (userscopes.Single(kvp => kvp.Key == ScopeName).Value.Contains(ScopeAccess))
{
//User is Authorized, complete execution
return Task.FromResult<object>(null);
}
}
我希望这会对某人有所帮助!
以下是如何使用 .Net 创建具有复杂 JSON 声明的 JWT 令牌。
使用 Nuget 获取库:System.IdentityModel.Tokens.Jwt
然后使用以下代码创建 JWT 令牌。
var keybytes = Convert.FromBase64String(YOUR_CLIENT_SECRET);
var signingCredentials = new SigningCredentials(
new InMemorySymmetricSecurityKey(keybytes),
SecurityAlgorithms.HmacSha256Signature,
SecurityAlgorithms.Sha256Digest);
var nbf = DateTime.UtcNow.AddSeconds(-1);
var exp = DateTime.UtcNow.AddSeconds(120);
var payload = new JwtPayload(null, "", new List<Claim>(), nbf, exp);
var users = new Dictionary<string, object>();
users.Add("actions", new List<string>() { "read", "create" });
var scopes = new Dictionary<string, object>();
scopes.Add("users", users);
payload.Add("scopes", scopes);
var jwtToken = new JwtSecurityToken(new JwtHeader(signingCredentials), payload);
var jwtTokenHandler = new JwtSecurityTokenHandler();
return jwtTokenHandler.WriteToken(jwtToken);
这会产生一个令牌,例如
{
"typ": "JWT",
"alg": "HS256"
}
{
"exp": 1433254394,
"nbf": 1433254273,
"scopes": {
"users": {
"actions": [
"read", "create"
]
}
}
}
这是我创建复杂令牌的方式:
var securityKey = new InMemorySymmetricSecurityKey(Encoding.Default.GetBytes("401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1"));
var signingCredentials = new SigningCredentials(securityKey,
SecurityAlgorithms.HmacSha256Signature,
SecurityAlgorithms.Sha256Digest);
var header = new JwtHeader(signingCredentials);
var payload = new JwtPayload();
payload.AddClaims(claims);
payload.Add("tags", _tags.ToArray()); // this guy accepts object!
var token = new JwtSecurityToken(header, payload);
var tokenString = securityTokenHandler.WriteToken(token);
This has been never an issue these days. It can be solved using the
Payload section of the token.
**using System.IdentityModel.Tokens.Jwt;** //Vesrion 5.5.0
Sample code
public static string Generate()
{
IList<User> users = new List<User> {
new User { Id = 1, Name = "User One" },
new User { Id = 2, Name = "User Two" },
new User { Id = 3, Name = "User Three" }
};
IList<Company> companies = new List<Company>
{
new Company{ Id = 1, Code = "C01", Name = "Company I", Users = users },
new Company{ Id = 2, Code = "C03", Name = "Company II", Users = null },
new Company{ Id = 3, Code = "C03", Name = "Company III", Users = users }
};
IList<Branch> branches = new List<Branch>
{
new Branch{Id = 1, CompanyId = 1, Code="B01", Name = "Branch 1.1"},
new Branch{Id = 2, CompanyId = 1, Code="B02", Name = "Branch 1.2"},
new Branch{Id = 3, CompanyId = 1, Code="B03", Name = "Branch 1.3"},
new Branch{Id = 4, CompanyId = 2, Code="B04", Name = "Branch 2.1"},
new Branch{Id = 5, CompanyId = 2, Code="B05", Name = "Branch 2.2"},
};
var payload = new JwtPayload {
{ "companies", companies },
{ "branches", branches }
};
string key = "eyJjb21wYW5pZXMiOlt7IklkIjoxLCJDb2RlIjoiQzAxIiwiTmFtZSI6IkNvbXBhbnkgSSIsIkJyYW5jaGVzIjpudWxsLCJVc2VycyI6W3siSWQiOjEsIk5hbWUiOiJV";
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
var header = new JwtHeader(credentials);
var secToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
var tokenString = handler.WriteToken(secToken);
Console.WriteLine(secToken);
Console.WriteLine(tokenString);
return tokenString;
}
Output
{
"companies": [
{
"Id": 1,
"Code": "C01",
"Name": "Company I",
"Branches": null,
"Users": [
{
"Id": 1,
"Name": "User One"
},
{
"Id": 2,
"Name": "User Two"
},
{
"Id": 3,
"Name": "User Three"
}
]
},
{
"Id": 2,
"Code": "C03",
"Name": "Company II",
"Branches": null,
"Users": null
},
{
"Id": 3,
"Code": "C03",
"Name": "Company III",
"Branches": null,
"Users": [
{
"Id": 1,
"Name": "User One"
},
{
"Id": 2,
"Name": "User Two"
},
{
"Id": 3,
"Name": "User Three"
}
]
}
],
"branches": [
{
"Id": 1,
"CompanyId": 1,
"Code": "B01",
"Name": "Branch 1.1"
},
{
"Id": 2,
"CompanyId": 1,
"Code": "B02",
"Name": "Branch 1.2"
},
{
"Id": 3,
"CompanyId": 1,
"Code": "B03",
"Name": "Branch 1.3"
},
{
"Id": 4,
"CompanyId": 2,
"Code": "B04",
"Name": "Branch 2.1"
},
{
"Id": 5,
"CompanyId": 2,
"Code": "B05",
"Name": "Branch 2.2"
}
]
}
Token
eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJjb21wYW5pZXMiOlt7IklkIjoxLCJDb2RlIjoiQzAxIiwiTmFtZSI6IkNvbXBhbnkgSSIsIkJyYW5jaGVzIjpudWxsLCJVc2VycyI6W3siSWQiOjEsIk5hbWUiOiJVc2VyIE9uZSJ9LHsiSWQiOjIsIk5hbWUiOiJVc2VyIFR3byJ9LHsiSWQiOjMsIk5hbWUiOiJVc2VyIFRocmVlIn1dfSx7IklkIjoyLCJDb2RlIjoiQzAzIiwiTmFtZSI6IkNvbXBhbnkgSUkiLCJCcmFuY2hlcyI6bnVsbCwiVXNlcnMiOm51bGx9LHsiSWQiOjMsIkNvZGUiOiJDMDMiLCJOYW1lIjoiQ29tcGFueSBJSUkiLCJCcmFuY2hlcyI6bnVsbCwiVXNlcnMiOlt7IklkIjoxLCJOYW1lIjoiVXNlciBPbmUifSx7IklkIjoyLCJOYW1lIjoiVXNlciBUd28ifSx7IklkIjozLCJOYW1lIjoiVXNlciBUaHJlZSJ9XX1dLCJicmFuY2hlcyI6W3siSWQiOjEsIkNvbXBhbnlJZCI6MSwiQ29kZSI6IkIwMSIsIk5hbWUiOiJCcmFuY2ggMS4xIn0seyJJZCI6MiwiQ29tcGFueUlkIjoxLCJDb2RlIjoiQjAyIiwiTmFtZSI6IkJyYW5jaCAxLjIifSx7IklkIjozLCJDb21wYW55SWQiOjEsIkNvZGUiOiJCMDMiLCJOYW1lIjoiQnJhbmNoIDEuMyJ9LHsiSWQiOjQsIkNvbXBhbnlJZCI6MiwiQ29kZSI6IkIwNCIsIk5hbWUiOiJCcmFuY2ggMi4xIn0seyJJZCI6NSwiQ29tcGFueUlkIjoyLCJDb2RlIjoiQjA1IiwiTmFtZSI6IkJyYW5jaCAyLjIifV19.ysjwBa3YeYNmVB0fVEh95wL0zt8Krb-T4VRpWKWIfbU
我正在尝试学习 JWT 和 ouath。我遇到了 JWT 的形式,它可以帮助我开发我的授权服务器。
我遇到的格式如下:
{
iat: 1416929061,
jti: "802057ff9b5b4eb7fbb8856b6eb2cc5b",
scopes: {
users: {
actions: ['read', 'create']
},
users_app_metadata: {
actions: ['read', 'create']
}
}
}
然而,由于在添加声明时我们只能添加简单的字符串,如何实现这样的事情呢?
到目前为止我看到的唯一方法是使用 JSON.serialization - 来自
new Claim(someClass,JsonConvert.SerializeObject(result)
任何指南将不胜感激!谢谢!
用于测试的代码
Class 我想在 JWT 中使用
public class MyTes
{
public string area { get; set; }
public List<string> areapermissions { get; set; }
}
然后我使用以下代码生成令牌
var identity = new ClaimsIdentity("JWT");
var cos = new List<string>();
cos.Add("aaa");
cos.Add("bbb");
MyTes vario = new MyTes()
{
area = "someregion",
areapermissions = cos
};
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "Manager"));
identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));
identity.AddClaim(new Claim("scope", "xyz1"));
identity.AddClaim(new Claim("scope", "xyz2"));
identity.AddClaim(new Claim("scope", "xyz3"));
identity.AddClaim(new Claim("APIs", JsonConvert.SerializeObject(cos)));
identity.AddClaim(new Claim("APIs2", JsonConvert.SerializeObject(vario)));
这没有错误,当我解码我现在得到的票时:
{
"unique_name": "Rafski",
"sub": "Rafski",
"role": [
"Manager",
"Supervisor"
],
"scope": [
"xyz1",
"xyz2",
"xyz3"
],
"APIs": "[\"aaa\",\"bbb\"]",
"APIs2": "{\"area\":\"someregion\",\"areapermissions\":[\"aaa\",\"bbb\"]}",
"iss": "http://kurwa.mac",
"aud": "7aaa70ed8f0b4807a01596e2abfbd44d",
"exp": 1429351056,
"nbf": 1429349256
}
所以这个问题的关键是理解:) 首先要注意的是下面的escape characters。
这基本上让我明白我所需要的只是适当的 serialization/deserialization 自定义数组对象。
所以我创建了以下内容作为每个范围的基础
Dictionary<string, List<string>> xx3 = new Dictionary<string, List<string>>()
{
{
"s3",new List<string>()
{
"access1" , "access2"
}
}
};
然后简单地序列化这个对象并添加为声明
var cos3 = JsonConvert.SerializeObject(xx3, Formatting.Indented);
identity.AddClaim(new Claim("scopes", cos1));
现在剩下的挑战是对我的 resources.So 的适当授权 我添加了自定义的 AuthorizationFilterAttribute
在那里我使用来自 here
的代码反序列化声明对于那些想要寻找更多代码的人来说,这是我的自定义过滤器的片段:
// Check if we have scopes
var AllScopes = principal.Claims.Where(p => p.Type == "scopes");
// Check if we have desired scope
foreach (var singlescope in AllScopes)
{
Dictionary<string, List<string>> userscopes = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(singlescope.Value);
if (userscopes.Single(kvp => kvp.Key == ScopeName).Value.Contains(ScopeAccess))
{
//User is Authorized, complete execution
return Task.FromResult<object>(null);
}
}
我希望这会对某人有所帮助!
以下是如何使用 .Net 创建具有复杂 JSON 声明的 JWT 令牌。
使用 Nuget 获取库:System.IdentityModel.Tokens.Jwt
然后使用以下代码创建 JWT 令牌。
var keybytes = Convert.FromBase64String(YOUR_CLIENT_SECRET);
var signingCredentials = new SigningCredentials(
new InMemorySymmetricSecurityKey(keybytes),
SecurityAlgorithms.HmacSha256Signature,
SecurityAlgorithms.Sha256Digest);
var nbf = DateTime.UtcNow.AddSeconds(-1);
var exp = DateTime.UtcNow.AddSeconds(120);
var payload = new JwtPayload(null, "", new List<Claim>(), nbf, exp);
var users = new Dictionary<string, object>();
users.Add("actions", new List<string>() { "read", "create" });
var scopes = new Dictionary<string, object>();
scopes.Add("users", users);
payload.Add("scopes", scopes);
var jwtToken = new JwtSecurityToken(new JwtHeader(signingCredentials), payload);
var jwtTokenHandler = new JwtSecurityTokenHandler();
return jwtTokenHandler.WriteToken(jwtToken);
这会产生一个令牌,例如
{
"typ": "JWT",
"alg": "HS256"
}
{
"exp": 1433254394,
"nbf": 1433254273,
"scopes": {
"users": {
"actions": [
"read", "create"
]
}
}
}
这是我创建复杂令牌的方式:
var securityKey = new InMemorySymmetricSecurityKey(Encoding.Default.GetBytes("401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1"));
var signingCredentials = new SigningCredentials(securityKey,
SecurityAlgorithms.HmacSha256Signature,
SecurityAlgorithms.Sha256Digest);
var header = new JwtHeader(signingCredentials);
var payload = new JwtPayload();
payload.AddClaims(claims);
payload.Add("tags", _tags.ToArray()); // this guy accepts object!
var token = new JwtSecurityToken(header, payload);
var tokenString = securityTokenHandler.WriteToken(token);
This has been never an issue these days. It can be solved using the Payload section of the token.
**using System.IdentityModel.Tokens.Jwt;** //Vesrion 5.5.0
Sample code
public static string Generate()
{
IList<User> users = new List<User> {
new User { Id = 1, Name = "User One" },
new User { Id = 2, Name = "User Two" },
new User { Id = 3, Name = "User Three" }
};
IList<Company> companies = new List<Company>
{
new Company{ Id = 1, Code = "C01", Name = "Company I", Users = users },
new Company{ Id = 2, Code = "C03", Name = "Company II", Users = null },
new Company{ Id = 3, Code = "C03", Name = "Company III", Users = users }
};
IList<Branch> branches = new List<Branch>
{
new Branch{Id = 1, CompanyId = 1, Code="B01", Name = "Branch 1.1"},
new Branch{Id = 2, CompanyId = 1, Code="B02", Name = "Branch 1.2"},
new Branch{Id = 3, CompanyId = 1, Code="B03", Name = "Branch 1.3"},
new Branch{Id = 4, CompanyId = 2, Code="B04", Name = "Branch 2.1"},
new Branch{Id = 5, CompanyId = 2, Code="B05", Name = "Branch 2.2"},
};
var payload = new JwtPayload {
{ "companies", companies },
{ "branches", branches }
};
string key = "eyJjb21wYW5pZXMiOlt7IklkIjoxLCJDb2RlIjoiQzAxIiwiTmFtZSI6IkNvbXBhbnkgSSIsIkJyYW5jaGVzIjpudWxsLCJVc2VycyI6W3siSWQiOjEsIk5hbWUiOiJV";
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
var header = new JwtHeader(credentials);
var secToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
var tokenString = handler.WriteToken(secToken);
Console.WriteLine(secToken);
Console.WriteLine(tokenString);
return tokenString;
}
Output
{
"companies": [
{
"Id": 1,
"Code": "C01",
"Name": "Company I",
"Branches": null,
"Users": [
{
"Id": 1,
"Name": "User One"
},
{
"Id": 2,
"Name": "User Two"
},
{
"Id": 3,
"Name": "User Three"
}
]
},
{
"Id": 2,
"Code": "C03",
"Name": "Company II",
"Branches": null,
"Users": null
},
{
"Id": 3,
"Code": "C03",
"Name": "Company III",
"Branches": null,
"Users": [
{
"Id": 1,
"Name": "User One"
},
{
"Id": 2,
"Name": "User Two"
},
{
"Id": 3,
"Name": "User Three"
}
]
}
],
"branches": [
{
"Id": 1,
"CompanyId": 1,
"Code": "B01",
"Name": "Branch 1.1"
},
{
"Id": 2,
"CompanyId": 1,
"Code": "B02",
"Name": "Branch 1.2"
},
{
"Id": 3,
"CompanyId": 1,
"Code": "B03",
"Name": "Branch 1.3"
},
{
"Id": 4,
"CompanyId": 2,
"Code": "B04",
"Name": "Branch 2.1"
},
{
"Id": 5,
"CompanyId": 2,
"Code": "B05",
"Name": "Branch 2.2"
}
]
}
Token
eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJjb21wYW5pZXMiOlt7IklkIjoxLCJDb2RlIjoiQzAxIiwiTmFtZSI6IkNvbXBhbnkgSSIsIkJyYW5jaGVzIjpudWxsLCJVc2VycyI6W3siSWQiOjEsIk5hbWUiOiJVc2VyIE9uZSJ9LHsiSWQiOjIsIk5hbWUiOiJVc2VyIFR3byJ9LHsiSWQiOjMsIk5hbWUiOiJVc2VyIFRocmVlIn1dfSx7IklkIjoyLCJDb2RlIjoiQzAzIiwiTmFtZSI6IkNvbXBhbnkgSUkiLCJCcmFuY2hlcyI6bnVsbCwiVXNlcnMiOm51bGx9LHsiSWQiOjMsIkNvZGUiOiJDMDMiLCJOYW1lIjoiQ29tcGFueSBJSUkiLCJCcmFuY2hlcyI6bnVsbCwiVXNlcnMiOlt7IklkIjoxLCJOYW1lIjoiVXNlciBPbmUifSx7IklkIjoyLCJOYW1lIjoiVXNlciBUd28ifSx7IklkIjozLCJOYW1lIjoiVXNlciBUaHJlZSJ9XX1dLCJicmFuY2hlcyI6W3siSWQiOjEsIkNvbXBhbnlJZCI6MSwiQ29kZSI6IkIwMSIsIk5hbWUiOiJCcmFuY2ggMS4xIn0seyJJZCI6MiwiQ29tcGFueUlkIjoxLCJDb2RlIjoiQjAyIiwiTmFtZSI6IkJyYW5jaCAxLjIifSx7IklkIjozLCJDb21wYW55SWQiOjEsIkNvZGUiOiJCMDMiLCJOYW1lIjoiQnJhbmNoIDEuMyJ9LHsiSWQiOjQsIkNvbXBhbnlJZCI6MiwiQ29kZSI6IkIwNCIsIk5hbWUiOiJCcmFuY2ggMi4xIn0seyJJZCI6NSwiQ29tcGFueUlkIjoyLCJDb2RlIjoiQjA1IiwiTmFtZSI6IkJyYW5jaCAyLjIifV19.ysjwBa3YeYNmVB0fVEh95wL0zt8Krb-T4VRpWKWIfbU