基于 IdentityServer3 实现 OAuth 2.0 授权服务数据持久化
2016-08-19 17:01
891 查看
最近花了一点时间,阅读了IdentityServer的源码,大致了解项目整体的抽象思维、面向对象的重要性; 生产环境如果要使用 IdentityServer3 ,主要涉及授权服务,资源服务的部署负载的问题,客户端(clients),作用域(scopes),票据(token)一定都要持久化, 客户端与作用域的持久化只需要实现 IClientStore 与 IScopeStore 的接口,可以自己实现,也可以直接使用 IdentityServer3 自身的扩展 IdentityServer3.EntityFramework 。
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
客户端与作用域的持久化只需要实现 IClientStore 与 IScopeStore 的接口,默认EF 在 IdentityServerServiceFactory 实现了 RegisterClientStore 与 RegisterScopeStore 两个扩展方法,也可以使用 RegisterConfigurationServices 方法,默认包含以上两个扩展方法合集;RegisterOperationalServices 扩展方法实现 IAuthorizationCodeStore, ITokenHandleStore, IRefreshTokenStore, and IConsentStore 功能等。
可以在 IdentityServer3.EntityFramework 的项目中找到数据库的初始SQL ,
ER 关系
项目结构
IdentityServerServiceFactoryExtensions 类扩展 IdentityServerServiceFactory 实现方法来持久化信息,最后 Registration 到接口上
TokenCleanup 类负责定时清除过期的票据信息
客户端模式问题
客户端,作用域,票据的持久化 [OK]
限制客户端每天获得新票据的次数
票据过期删除的策略 [OK]
授权服务器客户端信息缓存策略 [OK]
资源服务器票据验证的缓存策略 [OK]
作用域权限范围控制
ClientId 与 ClientSecret 的生成规则 [OK]
密码模式用户的身份验证 https://github.com/IdentityServer/IdentityServer3.AspNetIdentity
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 = 60) { if (options == null) throw new ArgumentNullException("options"); if (interval < 1) 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, 20); 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
相关文章推荐
- 基于 IdentityServer3 实现 OAuth 2.0 授权服务【密码模式(Resource Owner Password Credentials)】
- 基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】
- IdentityServer4 实现 OpenID Connect 和 OAuth 2.0
- 用DotNetOpenAuth实现基于OAuth 2.0的web api授权 (一)Getting Start
- IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API
- c#实现microsoft账号登入授权(OAuth 2.0)并获取个人信息
- IdentityServer4 实现自定义 GrantType 授权模式
- 基于OWIN ASP.NET WebAPI 使用OAUTH2授权服务的几点优化
- 基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】
- ASP.NET MVC 随想录—— 使用ASP.NET Identity实现基于声明的授权,高级篇
- ASP.NET Core 集成 IdentityServer4 实现 OAuth 2.0 服务
- ASP.NET MVC 随想录—— 使用ASP.NET Identity实现基于声明的授权,高级篇
- 基于 SAML 2.0 的 WebSphere Application Server SSO 实现
- Testing WSO2 Identity Server OAuth 2.0 support with Curl
- 实验:基于keepalived实现两台realserver服务器中的nginx和php-fpm服务互为主从
- asp.net权限认证:OWIN实现OAuth 2.0 之授权码模式(Authorization Code)
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
- 基于OWIN WebAPI 使用OAuth授权服务【客户端验证授权(Resource Owner Password Credentials Grant)】
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
- OAuth 2.0 构建微服务身份认证(二):java实现过程