博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于 IdentityServer3 实现 OAuth 2.0 授权服务数据持久化
阅读量:6291 次
发布时间:2019-06-22

本文共 9736 字,大约阅读时间需要 32 分钟。

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

Package

核心类库

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

配置信息持久化

客户端,作用域,票据的持久化 ,支持的扩展有两个,一个基于 EF,另外一个使用MongoDb(社区支持)

用户持久化

用户的持久化支持 MembershipReboot 与 ASP.NET Identity 两种

其他插件

WS-Federation

Access token validation middleware(验证中间件)

国际化

缓存

客户端

配置信息持久化(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 的项目中找到数据库的 ,

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
(resolver => new OperationalDbContext(options.ConnectionString, options.Schema))); factory.AuthorizationCodeStore = new Registration
(); factory.TokenHandleStore = new Registration
(); factory.ConsentStore = new Registration
(); factory.RefreshTokenStore = new Registration
(); } 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
(resolver => new ClientConfigurationDbContext(options.ConnectionString, options.Schema))); factory.ClientStore = new Registration
(); 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
(resolver => new ScopeConfigurationDbContext(options.ConnectionString, options.Schema))); factory.ScopeStore = new Registration
(); } }

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    {        ///         /// 配置Idsv授权服务        ///         ///         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
(resolver => AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve
()); //自定义视图 factory.ViewService = new Registration
>(); factory.Register(new Registration
(resolver => HttpContext.Current)); factory.Register(new Registration
(resolver => new HttpContextWrapper(resolver.Resolve
()))); //注册Request factory.Register(new Registration
(resolver => resolver.Resolve
().Request)); //注册Response factory.Register(new Registration
(resolver => resolver.Resolve
().Response)); factory.Register(new Registration
(resolver => resolver.Resolve
().Server)); //注册Session factory.Register(new Registration
(resolver => resolver.Resolve
().Session)); /* //注册 Redis 服务 factory.Register(new Registration
(resolver => ConnectionMultiplexer.Connect(CacheSetting.Redis).GetDatabase())); factory.AuthorizationCodeStore = new Registration
(); factory.TokenHandleStore = new Registration
(); factory.RefreshTokenStore = new Registration
(); */ /* //客户端信息缓存 var clientStoreCache = new ClientStoreCache(redis); //作用域信息缓存 var scopeStoreCache = new ScopeStoreCache(redis); //用户信息缓存 var userServiceCache = new UserServiceCache(redis); //注册客户端缓存- factory.ConfigureClientStoreCache(new Registration
>(clientStoreCache)); //注册作用域缓存 factory.ConfigureScopeStoreCache(new Registration
>>(scopeStoreCache)); //注册用户缓存 // factory.ConfigureUserServiceCache(new Registration
>>(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]
  • 密码模式用户的身份验证

REFER:

Deployment

转载地址:http://bpcta.baihongyu.com/

你可能感兴趣的文章
psutil
查看>>
在git@osc上托管自己的代码
查看>>
机器学习算法:朴素贝叶斯
查看>>
小五思科技术学习笔记之扩展访问列表
查看>>
使用Python脚本检验文件系统数据完整性
查看>>
使用MDT部署Windows Server 2003 R2
查看>>
Redhat as5安装Mysql5.0.28
查看>>
通过TMG发布ActiveSync
查看>>
Web服务器的配置与管理(4) 配置访问权限和安全
查看>>
ClientScriptManager与ScriptManager向客户端注册脚本的区别
查看>>
js和php中几种生成验证码的方式
查看>>
android UI进阶之仿iphone的tab效果1
查看>>
这是我的第1个C#程序(向控制台输出一句话)
查看>>
html
查看>>
Xqk.Data数据框架开发指南:丰富的、灵活的查询方法(第三部分:SqlField)
查看>>
颜色空间系列4: RGB和YDbDr颜色空间的转换及优化算法
查看>>
Unity C# 设计模式(七)适配器模式
查看>>
Lancel sac négociation avec insistance que nous pourrions réaliser de quelle route
查看>>
空白表单提交到后台的数据类型总结(java)
查看>>
Vue问题区
查看>>