调整为多租户模式

This commit is contained in:
yubaolee 2021-01-14 23:35:54 +08:00
parent 1228c6e875
commit 1ed50271bf
27 changed files with 148 additions and 59 deletions

View File

@ -1,4 +1,4 @@
namespace OpenAuth.App namespace Infrastructure
{ {
/// <summary> /// <summary>
/// 配置项 /// 配置项

View File

@ -1,6 +1,4 @@
using System; namespace Infrastructure
namespace OpenAuth.App
{ {
public static class Define public static class Define
{ {
@ -18,6 +16,7 @@ namespace OpenAuth.App
public const int INVALID_TOKEN = 50014; //token无效 public const int INVALID_TOKEN = 50014; //token无效
public const string TOKEN_NAME = "X-Token"; public const string TOKEN_NAME = "X-Token";
public const string TENANT_ID = "tenantId";
public const string SYSTEM_USERNAME = "System"; public const string SYSTEM_USERNAME = "System";

View File

@ -11,7 +11,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="9.0.0" /> <PackageReference Include="AutoMapper" Version="9.0.0" />
<PackageReference Include="EnyimMemcachedCore" Version="2.1.5" /> <PackageReference Include="EnyimMemcachedCore" Version="2.1.5" />
<PackageReference Include="log4net" Version="2.0.8" /> <PackageReference Include="log4net" Version="2.0.12" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.2" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />

View File

@ -14,6 +14,7 @@
//</summary> //</summary>
// *********************************************************************** // ***********************************************************************
using Infrastructure;
using OpenAuth.Repository; using OpenAuth.Repository;
using OpenAuth.Repository.Domain; using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Interface; using OpenAuth.Repository.Interface;

View File

@ -1,4 +1,5 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Infrastructure;
using Quartz; using Quartz;
namespace OpenAuth.App.Jobs namespace OpenAuth.App.Jobs

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Infrastructure;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using OpenAuth.App.Interface; using OpenAuth.App.Interface;
using OpenAuth.App.Request; using OpenAuth.App.Request;

View File

@ -5,6 +5,7 @@ using OpenAuth.App.Response;
using OpenAuth.Repository.Domain; using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Interface; using OpenAuth.Repository.Interface;
using System.Linq; using System.Linq;
using Infrastructure;
using OpenAuth.App.Request; using OpenAuth.App.Request;
using OpenAuth.Repository; using OpenAuth.Repository;

View File

@ -2,6 +2,7 @@ using Infrastructure.Cache;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using OpenAuth.App.Interface; using OpenAuth.App.Interface;
using System; using System;
using Infrastructure;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using OpenAuth.Repository.Domain; using OpenAuth.Repository.Domain;

View File

@ -3,6 +3,7 @@
* *
*/ */
using System; using System;
using Infrastructure;
using Infrastructure.Cache; using Infrastructure.Cache;
using OpenAuth.Repository; using OpenAuth.Repository;
using OpenAuth.Repository.Domain; using OpenAuth.Repository.Domain;

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Infrastructure;
using Infrastructure.Cache; using Infrastructure.Cache;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;

View File

@ -1,7 +1,10 @@
using Autofac.Extensions.DependencyInjection; using Autofac.Extensions.DependencyInjection;
using Infrastructure;
using Infrastructure.Cache; using Infrastructure.Cache;
using Infrastructure.Extensions.AutofacManager; using Infrastructure.Extensions.AutofacManager;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Moq; using Moq;
@ -23,10 +26,22 @@ namespace OpenAuth.App.Test
serviceCollection.AddOptions(); serviceCollection.AddOptions();
serviceCollection.AddLogging(); serviceCollection.AddLogging();
//模拟配置文件
var optionMock = new Mock<IOptions<AppSetting>>(); var optionMock = new Mock<IOptions<AppSetting>>();
optionMock.Setup(x => x.Value).Returns(new AppSetting { DbType = Define.DBTYPE_MYSQL}); optionMock.Setup(x => x.Value).Returns(new AppSetting { DbType = Define.DBTYPE_MYSQL});
serviceCollection.AddScoped(x => optionMock.Object); serviceCollection.AddScoped(x => optionMock.Object);
//模拟多租户id
var configMock = new Mock<IConfiguration>();
configMock.Setup(x => x.GetSection("ConnectionStrings")[Define.TENANT_ID]).Returns("");
serviceCollection.AddScoped(x => configMock.Object);
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
httpContextAccessorMock.Setup(x => x.HttpContext.Request.Query[Define.TOKEN_NAME]).Returns("tokentest");
httpContextAccessorMock.Setup(x => x.HttpContext.Request.Query[Define.TENANT_ID]).Returns("OpenAuthDBContext");
serviceCollection.AddScoped(x => httpContextAccessorMock.Object);
// 测试my sql // 测试my sql
serviceCollection.AddDbContext<OpenAuthDBContext>(options => serviceCollection.AddDbContext<OpenAuthDBContext>(options =>
options.UseMySql("server=127.0.0.1;user id=root;database=openauthdb;password=000000")); options.UseMySql("server=127.0.0.1;user id=root;database=openauthdb;password=000000"));

View File

@ -1,6 +1,7 @@
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Reflection; using System.Reflection;
using Infrastructure;
using Infrastructure.Cache; using Infrastructure.Cache;
using Infrastructure.Provider; using Infrastructure.Provider;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;

View File

@ -23,10 +23,6 @@ namespace OpenAuth.App.Test
cachemock.Setup(x => x.Get<UserAuthSession>("tokentest")).Returns(new UserAuthSession { Account = Define.SYSTEM_USERNAME }); cachemock.Setup(x => x.Get<UserAuthSession>("tokentest")).Returns(new UserAuthSession { Account = Define.SYSTEM_USERNAME });
services.AddScoped(x => cachemock.Object); services.AddScoped(x => cachemock.Object);
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
httpContextAccessorMock.Setup(x => x.HttpContext.Request.Query[Define.TOKEN_NAME]).Returns("tokentest");
services.AddScoped(x => httpContextAccessorMock.Object);
var logMock = new Mock<ILogger<FileApp>>(); var logMock = new Mock<ILogger<FileApp>>();
services.AddScoped(x => logMock.Object); services.AddScoped(x => logMock.Object);

View File

@ -1,4 +1,5 @@
using System.Net.Http; using System.Net.Http;
using Infrastructure;
using Infrastructure.Cache; using Infrastructure.Cache;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using NUnit.Framework; using NUnit.Framework;

View File

@ -1,4 +1,5 @@
using Infrastructure.Cache; using Infrastructure;
using Infrastructure.Cache;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using NUnit.Framework; using NUnit.Framework;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Castle.Core.Internal; using Castle.Core.Internal;
using Infrastructure;
using Infrastructure.Extensions; using Infrastructure.Extensions;
using OpenAuth.App.Interface; using OpenAuth.App.Interface;
using OpenAuth.App.Request; using OpenAuth.App.Request;

View File

@ -6,6 +6,7 @@ using IdentityServer4.Extensions;
using IdentityServer4.Models; using IdentityServer4.Models;
using IdentityServer4.Services; using IdentityServer4.Services;
using IdentityServer4.Test; using IdentityServer4.Test;
using Infrastructure;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using OpenAuth.App; using OpenAuth.App;
using OpenAuth.Repository.Domain; using OpenAuth.Repository.Domain;

View File

@ -11,6 +11,7 @@ using IdentityServer4.Extensions;
using IdentityServer4.Models; using IdentityServer4.Models;
using IdentityServer4.Services; using IdentityServer4.Services;
using IdentityServer4.Stores; using IdentityServer4.Stores;
using Infrastructure;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Security.Claims; using System.Security.Claims;
using IdentityModel; using IdentityModel;
using IdentityServer4.Test; using IdentityServer4.Test;
using Infrastructure;
using OpenAuth.App; using OpenAuth.App;
namespace OpenAuth.IdentityServer.Quickstart namespace OpenAuth.IdentityServer.Quickstart

View File

@ -3,6 +3,7 @@
using Autofac; using Autofac;
using Infrastructure;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;

View File

@ -13,6 +13,7 @@
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.3" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.3" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="MySql.Data" Version="8.0.13" /> <PackageReference Include="MySql.Data" Version="8.0.13" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />

View File

@ -1,7 +1,9 @@
using System; using Infrastructure;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.Options;
using OpenAuth.Repository.Domain; using OpenAuth.Repository.Domain;
using OpenAuth.Repository.QueryObj; using OpenAuth.Repository.QueryObj;
@ -12,19 +14,62 @@ namespace OpenAuth.Repository
{ {
private ILoggerFactory _LoggerFactory; private ILoggerFactory _LoggerFactory;
private IHttpContextAccessor _httpContextAccessor;
private IConfiguration _configuration;
private IOptions<AppSetting> _appConfiguration;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) public OpenAuthDBContext(DbContextOptions<OpenAuthDBContext> options, ILoggerFactory loggerFactory,
{ IHttpContextAccessor httpContextAccessor, IConfiguration configuration, IOptions<AppSetting> appConfiguration)
optionsBuilder.EnableSensitiveDataLogging (true); //允许打印参数
optionsBuilder.UseLoggerFactory (_LoggerFactory);
base.OnConfiguring (optionsBuilder);
}
public OpenAuthDBContext(DbContextOptions<OpenAuthDBContext> options, ILoggerFactory loggerFactory)
: base(options) : base(options)
{ {
_LoggerFactory = loggerFactory; _LoggerFactory = loggerFactory;
_httpContextAccessor = httpContextAccessor;
_configuration = configuration;
_appConfiguration = appConfiguration;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.EnableSensitiveDataLogging(true); //允许打印参数
optionsBuilder.UseLoggerFactory(_LoggerFactory);
InitTenant(optionsBuilder);
base.OnConfiguring(optionsBuilder);
}
//初始化多租户信息根据租户id调整数据库
private void InitTenant(DbContextOptionsBuilder optionsBuilder)
{
if (_httpContextAccessor == null || _httpContextAccessor.HttpContext == null)
{
return;
}
//读取多租户ID
string tenantId = _httpContextAccessor.HttpContext.Request.Query[Define.TENANT_ID];
if (string.IsNullOrEmpty(tenantId))
{
tenantId = _httpContextAccessor.HttpContext.Request.Headers[Define.TENANT_ID];
}
//如果没有租户id或租户用的是默认的OpenAuthDBContext,则不做任何调整
if (string.IsNullOrEmpty(tenantId) || tenantId == "OpenAuthDBContext")
{
return;
}
string connect = _configuration.GetConnectionString(tenantId);
if (string.IsNullOrEmpty(connect)) return;
var dbType =_appConfiguration.Value.DbType;
if (dbType == Define.DBTYPE_SQLSERVER)
{
optionsBuilder.UseSqlServer(connect);
}
else //mysql
{
optionsBuilder.UseMySql(connect);
}
} }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)

View File

@ -1,8 +1,13 @@
using System.Reflection; using System.Reflection;
using Autofac; using Autofac;
using Autofac.Extensions.DependencyInjection; using Autofac.Extensions.DependencyInjection;
using Infrastructure;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework; using NUnit.Framework;
using OpenAuth.Repository.Interface; using OpenAuth.Repository.Interface;
@ -26,6 +31,22 @@ namespace OpenAuth.Repository.Test
serviceCollection.AddScoped(typeof(IRepository<,>), typeof(BaseRepository<,>)); serviceCollection.AddScoped(typeof(IRepository<,>), typeof(BaseRepository<,>));
serviceCollection.AddScoped(typeof(IUnitWork<>), typeof(UnitWork<>)); serviceCollection.AddScoped(typeof(IUnitWork<>), typeof(UnitWork<>));
//模拟配置文件
var optionMock = new Mock<IOptions<AppSetting>>();
optionMock.Setup(x => x.Value).Returns(new AppSetting { DbType = Define.DBTYPE_MYSQL });
serviceCollection.AddScoped(x => optionMock.Object);
//模拟多租户id
var configMock = new Mock<IConfiguration>();
configMock.Setup(x => x.GetSection("ConnectionStrings")[Define.TENANT_ID]).Returns("");
serviceCollection.AddScoped(x => configMock.Object);
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
httpContextAccessorMock.Setup(x => x.HttpContext.Request.Query[Define.TOKEN_NAME]).Returns("tokentest");
httpContextAccessorMock.Setup(x => x.HttpContext.Request.Query[Define.TENANT_ID]).Returns("OpenAuthDBContext");
serviceCollection.AddScoped(x => httpContextAccessorMock.Object);
serviceCollection.AddDbContext<OpenAuthDBContext>(options => serviceCollection.AddDbContext<OpenAuthDBContext>(options =>
options.UseSqlServer("Data Source=.;Initial Catalog=OpenAuthDB;User=sa;Password=000000;Integrated Security=True")); options.UseSqlServer("Data Source=.;Initial Catalog=OpenAuthDB;User=sa;Password=000000;Integrated Security=True"));

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Infrastructure;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;

View File

@ -7,6 +7,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Infrastructure;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;

View File

@ -24,7 +24,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="log4net" Version="2.0.8" /> <PackageReference Include="log4net" Version="2.0.12" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" /> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.2" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.2" /> <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.2" />

View File

@ -34,11 +34,6 @@ namespace OpenAuth.WebApi.Test
cachemock.Setup(x => x.Get<UserAuthSession>("tokentest")).Returns(new UserAuthSession{Account = "admin"}); cachemock.Setup(x => x.Get<UserAuthSession>("tokentest")).Returns(new UserAuthSession{Account = "admin"});
services.AddScoped(x => cachemock.Object); services.AddScoped(x => cachemock.Object);
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
httpContextAccessorMock.Setup(x => x.HttpContext.Request.Query[Define.TOKEN_NAME]).Returns("tokentest");
services.AddScoped(x => httpContextAccessorMock.Object);
services.AddMvc().AddControllersAsServices(); services.AddMvc().AddControllersAsServices();
services.AddScoped<CheckController>(); services.AddScoped<CheckController>();