Browse Source

backlog of modifications

pull/65/head
cKey 5 years ago
parent
commit
836e7463e5
  1. 3
      aspnet-core/configuration/messages/LINGYUN.Abp.MessageService.HttpApi.Host/appsettings.Development.json
  2. 5
      aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
  3. 4
      aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj
  4. 5
      aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/BackendAdminHostModule.cs
  5. 5
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/ApiGatewayHttpApiHostModule.cs
  6. 39
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/AbpMessageServiceHttpApiHostModule.cs
  7. 61
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Authorization/HangfireDashboardAuthorizationFilter.cs
  8. 6
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireApplicationBuilderExtensions.cs
  9. 55
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireDashboardRouteOptions.cs
  10. 31
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireJwtTokenMiddleware.cs
  11. 8
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj
  12. 49
      vueJs/src/components/HangfireDashboard/index.vue

3
aspnet-core/configuration/messages/LINGYUN.Abp.MessageService.HttpApi.Host/appsettings.Development.json

@ -1,4 +1,7 @@
{ {
"App": {
"CorsOrigins": "http://localhost:9527,http://127.0.0.1:30000"
},
"ConnectionStrings": { "ConnectionStrings": {
"Default": "Server=127.0.0.1;Database=Messages;User Id=root;Password=123456", "Default": "Server=127.0.0.1;Database=Messages;User Id=root;Password=123456",
"MessageService": "Server=127.0.0.1;Database=Messages;User Id=root;Password=123456", "MessageService": "Server=127.0.0.1;Database=Messages;User Id=root;Password=123456",

5
aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs

@ -183,7 +183,10 @@ namespace AuthServer.Host
app.UseIdentityServer(); app.UseIdentityServer();
app.UseAuditing(); app.UseAuditing();
SeedData(context); if (context.GetEnvironment().IsDevelopment())
{
SeedData(context);
}
} }
private void SeedData(ApplicationInitializationContext context) private void SeedData(ApplicationInitializationContext context)

4
aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj

@ -40,7 +40,5 @@
<ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj" /> <ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj" />
<ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj" /> <ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj" />
</ItemGroup> </ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties appsettings_1development_1json__JsonSchema="http://json.schemastore.org/avro-avsc" /></VisualStudio></ProjectExtensions>
</Project> </Project>

5
aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/BackendAdminHostModule.cs

@ -306,7 +306,10 @@ namespace LINGYUN.BackendAdmin
// 路由 // 路由
app.UseConfiguredEndpoints(); app.UseConfiguredEndpoints();
SeedData(context); if (context.GetEnvironment().IsDevelopment())
{
SeedData(context);
}
} }
private void SeedData(ApplicationInitializationContext context) private void SeedData(ApplicationInitializationContext context)

5
aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/ApiGatewayHttpApiHostModule.cs

@ -210,7 +210,10 @@ namespace LINGYUN.ApiGateway
// 路由 // 路由
app.UseConfiguredEndpoints(); app.UseConfiguredEndpoints();
SeedData(context); if (context.GetEnvironment().IsDevelopment())
{
SeedData(context);
}
} }
private void SeedData(ApplicationInitializationContext context) private void SeedData(ApplicationInitializationContext context)

39
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/AbpMessageServiceHttpApiHostModule.cs

@ -16,15 +16,18 @@ using LINGYUN.Abp.MultiTenancy.DbFinder;
using LINGYUN.Abp.Notifications.SignalR; using LINGYUN.Abp.Notifications.SignalR;
using LINGYUN.Abp.Notifications.WeChat.WeApp; using LINGYUN.Abp.Notifications.WeChat.WeApp;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Caching.StackExchangeRedis; using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using StackExchange.Redis; using StackExchange.Redis;
using System; using System;
using System.Linq;
using System.Text; using System.Text;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.Authentication.JwtBearer;
@ -68,6 +71,8 @@ namespace LINGYUN.Abp.MessageService
)] )]
public class AbpMessageServiceHttpApiHostModule : AbpModule public class AbpMessageServiceHttpApiHostModule : AbpModule
{ {
private const string DefaultCorsPolicyName = "Default";
public override void PreConfigureServices(ServiceConfigurationContext context) public override void PreConfigureServices(ServiceConfigurationContext context)
{ {
var configuration = context.Services.GetConfiguration(); var configuration = context.Services.GetConfiguration();
@ -190,6 +195,35 @@ namespace LINGYUN.Abp.MessageService
}); });
}); });
context.Services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
Configure<HangfireDashboardRouteOptions>(options =>
{
options.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
);
});
// 支持本地化语言类型 // 支持本地化语言类型
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
@ -241,8 +275,12 @@ namespace LINGYUN.Abp.MessageService
app.UseAbpRequestLocalization(); app.UseAbpRequestLocalization();
//路由 //路由
app.UseRouting(); app.UseRouting();
// 跨域
app.UseCors(DefaultCorsPolicyName);
// 加入自定义中间件 // 加入自定义中间件
app.UseSignalRJwtToken(); app.UseSignalRJwtToken();
// TODO: 还有没有其他方法在iframe中传递身份令牌?
app.UseHangfireJwtToken();
// 认证 // 认证
app.UseAuthentication(); app.UseAuthentication();
// jwt // jwt
@ -263,6 +301,7 @@ namespace LINGYUN.Abp.MessageService
app.UseHangfireServer(); app.UseHangfireServer();
app.UseHangfireDashboard(options => app.UseHangfireDashboard(options =>
{ {
options.IgnoreAntiforgeryToken = true;
options.UseAuthorization(new HangfireDashboardAuthorizationFilter()); options.UseAuthorization(new HangfireDashboardAuthorizationFilter());
}); });
// 路由 // 路由

61
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Authorization/HangfireDashboardAuthorizationFilter.cs

@ -1,7 +1,10 @@
using Hangfire.Annotations; using Hangfire;
using Hangfire.Annotations;
using Hangfire.Dashboard; using Hangfire.Dashboard;
using LINGYUN.Abp.MessageService.Permissions;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using NUglify.Helpers;
using System.Linq;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Threading; using Volo.Abp.Threading;
@ -9,18 +12,42 @@ namespace LINGYUN.Abp.MessageService.Authorization
{ {
public class HangfireDashboardAuthorizationFilter : IDashboardAuthorizationFilter public class HangfireDashboardAuthorizationFilter : IDashboardAuthorizationFilter
{ {
protected string[] AllowGrantPath { get; }
public HangfireDashboardAuthorizationFilter()
{
AllowGrantPath = new string[] { "/css", "/js", "/fonts", "/stats" };
}
public bool Authorize([NotNull] DashboardContext context) public bool Authorize([NotNull] DashboardContext context)
{ {
// 本地请求
if (LocalRequestOnlyAuthorize(context))
{
return true;
}
// 放行路径
if (AllowGrantPath.Contains(context.Request.Path))
{
return true;
}
var httpContext = context.GetHttpContext(); var httpContext = context.GetHttpContext();
var permissionChecker = httpContext.RequestServices.GetService<IPermissionChecker>(); var options = httpContext.RequestServices.GetService<IOptions<HangfireDashboardRouteOptions>>()?.Value;
if (permissionChecker != null) if (options != null)
{ {
// 可以详细到每个页面授权,这里就免了 // 请求路径对应的权限检查
return AsyncHelper.RunSync(async () => await permissionChecker.IsGrantedAsync(AbpMessageServicePermissions.Hangfire.ManageQueue)); // TODO: 怎么来传递用户身份令牌?
var permission = options.GetPermission(context.Request.Path);
if (!permission.IsNullOrWhiteSpace())
{
var permissionChecker = httpContext.RequestServices.GetRequiredService<IPermissionChecker>();
return AsyncHelper.RunSync(async () => await permissionChecker.IsGrantedAsync(permission));
}
} }
return new LocalRequestsOnlyAuthorizationFilter().Authorize(context);
return false;
} }
public override int GetHashCode() public override int GetHashCode()
@ -42,5 +69,25 @@ namespace LINGYUN.Abp.MessageService.Authorization
} }
return base.Equals(obj); return base.Equals(obj);
} }
protected virtual bool LocalRequestOnlyAuthorize(DashboardContext context)
{
if (string.IsNullOrEmpty(context.Request.RemoteIpAddress))
{
return false;
}
if (context.Request.RemoteIpAddress == "127.0.0.1" || context.Request.RemoteIpAddress == "::1")
{
return true;
}
if (context.Request.RemoteIpAddress == context.Request.LocalIpAddress)
{
return true;
}
return false;
}
} }
} }

6
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireApplicationBuilderExtensions.cs

@ -7,6 +7,12 @@ namespace Hangfire
{ {
public static class HangfireApplicationBuilderExtensions public static class HangfireApplicationBuilderExtensions
{ {
public static IApplicationBuilder UseHangfireJwtToken(
[NotNull] this IApplicationBuilder app)
{
return app.UseMiddleware<HangfireJwtTokenMiddleware>();
}
public static IApplicationBuilder UseHangfireDashboard( public static IApplicationBuilder UseHangfireDashboard(
[NotNull] this IApplicationBuilder app, [NotNull] this IApplicationBuilder app,
[CanBeNull] Action<DashboardOptions> setup = null) [CanBeNull] Action<DashboardOptions> setup = null)

55
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireDashboardRouteOptions.cs

@ -0,0 +1,55 @@
using LINGYUN.Abp.MessageService.Permissions;
using System.Collections.Generic;
using System.Linq;
namespace Hangfire
{
public class HangfireDashboardRouteOptions
{
public IList<string> AllowFrameOrigins { get; }
public IDictionary<string, string> RoutePermissions { get; }
public HangfireDashboardRouteOptions()
{
AllowFrameOrigins = new List<string>();
RoutePermissions = new Dictionary<string, string>();
InitDefaultRoutes();
}
public void WithOrigins(params string[] origins)
{
AllowFrameOrigins.AddIfNotContains(origins);
}
public void WithPermission(string route, string permission)
{
RoutePermissions.Add(route, permission);
}
public string GetPermission(string route)
{
var permission = RoutePermissions
.Where(x => x.Key.StartsWith(route))
.Select(x => x.Value)
.FirstOrDefault();
return permission;
}
private void InitDefaultRoutes()
{
WithPermission("/hangfire", AbpMessageServicePermissions.Hangfire.Default);
WithPermission("/stats", AbpMessageServicePermissions.Hangfire.Default);
WithPermission("/servers", AbpMessageServicePermissions.Hangfire.Default);
WithPermission("/retries", AbpMessageServicePermissions.Hangfire.Default);
WithPermission("/recurring", AbpMessageServicePermissions.Hangfire.Default);
WithPermission("/jobs/enqueued", AbpMessageServicePermissions.Hangfire.ManageQueue);
WithPermission("/jobs/processing", AbpMessageServicePermissions.Hangfire.ManageQueue);
WithPermission("/jobs/scheduled", AbpMessageServicePermissions.Hangfire.ManageQueue);
WithPermission("/jobs/failed", AbpMessageServicePermissions.Hangfire.ManageQueue);
WithPermission("/jobs/deleted", AbpMessageServicePermissions.Hangfire.ManageQueue);
WithPermission("/jobs/awaiting", AbpMessageServicePermissions.Hangfire.ManageQueue);
WithPermission("/jobs/actions", AbpMessageServicePermissions.Hangfire.ManageQueue);
WithPermission("/jobs/details", AbpMessageServicePermissions.Hangfire.ManageQueue);
}
}
}

31
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireJwtTokenMiddleware.cs

@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Hangfire
{
public class HangfireJwtTokenMiddleware : IMiddleware, ITransientDependency
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
// 通过 iframe 加载页面的话,需要手动传递 access_token 到参数列表
if (context.Request.Path.StartsWithSegments("/hangfire") && context.User.Identity?.IsAuthenticated != true)
{
if (context.Request.Query.TryGetValue("access_token", out var accessTokens))
{
context.Request.Headers.Add("Authorization", accessTokens);
}
var options = context.RequestServices.GetService<IOptions<HangfireDashboardRouteOptions>>()?.Value;
if (options != null && options.AllowFrameOrigins.Count > 0)
{
// 跨域 iframe
context.Response.Headers.TryAdd("X-Frame-Options", $"\"ALLOW-FROM {options.AllowFrameOrigins.JoinAsString(",")}\"");
}
}
await next(context);
}
}
}

8
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj

@ -6,13 +6,13 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Remove="LINGYUN\Abp\MessageService\Localization\HttpApiHost\en.json" /> <Content Remove="Localization\HttpApiHost\en.json" />
<Content Remove="LINGYUN\Abp\MessageService\Localization\HttpApiHost\zh-Hans.json" /> <Content Remove="Localization\HttpApiHost\zh-Hans.json" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\MessageService\Localization\HttpApiHost\en.json" /> <EmbeddedResource Include="Localization\HttpApiHost\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\MessageService\Localization\HttpApiHost\zh-Hans.json" /> <EmbeddedResource Include="Localization\HttpApiHost\zh-Hans.json" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

49
vueJs/src/components/HangfireDashboard/index.vue

@ -0,0 +1,49 @@
<template>
<div class="dashboard-container">
<iframe
id="iframe-hangifre"
ref="hangfireIframe"
:src="hangfireUrl"
scrolling="auto"
frameborder="0"
class="iframe-hangifre"
/>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
@Component({
name: 'HangfireDashboard'
})
export default class extends Vue {
@Prop({ default: '' })
private hangfireUrl!: string
get showIframe() {
if (this.hangfireUrl) {
return true
}
return false
}
mounted() {
const hangfireFrame = this.$refs.hangfireIframe as any
if (hangfireFrame) {
const deviceWidth = document.documentElement.clientWidth
const deviceHeight = document.documentElement.clientHeight
hangfireFrame.style.width = deviceWidth + 'px'
hangfireFrame.style.height = deviceHeight + 'px'
}
}
}
</script>
<style lang="scss" scoped>
.iframe-hangifre {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
Loading…
Cancel
Save