这是基于vue-vben-admin 模板适用于abp Vnext的前端管理项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

461 lines
18 KiB

using LINGYUN.Abp.IdentityServer.IdentityResources;
using OpenIddict.Abstractions;
using System.Globalization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.ApiScopes;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement;
namespace LY.MicroService.Applications.Single.DataSeeder;
public class ClientDataSeederContributor : IDataSeedContributor, ITransientDependency
{
private readonly IOpenIddictApplicationManager _applicationManager;
private readonly IOpenIddictScopeManager _scopeManager;
private readonly IClientRepository _clientRepository;
private readonly IApiResourceRepository _apiResourceRepository;
private readonly IApiScopeRepository _apiScopeRepository;
private readonly ICustomIdentityResourceDataSeeder _customIdentityResourceDataSeeder;
private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder;
private readonly IGuidGenerator _guidGenerator;
private readonly IPermissionDataSeeder _permissionDataSeeder;
private readonly IConfiguration _configuration;
private readonly ICurrentTenant _currentTenant;
public ClientDataSeederContributor(
IOpenIddictApplicationManager applicationManager,
IOpenIddictScopeManager scopeManager,
IClientRepository clientRepository,
IApiResourceRepository apiResourceRepository,
IApiScopeRepository apiScopeRepository,
ICustomIdentityResourceDataSeeder customIdentityResourceDataSeeder,
IIdentityResourceDataSeeder identityResourceDataSeeder,
IGuidGenerator guidGenerator,
IPermissionDataSeeder permissionDataSeeder,
IConfiguration configuration,
ICurrentTenant currentTenant)
{
_applicationManager = applicationManager;
_scopeManager = scopeManager;
_clientRepository = clientRepository;
_apiResourceRepository = apiResourceRepository;
_apiScopeRepository = apiScopeRepository;
_customIdentityResourceDataSeeder = customIdentityResourceDataSeeder;
_identityResourceDataSeeder = identityResourceDataSeeder;
_guidGenerator = guidGenerator;
_permissionDataSeeder = permissionDataSeeder;
_configuration = configuration;
_currentTenant = currentTenant;
}
public async virtual Task SeedAsync(DataSeedContext context)
{
using (_currentTenant.Change(context.TenantId))
{
if (_configuration.GetValue<bool>("AuthServer:UseOpenIddict"))
{
await SeedOpenIddictAsync();
return;
}
await SeedIdentityServerAsync();
}
}
#region OpenIddict
private async Task SeedOpenIddictAsync()
{
await CreateScopeAsync("lingyun-abp-application");
await CreateApplicationAsync("lingyun-abp-application");
}
private async Task CreateScopeAsync(string scope)
{
if (await _scopeManager.FindByNameAsync(scope) == null)
{
await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor()
{
Name = scope,
DisplayName = scope + " access",
DisplayNames =
{
[CultureInfo.GetCultureInfo("zh-Hans")] = "Abp API 应用程序访问",
[CultureInfo.GetCultureInfo("en")] = "Abp API Application Access"
},
Resources =
{
scope
}
});
}
}
private async Task CreateApplicationAsync(string scope)
{
var configurationSection = _configuration.GetSection("OpenIddict:Applications");
var vueClientId = configurationSection["VueAdmin:ClientId"];
if (!vueClientId.IsNullOrWhiteSpace())
{
var vueClientRootUrl = configurationSection["VueAdmin:RootUrl"].EnsureEndsWith('/');
if (await _applicationManager.FindByClientIdAsync(vueClientId) == null)
{
await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = vueClientId,
ClientSecret = "1q2w3e*",
ConsentType = OpenIddictConstants.ConsentTypes.Explicit,
DisplayName = "Abp Vue Admin Client",
PostLogoutRedirectUris =
{
new Uri(vueClientRootUrl + "signout-callback-oidc"),
new Uri(vueClientRootUrl)
},
RedirectUris =
{
new Uri(vueClientRootUrl + "/signin-oidc"),
new Uri(vueClientRootUrl)
},
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.Endpoints.Device,
OpenIddictConstants.Permissions.Endpoints.Introspection,
OpenIddictConstants.Permissions.Endpoints.Revocation,
OpenIddictConstants.Permissions.Endpoints.Logout,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.Implicit,
OpenIddictConstants.Permissions.GrantTypes.Password,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.GrantTypes.DeviceCode,
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials,
OpenIddictConstants.Permissions.ResponseTypes.Code,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeToken,
OpenIddictConstants.Permissions.ResponseTypes.IdToken,
OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.None,
OpenIddictConstants.Permissions.ResponseTypes.Token,
OpenIddictConstants.Permissions.Scopes.Roles,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Address,
OpenIddictConstants.Permissions.Scopes.Phone,
OpenIddictConstants.Permissions.Prefixes.Scope + scope
}
});
var vueClientPermissions = new string[1]
{
"AbpIdentity.UserLookup"
};
await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, vueClientId, vueClientPermissions);
}
}
var internalServiceClientId = configurationSection["InternalService:ClientId"];
if (!internalServiceClientId.IsNullOrWhiteSpace())
{
if (await _applicationManager.FindByClientIdAsync(internalServiceClientId) == null)
{
await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = internalServiceClientId,
ClientSecret = "1q2w3e*",
ConsentType = OpenIddictConstants.ConsentTypes.Explicit,
DisplayName = "Abp Vue Admin Client",
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.Endpoints.Device,
OpenIddictConstants.Permissions.Endpoints.Introspection,
OpenIddictConstants.Permissions.Endpoints.Revocation,
OpenIddictConstants.Permissions.Endpoints.Logout,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.Implicit,
OpenIddictConstants.Permissions.GrantTypes.Password,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.GrantTypes.DeviceCode,
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials,
OpenIddictConstants.Permissions.ResponseTypes.Code,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeToken,
OpenIddictConstants.Permissions.ResponseTypes.IdToken,
OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.None,
OpenIddictConstants.Permissions.ResponseTypes.Token,
OpenIddictConstants.Permissions.Scopes.Roles,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Address,
OpenIddictConstants.Permissions.Scopes.Phone,
OpenIddictConstants.Permissions.Prefixes.Scope + scope
}
});
var internalServicePermissions = new string[2]
{
"AbpIdentity.UserLookup","AbpIdentity.Users"
};
await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, internalServiceClientId, internalServicePermissions);
}
}
}
#endregion
#region IdentityServer
private async Task SeedIdentityServerAsync()
{
await _identityResourceDataSeeder.CreateStandardResourcesAsync();
await _customIdentityResourceDataSeeder.CreateCustomResourcesAsync();
await CreateApiResourcesAsync();
await CreateApiScopesAsync();
await CreateClientsAsync();
}
private async Task CreateApiScopesAsync()
{
await CreateApiScopeAsync("lingyun-abp-application");
}
private async Task CreateApiResourcesAsync()
{
var commonApiUserClaims = new[]
{
"email",
"email_verified",
"name",
"phone_number",
"phone_number_verified",
"role"
};
await CreateApiResourceAsync("lingyun-abp-application", commonApiUserClaims);
}
private async Task<ApiResource> CreateApiResourceAsync(string name, IEnumerable<string> claims, IEnumerable<string> secrets = null)
{
var apiResource = await _apiResourceRepository.FindByNameAsync(name);
if (apiResource == null)
{
apiResource = await _apiResourceRepository.InsertAsync(
new ApiResource(
_guidGenerator.Create(),
name,
name + " API"
),
autoSave: true
);
}
foreach (var claim in claims)
{
if (apiResource.FindClaim(claim) == null)
{
apiResource.AddUserClaim(claim);
}
}
if (secrets != null)
{
foreach (var secret in secrets)
{
if (apiResource.FindSecret(secret) == null)
{
apiResource.AddSecret(secret);
}
}
}
return await _apiResourceRepository.UpdateAsync(apiResource);
}
private async Task<ApiScope> CreateApiScopeAsync(string name)
{
var apiScope = await _apiScopeRepository.FindByNameAsync(name);
if (apiScope == null)
{
apiScope = await _apiScopeRepository.InsertAsync(
new ApiScope(
_guidGenerator.Create(),
name,
name + " API"
),
autoSave: true
);
}
return apiScope;
}
private async Task CreateClientsAsync()
{
string commonSecret = IdentityServer4.Models.HashExtensions.Sha256("1q2w3e*");
var commonScopes = new[]
{
"email",
"openid",
"profile",
"role",
"phone",
"address",
"offline_access" // 加上刷新,
};
var configurationSection = _configuration.GetSection("IdentityServer:Clients");
var vueClientId = configurationSection["VueAdmin:ClientId"];
if (!vueClientId.IsNullOrWhiteSpace())
{
var vueClientPermissions = new string[1]
{
"AbpIdentity.UserLookup"
};
var vueClientRootUrl = configurationSection["VueAdmin:RootUrl"].EnsureEndsWith('/');
await CreateClientAsync(
vueClientId,
commonScopes.Union(new[] { "lingyun-abp-application" }),
new[] { "password", "client_credentials", "implicit", "phone_verify", "wx-mp" },
commonSecret,
redirectUri: $"{vueClientRootUrl}signin-oidc",
postLogoutRedirectUri: $"{vueClientRootUrl}signout-callback-oidc",
corsOrigins: configurationSection["CorsOrigins"],
permissions: vueClientPermissions
);
}
// InternalService 内部服务间通讯客户端,必要的话需要在前端指定它拥有所有权限,当前项目仅预置用户查询权限
var internalServiceClientId = configurationSection["InternalService:ClientId"];
if (!internalServiceClientId.IsNullOrWhiteSpace())
{
var internalServicePermissions = new string[2]
{
"AbpIdentity.UserLookup","AbpIdentity.Users"
};
await CreateClientAsync(
internalServiceClientId,
commonScopes.Union(new[] { "lingyun-abp-application" }),
new[] { "client_credentials" },
commonSecret,
permissions: internalServicePermissions
);
}
}
private async Task<Client> CreateClientAsync(
string name,
IEnumerable<string> scopes,
IEnumerable<string> grantTypes,
string secret,
string redirectUri = null,
string postLogoutRedirectUri = null,
IEnumerable<string> permissions = null,
string corsOrigins = null)
{
var client = await _clientRepository.FindByClientIdAsync(name);
if (client == null)
{
client = await _clientRepository.InsertAsync(
new Client(
_guidGenerator.Create(),
name
)
{
ClientName = name,
ProtocolType = "oidc",
Description = name,
AlwaysIncludeUserClaimsInIdToken = true,
AllowOfflineAccess = true,
AbsoluteRefreshTokenLifetime = 10800, //3 hours
AccessTokenLifetime = 7200, //2 hours
AuthorizationCodeLifetime = 300,
IdentityTokenLifetime = 300,
RequireConsent = false
},
autoSave: true
);
}
foreach (var scope in scopes)
{
if (client.FindScope(scope) == null)
{
client.AddScope(scope);
}
}
foreach (var grantType in grantTypes)
{
if (client.FindGrantType(grantType) == null)
{
client.AddGrantType(grantType);
}
}
if (client.FindSecret(secret) == null)
{
client.AddSecret(secret);
}
if (redirectUri != null)
{
if (client.FindRedirectUri(redirectUri) == null)
{
client.AddRedirectUri(redirectUri);
}
}
if (postLogoutRedirectUri != null)
{
if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null)
{
client.AddPostLogoutRedirectUri(postLogoutRedirectUri);
}
}
if (corsOrigins != null)
{
var corsOriginsSplit = corsOrigins.Split(";");
foreach (var corsOrigin in corsOriginsSplit)
{
if (client.FindCorsOrigin(corsOrigin) == null)
{
client.AddCorsOrigin(corsOrigin);
}
}
}
if (permissions != null)
{
await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, name, permissions);
}
return await _clientRepository.UpdateAsync(client);
}
#endregion
}