我正在使用ASP.NET WebApi 2构建web应用程序接口,使用声明身份验证,我的用户可以拥有非常多的声明。对于大量的声明,持有者令牌增长得非常快,所以我试图找到一种返回更短的持有者令牌的方法。
到目前为止,我发现我可以为OAuth选项OAuthAuthorizationServerOptions.AccessTokenProvider
属性提供一个IAuthenticationTokenProvider
:
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(12),
AccessTokenProvider = new GuidProvider() // <-- here
};
这让我有机会截取AuthenticationTicket
并将其隐藏起来,用一些更简单的东西替换它-在我的示例中,下面是一个散列的guid。(注意:目前这个类只包含我的会话的一个ConcurrentDictionary<string,AuthenticationTicket>
-在一个真实的示例中,我打算将会话存储在一些持久存储中)
public class GuidProvider : IAuthenticationTokenProvider
{
private static ConcurrentDictionary<string, AuthenticationTicket> tokens
= new ConcurrentDictionary<string, AuthenticationTicket>();
public void Create(AuthenticationTokenCreateContext context)
{
throw new NotImplementedException();
}
public async System.Threading.Tasks.Task CreateAsync(AuthenticationTokenCreateContext context)
{
var guid = Guid.NewGuid().ToString();
var ticket = Crypto.Hash(guid);
tokens.TryAdd(ticket, context.Ticket);
context.SetToken(ticket);
}
public void Receive(AuthenticationTokenReceiveContext context)
{
throw new NotImplementedException();
}
public async System.Threading.Tasks.Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
AuthenticationTicket ticket;
if (tokens.TryGetValue(context.Token, out ticket))
{
if (ticket.Properties.ExpiresUtc.Value < DateTime.UtcNow)
{
tokens.TryRemove(context.Token, out ticket);
}
context.SetTicket(ticket);
}
}
}
所以我的问题是:
另一件要注意的事情是,我打算支持刷新令牌,事实上,上面的示例是从使用这种刷新令牌机制的示例中提取出来的-除非使用刷新令牌,否则它们看起来是一次性使用的,所以ReceiveAsync
方法通常会删除从ConcurrentDictionary
提供的刷新令牌,我不完全确定我理解为什么?
发布于 2014-12-15 20:33:03
我不建议这样做,因为您最终会将身份验证票证存储到数据库或Redis服务器中,这里的回调是,对于每个包含一个持有者令牌的请求,您将检查这个永久存储区,以便解析Guid并再次获取票证来构造它。
我建议您使用JSON Web Token JWT而不是默认的持有者访问令牌格式,为此您需要在OAuthAuthorizationServerOptions
的属性Provider
中实现您的自定义访问令牌格式CustomOAuthProvider
,如下所示:
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth2/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat("http://jwtauthzsrv.azurewebsites.net")
};
我注意到,向JWT令牌添加更多声明不会像默认访问令牌格式那样显著增加其大小。
下面是两个JWTs的样本,每个JWTs的内部都有不同的声明,第二个比第一个大50个字符。我建议您使用jwt.io First JWT检查每个文件的编码内容:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6InRhaXNlZXIiLCJzdWIiOiJ0YWlzZWVyIiwicm9sZSI6WyJNYW5hZ2VyIiwiU3VwZXJ2aXNvciJdLCJpc3MiOiJodHRwOi8vand0YXV0aHpzcnYuYXp1cmV3ZWJzaXRlcy5uZXQiLCJhdWQiOiIwOTkxNTNjMjYyNTE0OWJjOGVjYjNlODVlMDNmMDAyMiIsImV4cCI6MTQxODY0NzMyNywibmJmIjoxNDE4NjQ1NTI3fQ.vH9XPtjtAv2-6SwlyX4fKNJfm5ZTVHd_9a3bRgkA_LI
第二个JWT (更多声明):
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6InRhaXNlZXIiLCJzdWIiOiJ0YWlzZWVyIiwicm9sZSI6WyJNYW5hZ2VyIiwiU3VwZXJ2aXNvciIsIlN1cGVydmlzb3IxIiwiU3VwZXJ2aXNvcjIiLCJTdXBlcnZpc29yMyJdLCJpc3MiOiJodHRwOi8vand0YXV0aHpzcnYuYXp1cmV3ZWJzaXRlcy5uZXQiLCJhdWQiOiIwOTkxNTNjMjYyNTE0OWJjOGVjYjNlODVlMDNmMDAyMiIsImV4cCI6MTQxODY0NzQ1NiwibmJmIjoxNDE4NjQ1NjU2fQ.TFEGDtz1RN8VmCQu7JH4Iug0B8UlWDLVrIlvc-7IK3E
JWT格式正在成为发布OAuth 2.0持有者令牌的标准方式,它也将与刷新令牌授权一起工作。
我已经在bitoftech.net上编写了关于如何在ASP.NET Web API中使用JWT令牌的detailed blog post,以及一个实时演示API和source code on GIthub,请随时查看它,如果您需要更多帮助,请告诉我。
祝好运!
https://stackoverflow.com/questions/27361358
复制相似问题