Browse Source

Add redis and cors and ids data seed.

pull/11486/head
maliming 5 years ago
parent
commit
20da223f31
No known key found for this signature in database GPG Key ID: 96224957E51C89E
  1. 7
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplate.cs
  2. 340
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/Data/IdentityServerDataSeedContributor.cs
  3. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj
  4. 45
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyProjectNameModule.cs
  5. 38
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/appsettings.json
  6. 340
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Data/IdentityServerDataSeedContributor.cs
  7. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj
  8. 44
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyProjectNameModule.cs
  9. 38
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/appsettings.json

7
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplate.cs

@ -89,7 +89,12 @@ public class AppNoLayersTemplate : AppTemplateBase
RandomizeStringEncryption(context, steps);
UpdateNuGetConfig(context, steps);
ChangeConnectionString(context, steps);
CleanupFolderHierarchy(context, steps);
//CleanupFolderHierarchy(context, steps);
if (context.BuildArgs.UiFramework != UiFramework.Angular)
{
steps.Add(new MoveFolderStep("/aspnet-core/", "/"));
}
return steps;
}

340
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/Data/IdentityServerDataSeedContributor.cs

@ -0,0 +1,340 @@
using IdentityServer4.Models;
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;
using Volo.Abp.Uow;
using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource;
using ApiScope = Volo.Abp.IdentityServer.ApiScopes.ApiScope;
using Client = Volo.Abp.IdentityServer.Clients.Client;
namespace MyCompanyName.MyProjectName.Data;
public class IdentityServerDataSeedContributor : IDataSeedContributor, ITransientDependency
{
private readonly IApiResourceRepository _apiResourceRepository;
private readonly IApiScopeRepository _apiScopeRepository;
private readonly IClientRepository _clientRepository;
private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder;
private readonly IGuidGenerator _guidGenerator;
private readonly IPermissionDataSeeder _permissionDataSeeder;
private readonly IConfiguration _configuration;
private readonly ICurrentTenant _currentTenant;
public IdentityServerDataSeedContributor(
IClientRepository clientRepository,
IApiResourceRepository apiResourceRepository,
IApiScopeRepository apiScopeRepository,
IIdentityResourceDataSeeder identityResourceDataSeeder,
IGuidGenerator guidGenerator,
IPermissionDataSeeder permissionDataSeeder,
IConfiguration configuration,
ICurrentTenant currentTenant)
{
_clientRepository = clientRepository;
_apiResourceRepository = apiResourceRepository;
_apiScopeRepository = apiScopeRepository;
_identityResourceDataSeeder = identityResourceDataSeeder;
_guidGenerator = guidGenerator;
_permissionDataSeeder = permissionDataSeeder;
_configuration = configuration;
_currentTenant = currentTenant;
}
[UnitOfWork]
public virtual async Task SeedAsync(DataSeedContext context)
{
using (_currentTenant.Change(context?.TenantId))
{
await _identityResourceDataSeeder.CreateStandardResourcesAsync();
await CreateApiResourcesAsync();
await CreateApiScopesAsync();
await CreateClientsAsync();
}
}
private async Task CreateApiScopesAsync()
{
await CreateApiScopeAsync("MyProjectName");
}
private async Task CreateApiResourcesAsync()
{
var commonApiUserClaims = new[] {"email", "email_verified", "name", "phone_number", "phone_number_verified", "role"};
await CreateApiResourceAsync("MyProjectName", commonApiUserClaims);
}
private async Task<ApiResource> CreateApiResourceAsync(string name, IEnumerable<string> claims)
{
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);
}
}
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()
{
var commonScopes = new[]
{
"email",
"openid",
"profile",
"role",
"phone",
"address",
"MyProjectName"
};
var configurationSection = _configuration.GetSection("IdentityServer:Clients");
//<TEMPLATE-REMOVE IF-NOT='ui:mvc&&tiered'>
//Web Client
var webClientId = configurationSection["MyProjectName_Web:ClientId"];
if (!webClientId.IsNullOrWhiteSpace())
{
var webClientRootUrl = configurationSection["MyProjectName_Web:RootUrl"].EnsureEndsWith('/');
await CreateClientAsync(
name: webClientId,
scopes: commonScopes,
grantTypes: new[] { "hybrid" },
secret: (configurationSection["MyProjectName_Web:ClientSecret"] ?? "1q2w3e*").Sha256(),
redirectUri: $"{webClientRootUrl}signin-oidc",
postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc",
frontChannelLogoutUri: $"{webClientRootUrl}Account/FrontChannelLogout",
corsOrigins: new[] { webClientRootUrl.RemovePostFix("/") }
);
}
//</TEMPLATE-REMOVE>
//Console Test / Angular Client
var consoleAndAngularClientId = configurationSection["MyProjectName_App:ClientId"];
if (!consoleAndAngularClientId.IsNullOrWhiteSpace())
{
var webClientRootUrl = configurationSection["MyProjectName_App:RootUrl"]?.TrimEnd('/');
await CreateClientAsync(
name: consoleAndAngularClientId,
scopes: commonScopes,
grantTypes: new[] { "password", "client_credentials", "authorization_code" },
secret: (configurationSection["MyProjectName_App:ClientSecret"] ?? "1q2w3e*").Sha256(),
requireClientSecret: false,
redirectUri: webClientRootUrl,
postLogoutRedirectUri: webClientRootUrl,
corsOrigins: new[] { webClientRootUrl.RemovePostFix("/") }
);
}
//<TEMPLATE-REMOVE IF-NOT='ui:blazor'>
// Blazor Client
var blazorClientId = configurationSection["MyProjectName_Blazor:ClientId"];
if (!blazorClientId.IsNullOrWhiteSpace())
{
var blazorRootUrl = configurationSection["MyProjectName_Blazor:RootUrl"].TrimEnd('/');
await CreateClientAsync(
name: blazorClientId,
scopes: commonScopes,
grantTypes: new[] { "authorization_code" },
secret: configurationSection["MyProjectName_Blazor:ClientSecret"]?.Sha256(),
requireClientSecret: false,
redirectUri: $"{blazorRootUrl}/authentication/login-callback",
postLogoutRedirectUri: $"{blazorRootUrl}/authentication/logout-callback",
corsOrigins: new[] { blazorRootUrl.RemovePostFix("/") }
);
}
//</TEMPLATE-REMOVE>
//<TEMPLATE-REMOVE IF-NOT='ui:blazor-server&&tiered'>
//Blazor Server Tiered Client
var blazorServerTieredClientId = configurationSection["MyProjectName_BlazorServerTiered:ClientId"];
if (!blazorServerTieredClientId.IsNullOrWhiteSpace())
{
var blazorServerTieredClientRootUrl = configurationSection["MyProjectName_BlazorServerTiered:RootUrl"].EnsureEndsWith('/');
/* MyProjectName_BlazorServerTiered client is only needed if you created a tiered blazor server
* solution. Otherwise, you can delete this client. */
await CreateClientAsync(
name: blazorServerTieredClientId,
scopes: commonScopes,
grantTypes: new[] { "hybrid" },
secret: (configurationSection["MyProjectName_BlazorServerTiered:ClientSecret"] ?? "1q2w3e*").Sha256(),
redirectUri: $"{blazorServerTieredClientRootUrl}signin-oidc",
postLogoutRedirectUri: $"{blazorServerTieredClientRootUrl}signout-callback-oidc",
frontChannelLogoutUri: $"{blazorServerTieredClientRootUrl}Account/FrontChannelLogout",
corsOrigins: new[] { blazorServerTieredClientRootUrl.RemovePostFix("/") }
);
}
//</TEMPLATE-REMOVE>
// Swagger Client
var swaggerClientId = configurationSection["MyProjectName_Swagger:ClientId"];
if (!swaggerClientId.IsNullOrWhiteSpace())
{
var swaggerRootUrl = configurationSection["MyProjectName_Swagger:RootUrl"].TrimEnd('/');
await CreateClientAsync(
name: swaggerClientId,
scopes: commonScopes,
grantTypes: new[] { "authorization_code" },
secret: configurationSection["MyProjectName_Swagger:ClientSecret"]?.Sha256(),
requireClientSecret: false,
redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html",
corsOrigins: new[] { swaggerRootUrl.RemovePostFix("/") }
);
}
}
private async Task<Client> CreateClientAsync(
string name,
IEnumerable<string> scopes,
IEnumerable<string> grantTypes,
string secret = null,
string redirectUri = null,
string postLogoutRedirectUri = null,
string frontChannelLogoutUri = null,
bool requireClientSecret = true,
bool requirePkce = false,
IEnumerable<string> permissions = null,
IEnumerable<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 = 31536000, //365 days
AccessTokenLifetime = 31536000, //365 days
AuthorizationCodeLifetime = 300,
IdentityTokenLifetime = 300,
RequireConsent = false,
FrontChannelLogoutUri = frontChannelLogoutUri,
RequireClientSecret = requireClientSecret,
RequirePkce = requirePkce
},
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 (!secret.IsNullOrEmpty())
{
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 (permissions != null)
{
await _permissionDataSeeder.SeedAsync(
ClientPermissionValueProvider.ProviderName,
name,
permissions,
null
);
}
if (corsOrigins != null)
{
foreach (var origin in corsOrigins)
{
if (!origin.IsNullOrWhiteSpace() && client.FindCorsOrigin(origin) == null)
{
client.AddCorsOrigin(origin);
}
}
}
return await _clientRepository.UpdateAsync(client);
}
}

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj

@ -16,6 +16,7 @@
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Swashbuckle\Volo.Abp.Swashbuckle.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Caching.StackExchangeRedis\Volo.Abp.Caching.StackExchangeRedis.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Authentication.JwtBearer\Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Serilog\Volo.Abp.AspNetCore.Serilog.csproj" />
</ItemGroup>
@ -68,6 +69,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="6.0.1" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="6.0.1" />
</ItemGroup>
<ItemGroup>

45
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyProjectNameModule.cs

@ -1,6 +1,9 @@
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.OpenApi.Models;
using MyCompanyName.MyProjectName.Data;
using MyCompanyName.MyProjectName.Localization;
using StackExchange.Redis;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web;
@ -13,7 +16,7 @@ using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.AuditLogging.MongoDB;
using Volo.Abp.Autofac;
using Volo.Abp.AutoMapper;
using Volo.Abp.MongoDB;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.FeatureManagement;
using Volo.Abp.FeatureManagement.MongoDB;
using Volo.Abp.Identity;
@ -44,6 +47,7 @@ namespace MyCompanyName.MyProjectName;
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpAutofacModule),
typeof(AbpAutoMapperModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpSwashbuckleModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpAspNetCoreSerilogModule),
@ -110,6 +114,8 @@ public class MyProjectNameModule : AbpModule
ConfigureAutoApiControllers();
ConfigureLocalization();
ConfigureAuthentication(context.Services, configuration);
ConfigureCors(context, configuration);
ConfigureDataProtection(context, configuration, hostingEnvironment);
ConfigureMongoDB(context);
}
@ -210,6 +216,41 @@ public class MyProjectNameModule : AbpModule
});
}
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
}
private void ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration,
IWebHostEnvironment hostingEnvironment)
{
var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("MyProjectName");
if (!hostingEnvironment.IsDevelopment())
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "MyProjectName-Protection-Keys");
}
}
private void ConfigureMongoDB(ServiceConfigurationContext context)
{
context.Services.AddMongoDbContext<MyProjectNameDbContext>(options =>

38
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/appsettings.json

@ -1,15 +1,49 @@
{
"App": {
"SelfUrl": "https://localhost:44305"
"SelfUrl": "https://localhost:44305",
"CorsOrigins": "https://*.MyProjectName.com,http://localhost:4200"
},
"ConnectionStrings": {
"Default": "mongodb://localhost:27017/MyProjectName"
},
"Redis": {
"Configuration": "127.0.0.1"
},
"AuthServer": {
"Authority": "https://localhost:44305",
"RequireHttpsMetadata": "false"
"RequireHttpsMetadata": "false",
"SwaggerClientId": "MyProjectName_Swagger",
"SwaggerClientSecret": "1q2w3e*"
},
"StringEncryption": {
"DefaultPassPhrase": "gsKnGZ041HLL4IM8"
},
"IdentityServer": {
"Clients": {
"MyProjectName_Web": {
"ClientId": "MyProjectName_Web",
"ClientSecret": "1q2w3e*",
"RootUrl": "https://localhost:44302"
},
"MyProjectName_App": {
"ClientId": "MyProjectName_App",
"ClientSecret": "1q2w3e*",
"RootUrl": "http://localhost:4200"
},
"MyProjectName_Blazor": {
"ClientId": "MyProjectName_Blazor",
"RootUrl": "https://localhost:44307"
},
"MyProjectName_BlazorServerTiered": {
"ClientId": "MyProjectName_BlazorServerTiered",
"ClientSecret": "1q2w3e*",
"RootUrl": "https://localhost:44314"
},
"MyProjectName_Swagger": {
"ClientId": "MyProjectName_Swagger",
"ClientSecret": "1q2w3e*",
"RootUrl": "https://localhost:44305"
}
}
}
}

340
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Data/IdentityServerDataSeedContributor.cs

@ -0,0 +1,340 @@
using IdentityServer4.Models;
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;
using Volo.Abp.Uow;
using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource;
using ApiScope = Volo.Abp.IdentityServer.ApiScopes.ApiScope;
using Client = Volo.Abp.IdentityServer.Clients.Client;
namespace MyCompanyName.MyProjectName.Data;
public class IdentityServerDataSeedContributor : IDataSeedContributor, ITransientDependency
{
private readonly IApiResourceRepository _apiResourceRepository;
private readonly IApiScopeRepository _apiScopeRepository;
private readonly IClientRepository _clientRepository;
private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder;
private readonly IGuidGenerator _guidGenerator;
private readonly IPermissionDataSeeder _permissionDataSeeder;
private readonly IConfiguration _configuration;
private readonly ICurrentTenant _currentTenant;
public IdentityServerDataSeedContributor(
IClientRepository clientRepository,
IApiResourceRepository apiResourceRepository,
IApiScopeRepository apiScopeRepository,
IIdentityResourceDataSeeder identityResourceDataSeeder,
IGuidGenerator guidGenerator,
IPermissionDataSeeder permissionDataSeeder,
IConfiguration configuration,
ICurrentTenant currentTenant)
{
_clientRepository = clientRepository;
_apiResourceRepository = apiResourceRepository;
_apiScopeRepository = apiScopeRepository;
_identityResourceDataSeeder = identityResourceDataSeeder;
_guidGenerator = guidGenerator;
_permissionDataSeeder = permissionDataSeeder;
_configuration = configuration;
_currentTenant = currentTenant;
}
[UnitOfWork]
public virtual async Task SeedAsync(DataSeedContext context)
{
using (_currentTenant.Change(context?.TenantId))
{
await _identityResourceDataSeeder.CreateStandardResourcesAsync();
await CreateApiResourcesAsync();
await CreateApiScopesAsync();
await CreateClientsAsync();
}
}
private async Task CreateApiScopesAsync()
{
await CreateApiScopeAsync("MyProjectName");
}
private async Task CreateApiResourcesAsync()
{
var commonApiUserClaims = new[] {"email", "email_verified", "name", "phone_number", "phone_number_verified", "role"};
await CreateApiResourceAsync("MyProjectName", commonApiUserClaims);
}
private async Task<ApiResource> CreateApiResourceAsync(string name, IEnumerable<string> claims)
{
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);
}
}
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()
{
var commonScopes = new[]
{
"email",
"openid",
"profile",
"role",
"phone",
"address",
"MyProjectName"
};
var configurationSection = _configuration.GetSection("IdentityServer:Clients");
//<TEMPLATE-REMOVE IF-NOT='ui:mvc&&tiered'>
//Web Client
var webClientId = configurationSection["MyProjectName_Web:ClientId"];
if (!webClientId.IsNullOrWhiteSpace())
{
var webClientRootUrl = configurationSection["MyProjectName_Web:RootUrl"].EnsureEndsWith('/');
await CreateClientAsync(
name: webClientId,
scopes: commonScopes,
grantTypes: new[] { "hybrid" },
secret: (configurationSection["MyProjectName_Web:ClientSecret"] ?? "1q2w3e*").Sha256(),
redirectUri: $"{webClientRootUrl}signin-oidc",
postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc",
frontChannelLogoutUri: $"{webClientRootUrl}Account/FrontChannelLogout",
corsOrigins: new[] { webClientRootUrl.RemovePostFix("/") }
);
}
//</TEMPLATE-REMOVE>
//Console Test / Angular Client
var consoleAndAngularClientId = configurationSection["MyProjectName_App:ClientId"];
if (!consoleAndAngularClientId.IsNullOrWhiteSpace())
{
var webClientRootUrl = configurationSection["MyProjectName_App:RootUrl"]?.TrimEnd('/');
await CreateClientAsync(
name: consoleAndAngularClientId,
scopes: commonScopes,
grantTypes: new[] { "password", "client_credentials", "authorization_code" },
secret: (configurationSection["MyProjectName_App:ClientSecret"] ?? "1q2w3e*").Sha256(),
requireClientSecret: false,
redirectUri: webClientRootUrl,
postLogoutRedirectUri: webClientRootUrl,
corsOrigins: new[] { webClientRootUrl.RemovePostFix("/") }
);
}
//<TEMPLATE-REMOVE IF-NOT='ui:blazor'>
// Blazor Client
var blazorClientId = configurationSection["MyProjectName_Blazor:ClientId"];
if (!blazorClientId.IsNullOrWhiteSpace())
{
var blazorRootUrl = configurationSection["MyProjectName_Blazor:RootUrl"].TrimEnd('/');
await CreateClientAsync(
name: blazorClientId,
scopes: commonScopes,
grantTypes: new[] { "authorization_code" },
secret: configurationSection["MyProjectName_Blazor:ClientSecret"]?.Sha256(),
requireClientSecret: false,
redirectUri: $"{blazorRootUrl}/authentication/login-callback",
postLogoutRedirectUri: $"{blazorRootUrl}/authentication/logout-callback",
corsOrigins: new[] { blazorRootUrl.RemovePostFix("/") }
);
}
//</TEMPLATE-REMOVE>
//<TEMPLATE-REMOVE IF-NOT='ui:blazor-server&&tiered'>
//Blazor Server Tiered Client
var blazorServerTieredClientId = configurationSection["MyProjectName_BlazorServerTiered:ClientId"];
if (!blazorServerTieredClientId.IsNullOrWhiteSpace())
{
var blazorServerTieredClientRootUrl = configurationSection["MyProjectName_BlazorServerTiered:RootUrl"].EnsureEndsWith('/');
/* MyProjectName_BlazorServerTiered client is only needed if you created a tiered blazor server
* solution. Otherwise, you can delete this client. */
await CreateClientAsync(
name: blazorServerTieredClientId,
scopes: commonScopes,
grantTypes: new[] { "hybrid" },
secret: (configurationSection["MyProjectName_BlazorServerTiered:ClientSecret"] ?? "1q2w3e*").Sha256(),
redirectUri: $"{blazorServerTieredClientRootUrl}signin-oidc",
postLogoutRedirectUri: $"{blazorServerTieredClientRootUrl}signout-callback-oidc",
frontChannelLogoutUri: $"{blazorServerTieredClientRootUrl}Account/FrontChannelLogout",
corsOrigins: new[] { blazorServerTieredClientRootUrl.RemovePostFix("/") }
);
}
//</TEMPLATE-REMOVE>
// Swagger Client
var swaggerClientId = configurationSection["MyProjectName_Swagger:ClientId"];
if (!swaggerClientId.IsNullOrWhiteSpace())
{
var swaggerRootUrl = configurationSection["MyProjectName_Swagger:RootUrl"].TrimEnd('/');
await CreateClientAsync(
name: swaggerClientId,
scopes: commonScopes,
grantTypes: new[] { "authorization_code" },
secret: configurationSection["MyProjectName_Swagger:ClientSecret"]?.Sha256(),
requireClientSecret: false,
redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html",
corsOrigins: new[] { swaggerRootUrl.RemovePostFix("/") }
);
}
}
private async Task<Client> CreateClientAsync(
string name,
IEnumerable<string> scopes,
IEnumerable<string> grantTypes,
string secret = null,
string redirectUri = null,
string postLogoutRedirectUri = null,
string frontChannelLogoutUri = null,
bool requireClientSecret = true,
bool requirePkce = false,
IEnumerable<string> permissions = null,
IEnumerable<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 = 31536000, //365 days
AccessTokenLifetime = 31536000, //365 days
AuthorizationCodeLifetime = 300,
IdentityTokenLifetime = 300,
RequireConsent = false,
FrontChannelLogoutUri = frontChannelLogoutUri,
RequireClientSecret = requireClientSecret,
RequirePkce = requirePkce
},
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 (!secret.IsNullOrEmpty())
{
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 (permissions != null)
{
await _permissionDataSeeder.SeedAsync(
ClientPermissionValueProvider.ProviderName,
name,
permissions,
null
);
}
if (corsOrigins != null)
{
foreach (var origin in corsOrigins)
{
if (!origin.IsNullOrWhiteSpace() && client.FindCorsOrigin(origin) == null)
{
client.AddCorsOrigin(origin);
}
}
}
return await _clientRepository.UpdateAsync(client);
}
}

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj

@ -16,6 +16,7 @@
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Swashbuckle\Volo.Abp.Swashbuckle.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Caching.StackExchangeRedis\Volo.Abp.Caching.StackExchangeRedis.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Authentication.JwtBearer\Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Serilog\Volo.Abp.AspNetCore.Serilog.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.EntityFrameworkCore.SqlServer\Volo.Abp.EntityFrameworkCore.SqlServer.csproj" />
@ -69,6 +70,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="6.0.1" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="6.0.1" />
</ItemGroup>
<ItemGroup>

44
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyProjectNameModule.cs

@ -1,6 +1,9 @@
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.OpenApi.Models;
using MyCompanyName.MyProjectName.Data;
using MyCompanyName.MyProjectName.Localization;
using StackExchange.Redis;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web;
@ -13,6 +16,7 @@ using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.Autofac;
using Volo.Abp.AutoMapper;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.FeatureManagement;
@ -44,6 +48,7 @@ namespace MyCompanyName.MyProjectName;
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpAutofacModule),
typeof(AbpAutoMapperModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpEntityFrameworkCoreSqlServerModule),
typeof(AbpSwashbuckleModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
@ -111,6 +116,8 @@ public class MyProjectNameModule : AbpModule
ConfigureAutoApiControllers();
ConfigureLocalization();
ConfigureAuthentication(context.Services, configuration);
ConfigureCors(context, configuration);
ConfigureDataProtection(context, configuration, hostingEnvironment);
ConfigureEfCore(context);
}
@ -211,6 +218,41 @@ public class MyProjectNameModule : AbpModule
});
}
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
}
private void ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration,
IWebHostEnvironment hostingEnvironment)
{
var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("MyProjectName");
if (!hostingEnvironment.IsDevelopment())
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "MyProjectName-Protection-Keys");
}
}
private void ConfigureEfCore(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<MyProjectNameDbContext>(options =>

38
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/appsettings.json

@ -1,15 +1,49 @@
{
"App": {
"SelfUrl": "https://localhost:44305"
"SelfUrl": "https://localhost:44305",
"CorsOrigins": "https://*.MyProjectName.com,http://localhost:4200"
},
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
},
"Redis": {
"Configuration": "127.0.0.1"
},
"AuthServer": {
"Authority": "https://localhost:44305",
"RequireHttpsMetadata": "false"
"RequireHttpsMetadata": "false",
"SwaggerClientId": "MyProjectName_Swagger",
"SwaggerClientSecret": "1q2w3e*"
},
"StringEncryption": {
"DefaultPassPhrase": "gsKnGZ041HLL4IM8"
},
"IdentityServer": {
"Clients": {
"MyProjectName_Web": {
"ClientId": "MyProjectName_Web",
"ClientSecret": "1q2w3e*",
"RootUrl": "https://localhost:44302"
},
"MyProjectName_App": {
"ClientId": "MyProjectName_App",
"ClientSecret": "1q2w3e*",
"RootUrl": "http://localhost:4200"
},
"MyProjectName_Blazor": {
"ClientId": "MyProjectName_Blazor",
"RootUrl": "https://localhost:44307"
},
"MyProjectName_BlazorServerTiered": {
"ClientId": "MyProjectName_BlazorServerTiered",
"ClientSecret": "1q2w3e*",
"RootUrl": "https://localhost:44314"
},
"MyProjectName_Swagger": {
"ClientId": "MyProjectName_Swagger",
"ClientSecret": "1q2w3e*",
"RootUrl": "https://localhost:44305"
}
}
}
}

Loading…
Cancel
Save