最近花了一点时间,阅读了IdentityServer的源码,大致了解项目整体的抽象思维、面向对象的重要性; 生产环境如果要使用 IdentityServer3 ,主要涉及授权服务,资源服务的部署负载的问题,客户端(clients),作用域(scopes),票据(token)一定都要持久化, 客户端与作用域的持久化只需要实现 IClientStore 与 IScopeStore 的接口,可以自己实现,也可以直接使用 IdentityServer3 自身的扩展 IdentityServer3.EntityFramework

Package

核心类库
Install-Package IdentityServer3
IdentityServer 核心库,只支持基于内存的客户端信息与用户信息配置

配置信息持久化
客户端,作用域,票据的持久化 ,支持的扩展有两个,一个基于 EF,另外一个使用MongoDb(社区支持)
Install-Package IdentityServer3.EntityFramework
Install-Package IdentityServer.v3.MongoDb

用户持久化

用户的持久化支持 MembershipReboot 与 ASP.NET Identity 两种
Install-Package IdentityServer3.MembershipReboot
Install-Package IdentityServer3.AspNetIdentity

其他插件

WS-Federation
Install-Package IdentityServer3.WsFederation
Access token validation middleware(验证中间件)
Install-Package IdentityServer3.AccessTokenValidation

国际化

https://github.com/johnkors/IdentityServer3.Contrib.Localization

缓存

https://github.com/AliBazzi/IdentityServer3.Contrib.RedisStore

客户端

https://github.com/IdentityModel/IdentityModel2

配置信息持久化(Entity Framework support for Clients, Scopes, and Operational Data)

客户端(clients)与作用域(scopes)的持久化

客户端与作用域的持久化只需要实现 IClientStore 与 IScopeStore 的接口,默认EF 在 IdentityServerServiceFactory 实现了 RegisterClientStore 与 RegisterScopeStore 两个扩展方法,也可以使用 RegisterConfigurationServices 方法,默认包含以上两个扩展方法合集;RegisterOperationalServices 扩展方法实现 IAuthorizationCodeStore, ITokenHandleStore, IRefreshTokenStore, and IConsentStore 功能等。

可以在 IdentityServer3.EntityFramework 的项目中找到数据库的初始SQL

ER 关系项目结构

IdentityServerServiceFactoryExtensions 类扩展 IdentityServerServiceFactory 实现方法来持久化信息,最后 Registration 到接口上

public static class IdentityServerServiceFactoryExtensions
{
public static void RegisterOperationalServices(this IdentityServerServiceFactory factory, EntityFrameworkServiceOptions options)
{
if (factory == null) throw new ArgumentNullException("factory");
if (options == null) throw new ArgumentNullException("options"); factory.Register(new Registration<IOperationalDbContext>(resolver => new OperationalDbContext(options.ConnectionString, options.Schema)));
factory.AuthorizationCodeStore = new Registration<IAuthorizationCodeStore, AuthorizationCodeStore>();
factory.TokenHandleStore = new Registration<ITokenHandleStore, TokenHandleStore>();
factory.ConsentStore = new Registration<IConsentStore, ConsentStore>();
factory.RefreshTokenStore = new Registration<IRefreshTokenStore, RefreshTokenStore>();
} public static void RegisterConfigurationServices(this IdentityServerServiceFactory factory, EntityFrameworkServiceOptions options)
{
factory.RegisterClientStore(options);
factory.RegisterScopeStore(options);
} public static void RegisterClientStore(this IdentityServerServiceFactory factory, EntityFrameworkServiceOptions options)
{
if (factory == null) throw new ArgumentNullException("factory");
if (options == null) throw new ArgumentNullException("options"); factory.Register(new Registration<IClientConfigurationDbContext>(resolver => new ClientConfigurationDbContext(options.ConnectionString, options.Schema)));
factory.ClientStore = new Registration<IClientStore, ClientStore>();
factory.CorsPolicyService = new ClientConfigurationCorsPolicyRegistration(options);
} public static void RegisterScopeStore(this IdentityServerServiceFactory factory, EntityFrameworkServiceOptions options)
{
if (factory == null) throw new ArgumentNullException("factory");
if (options == null) throw new ArgumentNullException("options"); factory.Register(new Registration<IScopeConfigurationDbContext>(resolver => new ScopeConfigurationDbContext(options.ConnectionString, options.Schema)));
factory.ScopeStore = new Registration<IScopeStore, ScopeStore>();
}
}

TokenCleanup 类负责定时清除过期的票据信息

public class TokenCleanup
{
private readonly static ILog Logger = LogProvider.GetCurrentClassLogger(); EntityFrameworkServiceOptions options;
CancellationTokenSource source;
TimeSpan interval; public TokenCleanup(EntityFrameworkServiceOptions options, int interval = )
{
if (options == null) throw new ArgumentNullException("options");
if (interval < ) throw new ArgumentException("interval must be more than 1 second"); this.options = options;
this.interval = TimeSpan.FromSeconds(interval);
} public void Start()
{
if (source != null) throw new InvalidOperationException("Already started. Call Stop first."); source = new CancellationTokenSource();
Task.Factory.StartNew(()=>Start(source.Token));
} public void Stop()
{
if (source == null) throw new InvalidOperationException("Not started. Call Start first."); source.Cancel();
source = null;
} public async Task Start(CancellationToken cancellationToken)
{
while (true)
{
if (cancellationToken.IsCancellationRequested)
{
Logger.Info("CancellationRequested");
break;
} try
{
await Task.Delay(interval, cancellationToken);
}
catch
{
Logger.Info("Task.Delay exception. exiting.");
break;
} if (cancellationToken.IsCancellationRequested)
{
Logger.Info("CancellationRequested");
break;
} await ClearTokens();
}
} public virtual IOperationalDbContext CreateOperationalDbContext()
{
return new OperationalDbContext(options.ConnectionString, options.Schema);
} private async Task ClearTokens()
{
try
{
Logger.Info("Clearing tokens");
using (var db = CreateOperationalDbContext())
{
var query =
from token in db.Tokens
where token.Expiry < DateTimeOffset.UtcNow
select token; db.Tokens.RemoveRange(query); await db.SaveChangesAsync();
}
}
catch(Exception ex)
{
Logger.ErrorException("Exception cleaning tokens", ex);
}
}
}

配置Idsv授权服务

Startup 类

 public class Startup
{
/// <summary>
/// 配置Idsv授权服务
/// </summary>
/// <param name="app"></param>
public void Configuration(IAppBuilder app)
{
#region OAuth 2.0 服务端初始化
//配置EF
var ef = new EntityFrameworkServiceOptions
{
ConnectionString = DbSetting.OAuth2,
}; var factory = new IdentityServerServiceFactory();
//注册Client与Scope的实现
factory.RegisterConfigurationServices(ef);
//注册Token实现
factory.RegisterOperationalServices(ef);
//自定义用户服务
factory.UserService = new Registration<IUserService>(resolver => AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve<IdSvrUserService>());
//自定义视图
factory.ViewService = new Registration<IViewService, IdSvrMvcViewService<LoginController>>(); factory.Register(new Registration<HttpContext>(resolver => HttpContext.Current));
factory.Register(new Registration<HttpContextBase>(resolver => new HttpContextWrapper(resolver.Resolve<HttpContext>())));
//注册Request
factory.Register(new Registration<HttpRequestBase>(resolver => resolver.Resolve<HttpContextBase>().Request));
//注册Response
factory.Register(new Registration<HttpResponseBase>(resolver => resolver.Resolve<HttpContextBase>().Response));
factory.Register(new Registration<HttpServerUtilityBase>(resolver => resolver.Resolve<HttpContextBase>().Server));
//注册Session
factory.Register(new Registration<HttpSessionStateBase>(resolver => resolver.Resolve<HttpContextBase>().Session)); /*
//注册 Redis 服务
factory.Register(new Registration<IDatabaseAsync>(resolver => ConnectionMultiplexer.Connect(CacheSetting.Redis).GetDatabase()));
factory.AuthorizationCodeStore = new Registration<IAuthorizationCodeStore, IdentityServer3.Contrib.RedisStore.Stores.AuthorizationCodeStore>();
factory.TokenHandleStore = new Registration<ITokenHandleStore, IdentityServer3.Contrib.RedisStore.Stores.TokenHandleStore>();
factory.RefreshTokenStore = new Registration<IRefreshTokenStore, IdentityServer3.Contrib.RedisStore.Stores.RefreshTokenStore>();
*/ /*
//客户端信息缓存
var clientStoreCache = new ClientStoreCache(redis);
//作用域信息缓存
var scopeStoreCache = new ScopeStoreCache(redis);
//用户信息缓存
var userServiceCache = new UserServiceCache(redis);
//注册客户端缓存-
factory.ConfigureClientStoreCache(new Registration<ICache<Client>>(clientStoreCache));
//注册作用域缓存
factory.ConfigureScopeStoreCache(new Registration<ICache<IEnumerable<Scope>>>(scopeStoreCache));
//注册用户缓存
// factory.ConfigureUserServiceCache(new Registration<ICache<IEnumerable<Claim>>>(userServiceCache));
// factory.ConfigureUserServiceCache(TimeSpan.FromMilliseconds(1000 * 10));
*/ //Idsv 配置
app.UseIdentityServer(new IdentityServerOptions
{
SiteName = "Embedded Homeinns PMS 2.0 OAuth2 Service",
EnableWelcomePage = true,
Factory = factory,
RequireSsl = Constants.RequireSsl,
PublicOrigin = Constants.PublicOrigin,
LoggingOptions = new LoggingOptions()
{
EnableHttpLogging = true,
// EnableKatanaLogging = true,
// EnableWebApiDiagnostics = true,
// WebApiDiagnosticsIsVerbose = true,
},
SigningCertificate = new X509Certificate2(string.Format(@"{0}\IdSvr\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test"),
EventsOptions = new EventsOptions
{
RaiseSuccessEvents = true,
RaiseErrorEvents = true,
RaiseFailureEvents = true,
RaiseInformationEvents = true,
},
CspOptions = new CspOptions
{
Enabled = false,
},
AuthenticationOptions = new AuthenticationOptions
{
CookieOptions = new IdentityServer3.Core.Configuration.CookieOptions
{
SlidingExpiration = true,
},
EnablePostSignOutAutoRedirect = true,
EnableLocalLogin = true,
EnableSignOutPrompt = false
}
});
//启动清除过期票据定时器
var cleanToken = new TokenCleanup(ef, );
cleanToken.Start();
#endregion #region OAuth 2.0 管理后台 初始化
/*
//管理员功能 初始化
app.Map("/admin", adminApp =>
{
var factoryAdmin = new IdentityAdmin.Configuration.IdentityAdminServiceFactory();
//注入配置
factoryAdmin.Configure();
//注册管理员
adminApp.UseIdentityAdmin(new IdentityAdmin.Configuration.IdentityAdminOptions
{
Factory = factoryAdmin,
//AdminSecurityConfiguration =
});
});
*/
#endregion
}
}

客户端模式问题

  • 客户端,作用域,票据的持久化 [OK]
  • 限制客户端每天获得新票据的次数
  • 票据过期删除的策略 [OK]
  • 授权服务器客户端信息缓存策略 [OK]
  • 资源服务器票据验证的缓存策略 [OK]
  • 作用域权限范围控制
  • ClientId 与 ClientSecret 的生成规则 [OK]
  • 密码模式用户的身份验证 https://github.com/IdentityServer/IdentityServer3.AspNetIdentity

REFER:
Deployment
https://identityserver.github.io/Documentation/docsv2/advanced/deployment.html

基于 IdentityServer3 实现 OAuth 2.0 授权服务数据持久化的更多相关文章

  1. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【密码模式(Resource Owner Password Credentials)】

    密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码.客户端使用这些信息,向"服务商提供商"索要授权 ...

  2. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】

    github:https://github.com/IdentityServer/IdentityServer3/ documentation:https://identityserver.githu ...

  3. Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端

    Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端 目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Se ...

  4. 理解OAuth 2.0授权

    一.什么是OAuth 二.什么场景下会用到OAuth授权 三.OAuth 2.0中的4个成员 四.OAuth 2.0授权流程 五.OAuth 2.0授权模式 1.    authorization c ...

  5. React + Node 单页应用「二」OAuth 2.0 授权认证 & GitHub 授权实践

    关于项目 项目地址 预览地址 记录最近做的一个 demo,前端使用 React,用 React Router 实现前端路由,Koa 2 搭建 API Server, 最后通过 Nginx 做请求转发. ...

  6. 转 OAuth 2.0授权协议详解

    http://www.jb51.net/article/54948.htm 作者:阮一峰 字体:[增加 减小] 类型:转载 时间:2014-09-10我要评论 这篇文章主要介绍了OAuth 2.0授权 ...

  7. Spring Security实现OAuth2.0授权服务 - 进阶版

    <Spring Security实现OAuth2.0授权服务 - 基础版>介绍了如何使用Spring Security实现OAuth2.0授权和资源保护,但是使用的都是Spring Sec ...

  8. OAuth 2.0授权框架详解

    目录 简介 OAuth的构成 refresh Token Authorization Code模式 隐式授权 Resource Owner 授权密码认证 Client 认证授权 github的OAut ...

  9. SimpleSSO:使用Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端

    目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Security.SimpleSSO模拟OpenID认证 通过authorization co ...

随机推荐

  1. (转)jQuery中的extend()方法

    本文转自:http://www.xiabingbao.com/jquery/2015/05/30/jquery-extend 原文的排版要比这里美观很多,建议去原文查看.本文仅仅作为个人的mark,方 ...

  2. object-assign合并对象

    1. Object.assign() 对于合并对象操作, ECMAScript 6 中提供了一个函数: Object.assign(target, source); 这个方法会将所有可枚举 [1] 的 ...

  3. Spring 4集成 Quartz2(转)

    本文将演示如何通过 Spring 使用 Quartz Scheduler 进行任务调度.Spring 为简化 Quartz 的操作提供了相关支持类.本文示例使用的相关工具如下: Spring 4.2. ...

  4. iOS开发-Alcatraz插件管理

    CocoaPod负责iOS开发中的引用类库的管理,Alcatraz中文翻译阿尔卡特拉斯岛,也有人称之为恶魔岛,主要是负责管理第三方Xcode 插件.模版以及颜色配置的工具,直接集成到 Xcode 的图 ...

  5. laravel遇到的问题

    这是由于访问laravel项目报错的,解决几种可能出现的错误. 1)打开:D:\java\wamp\www\subway\app\config\app.php 修改:'debug' => tru ...

  6. Decorator(装饰)-对象结构型模式

    1.意图 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. 2.别名 包装器 Wrapper. 3.动机 给某个对象而不是整个类添加一些功能.一个较为灵 ...

  7. svc6 控制台程序利用SoapToolkit3.0调用WebService

    1. 首先要安装SoapToolkit3.0安装包并安装(我的安装目录为:C:\Program Files\Common Files) 2. 新建vc控制台程序(空项目),项目名称:WinConsol ...

  8. TortoiseSVN汉化包装了,不管用,仍然是英文菜单

    TortoiseSVN装了后,把对应的汉化包也装了,但不管用,仍然是英文菜单. 想着是因为没有重启的原因,但是重启了再装,仍然看不到中文工菜单. 想了一下,TortoiseSVN汉化包在装的时候,没有 ...

  9. LeetCode(一)

    数据流的中位数 class MedianFinder { private Queue<Integer> maxHeap = new PriorityQueue(new Comparator ...

  10. iOS字符串为空的判断

    //判断字符串 -(BOOL) isValidString:(id)input { if (!input) { return NO; } if ((NSNull *)input == [NSNull ...