diff --git a/Readme.md b/Readme.md index 714afbf1..604050f2 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ 
- [Abp Vnext Pro](https://github.com/WangJunZzz/abp-vnext-pro) 的 Vue3 实现版本 开箱即用的中后台前端/设计解决方案 +[Abp Vnext Pro](https://github.com/WangJunZzz/abp-vnext-pro) 的 Vue3 实现版本 开箱即用的中后台前端/设计解决方案 @@ -46,7 +46,7 @@ - [x] 单元测试 - [x] ES 日志 - [x] Setting 管理 -- [ ] 多租户 +- [x] 多租户 - [ ] 组织机构 ### 使用 @@ -55,9 +55,6 @@ ![](https://blog-resouce.oss-cn-shenzhen.aliyuncs.com/images/abp/gui.png) - - - #### 参与贡献 非常欢迎你的贡献,你可以通过以下方式和我们一起共建 :star2:: diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs index d006cbf0..ba3ebb57 100644 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs +++ b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs @@ -104,7 +104,7 @@ namespace CompanyName.ProjectName { app.UseMultiTenancy(); } - + app.UseAuthorization(); app.UseSwagger(); diff --git a/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/ProjectNameIdentityServerModule.cs b/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/ProjectNameIdentityServerModule.cs index f7efa2ad..b2b48991 100644 --- a/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/ProjectNameIdentityServerModule.cs +++ b/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/ProjectNameIdentityServerModule.cs @@ -11,6 +11,9 @@ using CompanyName.ProjectName.EntityFrameworkCore; using CompanyName.ProjectName.Extensions; using CompanyName.ProjectName.Localization; using CompanyName.ProjectName.MultiTenancy; +using IdentityServer4.Configuration; +using IdentityServer4.Extensions; +using IdentityServer4.Models; using StackExchange.Redis; using Volo.Abp; using Volo.Abp.Account; @@ -43,7 +46,7 @@ namespace CompanyName.ProjectName typeof(AbpAspNetCoreMvcUiBasicThemeModule), typeof(ProjectNameEntityFrameworkCoreDbMigrationsModule), typeof(AbpAspNetCoreSerilogModule) - )] + )] public class ProjectNameIdentityServerModule : AbpModule { private const string DefaultCorsPolicyName = "Default"; @@ -60,7 +63,7 @@ namespace CompanyName.ProjectName .AddBaseTypes( typeof(AbpUiResource) ); - + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); @@ -80,10 +83,7 @@ namespace CompanyName.ProjectName { options.StyleBundles.Configure( BasicThemeBundles.Styles.Global, - bundle => - { - bundle.AddFiles("/global-styles.css"); - } + bundle => { bundle.AddFiles("/global-styles.css"); } ); }); @@ -96,7 +96,6 @@ namespace CompanyName.ProjectName if (hostingEnvironment.IsDevelopment()) { Configure(options => { options.FileSets.AddEmbedded(); }); - } Configure(options => @@ -108,15 +107,9 @@ namespace CompanyName.ProjectName options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password"; }); - Configure(options => - { - options.IsJobExecutionEnabled = false; - }); + Configure(options => { options.IsJobExecutionEnabled = false; }); - Configure(options => - { - options.KeyPrefix = "ProjectName:"; - }); + Configure(options => { options.KeyPrefix = "ProjectName:"; }); if (!hostingEnvironment.IsDevelopment()) { @@ -169,18 +162,19 @@ namespace CompanyName.ProjectName app.UseCors(DefaultCorsPolicyName); app.UseCookiePolicy(); app.UseAuthentication(); - + if (MultiTenancyConsts.IsEnabled) { app.UseMultiTenancy(); } - + app.UseUnitOfWork(); app.UseIdentityServer(); app.UseAuthorization(); app.UseAuditing(); app.UseAbpSerilogEnrichers(); app.UseConfiguredEndpoints(); + } } -} +} \ No newline at end of file diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Permissions/ProjectNamePermissionDefinitionProvider.cs b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Permissions/ProjectNamePermissionDefinitionProvider.cs index eb91a766..65b68d35 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Permissions/ProjectNamePermissionDefinitionProvider.cs +++ b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Permissions/ProjectNamePermissionDefinitionProvider.cs @@ -2,6 +2,7 @@ using Volo.Abp.Authorization.Permissions; using Volo.Abp.Identity; using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; namespace CompanyName.ProjectName.Permissions { @@ -20,52 +21,56 @@ namespace CompanyName.ProjectName.Permissions abpIdentityGroup.AddPermission(ProjectNamePermissions.SystemManagement.Hangfire, L("Permission:HangfireManagement")); var capManagement = abpIdentityGroup.AddPermission(ProjectNamePermissions.SystemManagement.Cap, L("Permission:CapManagement")); - + #region IdentityServer + // multiTenancySide: MultiTenancySides.Host 只有host租户才有权限 var identityServerManagementGroup = - context.AddGroup(ProjectNamePermissions.IdentityServer.IdentityServerManagement, L("Permission:IdentityServerManagement")); + context.AddGroup(ProjectNamePermissions.IdentityServer.IdentityServerManagement, L("Permission:IdentityServerManagement"), + multiTenancySide: MultiTenancySides.Host); var clientManagment = identityServerManagementGroup.AddPermission(ProjectNamePermissions.IdentityServer.Client.Default, - L("Permission:IdentityServerManagement:Client")); + L("Permission:IdentityServerManagement:Client"),multiTenancySide: MultiTenancySides.Host); clientManagment.AddChild(ProjectNamePermissions.IdentityServer.Client.Create, - L("Permission:Create")); + L("Permission:Create"),multiTenancySide: MultiTenancySides.Host); clientManagment.AddChild(ProjectNamePermissions.IdentityServer.Client.Update, - L("Permission:Update")); + L("Permission:Update"),multiTenancySide: MultiTenancySides.Host); clientManagment.AddChild(ProjectNamePermissions.IdentityServer.Client.Delete, - L("Permission:Delete")); + L("Permission:Delete"),multiTenancySide: MultiTenancySides.Host); clientManagment.AddChild(ProjectNamePermissions.IdentityServer.Client.Enable, - L("Permission:Enable")); - - - var apiResourceManagment = identityServerManagementGroup.AddPermission(ProjectNamePermissions.IdentityServer.ApiResource.Default, - L("Permission:IdentityServerManagement:ApiResource")); + L("Permission:Enable"),multiTenancySide: MultiTenancySides.Host); + + + var apiResourceManagment = identityServerManagementGroup.AddPermission( + ProjectNamePermissions.IdentityServer.ApiResource.Default, + L("Permission:IdentityServerManagement:ApiResource"),multiTenancySide: MultiTenancySides.Host); apiResourceManagment.AddChild(ProjectNamePermissions.IdentityServer.ApiResource.Create, - L("Permission:Create")); + L("Permission:Create"),multiTenancySide: MultiTenancySides.Host); apiResourceManagment.AddChild(ProjectNamePermissions.IdentityServer.ApiResource.Update, - L("Permission:Update")); + L("Permission:Update"),multiTenancySide: MultiTenancySides.Host); apiResourceManagment.AddChild(ProjectNamePermissions.IdentityServer.ApiResource.Delete, - L("Permission:Delete")); + L("Permission:Delete"),multiTenancySide: MultiTenancySides.Host); var apiScopeManagment = identityServerManagementGroup.AddPermission(ProjectNamePermissions.IdentityServer.ApiScope.Default, - L("Permission:IdentityServerManagement:ApiScope")); + L("Permission:IdentityServerManagement:ApiScope"),multiTenancySide: MultiTenancySides.Host); apiScopeManagment.AddChild(ProjectNamePermissions.IdentityServer.ApiScope.Create, - L("Permission:Create")); + L("Permission:Create"),multiTenancySide: MultiTenancySides.Host); apiScopeManagment.AddChild(ProjectNamePermissions.IdentityServer.ApiScope.Update, - L("Permission:Update")); + L("Permission:Update"),multiTenancySide: MultiTenancySides.Host); apiScopeManagment.AddChild(ProjectNamePermissions.IdentityServer.ApiScope.Delete, - L("Permission:Delete")); - + L("Permission:Delete"),multiTenancySide: MultiTenancySides.Host); - var identityResourcesManagment = identityServerManagementGroup.AddPermission(ProjectNamePermissions.IdentityServer.IdentityResources.Default, - L("Permission:IdentityServerManagement:IdentityResources")); + + var identityResourcesManagment = identityServerManagementGroup.AddPermission( + ProjectNamePermissions.IdentityServer.IdentityResources.Default, + L("Permission:IdentityServerManagement:IdentityResources"),multiTenancySide: MultiTenancySides.Host); identityResourcesManagment.AddChild(ProjectNamePermissions.IdentityServer.IdentityResources.Create, - L("Permission:Create")); + L("Permission:Create"),multiTenancySide: MultiTenancySides.Host); identityResourcesManagment.AddChild(ProjectNamePermissions.IdentityServer.IdentityResources.Update, - L("Permission:Update")); + L("Permission:Update"),multiTenancySide: MultiTenancySides.Host); identityResourcesManagment.AddChild(ProjectNamePermissions.IdentityServer.IdentityResources.Delete, - L("Permission:Delete")); - + L("Permission:Delete"),multiTenancySide: MultiTenancySides.Host); + #endregion } diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Domain.Shared/ProjectNameDomainSharedModule.cs b/aspnet-core/services/src/CompanyName.ProjectName.Domain.Shared/ProjectNameDomainSharedModule.cs index 283f66cd..17459c3c 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Domain.Shared/ProjectNameDomainSharedModule.cs +++ b/aspnet-core/services/src/CompanyName.ProjectName.Domain.Shared/ProjectNameDomainSharedModule.cs @@ -45,7 +45,7 @@ namespace CompanyName.ProjectName Configure(options => { options.Resources - .Add("en") + .Add("zh-Hans") .AddBaseTypes(typeof(AbpValidationResource)) .AddVirtualJson("/Localization/ProjectName"); diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs index f760d8ce..774c8c2c 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs +++ b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs @@ -147,9 +147,9 @@ namespace CompanyName.ProjectName.IdentityServer scopes: commonScopes, grantTypes: new[] {"implicit"}, secret: "1q2w3E*".Sha256(), - redirectUri: "http://localhost:4200/oidc", - postLogoutRedirectUri: "http://localhost:4200/oidc,http://120.24.194.14:8012/oidc", - frontChannelLogoutUri: "http://localhost:4200/oidc", + redirectUri: "http://localhost:4200/oidcSignIn", + postLogoutRedirectUri: "http://localhost:4200/oidcSignOut", + frontChannelLogoutUri: "http://localhost:4200/oidcSignOut", corsOrigins: new[] {"https://localhost:4200", "http://localhost:4200", "http://120.24.194.14:8012"}, requireClientSecret: false ); diff --git a/vben271/index.html b/vben271/index.html index 5b99faf6..47fe929b 100644 --- a/vben271/index.html +++ b/vben271/index.html @@ -8,10 +8,14 @@ name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" /> - + <%= title %> + diff --git a/vben271/src/views/sys/login/OidcSingOut.vue b/vben271/src/views/sys/login/OidcSingOut.vue deleted file mode 100644 index e69de29b..00000000 diff --git a/vben271/src/views/sys/login/SessionTimeoutLogin.vue b/vben271/src/views/sys/login/SessionTimeoutLogin.vue index d1a2f34e..871afc3f 100644 --- a/vben271/src/views/sys/login/SessionTimeoutLogin.vue +++ b/vben271/src/views/sys/login/SessionTimeoutLogin.vue @@ -27,7 +27,6 @@ onMounted(() => { // 记录当前的UserId userId.value = userStore.getUserInfo?.userId; - console.log('Mounted', userStore.getUserInfo); }); onBeforeUnmount(() => { diff --git a/vben271/src/views/sys/login/useLogin.ts b/vben271/src/views/sys/login/useLogin.ts index 95457d6f..8c1e20fe 100644 --- a/vben271/src/views/sys/login/useLogin.ts +++ b/vben271/src/views/sys/login/useLogin.ts @@ -3,6 +3,7 @@ import type { RuleObject } from 'ant-design-vue/lib/form/interface'; import { ref, computed, unref, Ref } from 'vue'; import { useI18n } from '/@/hooks/web/useI18n'; import Oidc from 'oidc-client'; +import { useUserStore } from '/@/store/modules/user'; export enum LoginStateEnum { LOGIN, REGISTER, @@ -115,25 +116,36 @@ export function useFormRules(formData?: Recordable) { return { getFormRules }; } -export function useOidcLogin() { +function getOidcSettings() { const { protocol, hostname, port } = window.location; let currentHost = `${protocol}//${hostname}${port ? `:${port}` : ''}`; const settings: any = { authority: import.meta.env.VITE_AUTH_URL, client_id: 'Vue3', - redirect_uri: currentHost + '/oidc', - post_logout_redirect_uri: import.meta.env.VITE_AUTH_URL + 'signOut', + redirect_uri: currentHost + '/oidcSignIn', + post_logout_redirect_uri: currentHost + '/oidcSignOut', response_type: `id_token token`, scope: 'openid email profile', //silent_redirect_uri: currentHost + '/oidc-silent-renew', automaticSilentRenew: true, // If true oidc-client will try to renew your token when it is about to expire automaticSilentSignin: true, // If true vuex-oidc will try to silently signin unauthenticated users on public routes. Defaults to true }; + return settings; +} +export function useOidcLogin() { + const settings = getOidcSettings(); const mgr = new Oidc.UserManager(settings); mgr.signinRedirect(); } +export async function useOidcLogout() { + const settings = getOidcSettings(); + const mgr = new Oidc.UserManager(settings); + const userStore = useUserStore(); + await mgr.signoutRedirect({ id_token_hint: userStore.userInfo?.idToken }); +} + function createRule(message: string) { return [ { diff --git a/vben271/types/store.d.ts b/vben271/types/store.d.ts index 36a6025f..398a7bf2 100644 --- a/vben271/types/store.d.ts +++ b/vben271/types/store.d.ts @@ -38,6 +38,8 @@ export interface UserInfo { desc?: string; homePath?: string; roles: RoleInfo[]; + isSts: boolean; // 是否通过IdentityServer4登录 + idToken: string; } export interface BeforeMiniState {