Browse Source

Merge pull request #1518 from colinin/templ-blob-link-authorize

feat: The temporary link of the file does not perform permission checks.
pull/1529/head
yx lin 3 months ago
committed by GitHub
parent
commit
e3e95c8f13
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 7
      aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByIdInput.cs
  2. 10
      aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppService.cs
  3. 27
      aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppServiceBase.cs
  4. 6
      aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadKeyCacheItem.cs
  5. 14
      aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobManager.cs
  6. 6
      aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/BlobController.cs
  7. 1
      aspnet-core/services/LY.MicroService.Applications.Single/GlobalUsings.cs

7
aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByIdInput.cs

@ -1,12 +1,9 @@
using System; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.BlobManagement.Dtos; namespace LINGYUN.Abp.BlobManagement.Dtos;
public class BlobDownloadByIdInput public class BlobDownloadByIdInput
{ {
public Guid? TenantId { get; set; }
[Required] [Required]
public Guid Id { get; set; } public string Key { get; set; }
} }

10
aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppService.cs

@ -49,18 +49,12 @@ public class BlobAppService : BlobAppServiceBase, IBlobAppService
public async virtual Task<IRemoteStreamContent> DownloadAsync(BlobDownloadByIdInput input) public async virtual Task<IRemoteStreamContent> DownloadAsync(BlobDownloadByIdInput input)
{ {
using (CurrentTenant.Change(input.TenantId ?? CurrentTenant.Id)) return await base.DownloadByKeyAsync(input.Key);
{
return await base.DownloadAsync(input.Id);
}
} }
public async virtual Task<IRemoteStreamContent> PreviewAsync(BlobDownloadByIdInput input) public async virtual Task<IRemoteStreamContent> PreviewAsync(BlobDownloadByIdInput input)
{ {
using (CurrentTenant.Change(input.TenantId ?? CurrentTenant.Id)) return await base.DownloadByKeyAsync(input.Key);
{
return await base.DownloadAsync(input.Id);
}
} }
public async virtual Task<IRemoteStreamContent> DownloadByNameAsync(BlobDownloadByNameInput input) public async virtual Task<IRemoteStreamContent> DownloadByNameAsync(BlobDownloadByNameInput input)

27
aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppServiceBase.cs

@ -66,11 +66,28 @@ public abstract class BlobAppServiceBase : BlobManagementApplicationService
return new RemoteStreamContent( return new RemoteStreamContent(
stream ?? Stream.Null, stream ?? Stream.Null,
blob.Name, blob.Name,
blob.ContentType, blob.ContentType,
stream != null ? blob.Size : null); stream != null ? blob.Size : null);
} }
public async virtual Task<IRemoteStreamContent> DownloadByKeyAsync(string key)
{
var blob = await BlobManager.FindBlobByDownloadKeyAsync(key);
if (blob != null)
{
var stream = await BlobManager.DownloadBlobsync(blob);
return new RemoteStreamContent(
stream ?? Stream.Null,
blob.Name,
blob.ContentType,
stream != null ? blob.Size : null);
}
return new RemoteStreamContent(Stream.Null);
}
public async virtual Task<BlobDto> GetAsync(Guid id) public async virtual Task<BlobDto> GetAsync(Guid id)
{ {
var blob = await BlobRepository.GetAsync(id); var blob = await BlobRepository.GetAsync(id);
@ -187,14 +204,12 @@ public abstract class BlobAppServiceBase : BlobManagementApplicationService
await CheckGetPolicyAsync(blob); await CheckGetPolicyAsync(blob);
var fallbackDownloadUrl = blob.TenantId.HasValue var fallbackUrlPrefix = $"/api/{BlobManagementRemoteServiceConsts.ModuleName}/blobs/{method}/";
? $"/api/{BlobManagementRemoteServiceConsts.ModuleName}/blobs/{method}/t/{blob.TenantId:N}/{blob.Id:N}"
: $"/api/{BlobManagementRemoteServiceConsts.ModuleName}/blobs/{method}/{blob.Id:N}";
var downloadUrl = await BlobManager.GenerateDownloadUrlAsync( var downloadUrl = await BlobManager.GenerateDownloadUrlAsync(
blobContainer, blobContainer,
blob, blob,
fallbackDownloadUrl, fallbackUrlPrefix,
isAttachmentContent); isAttachmentContent);
return downloadUrl; return downloadUrl;

6
aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadKeyCacheItem.cs

@ -1,19 +1,23 @@
using System; using System;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.BlobManagement; namespace LINGYUN.Abp.BlobManagement;
[IgnoreMultiTenancy]
public class BlobDownloadKeyCacheItem public class BlobDownloadKeyCacheItem
{ {
public string Url { get; set; } public string Url { get; set; }
public Guid BlobId { get; set; } public Guid BlobId { get; set; }
public Guid? TenantId { get; set; }
public BlobDownloadKeyCacheItem() public BlobDownloadKeyCacheItem()
{ {
} }
public BlobDownloadKeyCacheItem(Guid blobId, string url) public BlobDownloadKeyCacheItem(Guid blobId, string url, Guid? tenantId = null)
{ {
BlobId = blobId; BlobId = blobId;
Url = url; Url = url;
TenantId = tenantId;
} }
} }

14
aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobManager.cs

@ -343,10 +343,10 @@ public class BlobManager : DomainService
public async virtual Task<string> GenerateDownloadUrlAsync( public async virtual Task<string> GenerateDownloadUrlAsync(
BlobContainer blobContainer, BlobContainer blobContainer,
Blob blob, Blob blob,
string fallbackDownloadUrl, string fallbackUrlPrefix,
bool isAttachmentContent = true) bool isAttachmentContent = true)
{ {
var cacheKey = $"{fallbackDownloadUrl.ToMd5()}"; var cacheKey = $"{fallbackUrlPrefix}{Clock.Now:yyyy-MM-ddHH}{blob.Name}".ToMd5();
var cacheItem = await _blobDownloadKeyCache.GetAsync(cacheKey); var cacheItem = await _blobDownloadKeyCache.GetAsync(cacheKey);
if (cacheItem == null) if (cacheItem == null)
{ {
@ -364,12 +364,13 @@ public class BlobManager : DomainService
if (downloadUrl.IsNullOrWhiteSpace()) if (downloadUrl.IsNullOrWhiteSpace())
{ {
// 特殊对象存储提供者(FileSystem)无法生成下载链接, 回退指定的请求Url // 特殊对象存储提供者(FileSystem)无法生成下载链接, 回退指定的请求Url
downloadUrl = fallbackDownloadUrl; downloadUrl = $"{fallbackUrlPrefix.EnsureEndsWith('/')}{cacheKey}";
} }
cacheItem = new BlobDownloadKeyCacheItem( cacheItem = new BlobDownloadKeyCacheItem(
blob.Id, blob.Id,
downloadUrl); downloadUrl,
blob.TenantId);
await _blobDownloadKeyCache.SetAsync( await _blobDownloadKeyCache.SetAsync(
cacheKey, cacheKey,
@ -391,7 +392,10 @@ public class BlobManager : DomainService
return null; return null;
} }
return await _blobRepository.FindAsync(cacheItem.BlobId); using (CurrentTenant.Change(cacheItem.TenantId))
{
return await _blobRepository.FindAsync(cacheItem.BlobId);
}
} }
public virtual string GetBlobProvider() public virtual string GetBlobProvider()

6
aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/BlobController.cs

@ -51,15 +51,13 @@ public class BlobController : BlobControllerBase, IBlobAppService
return _service.DeleteAsync(id); return _service.DeleteAsync(id);
} }
[HttpGet("download/{id}")] [HttpGet("download/{key}")]
[HttpGet("download/t/{tenantId}/{id}")]
public virtual Task<IRemoteStreamContent> DownloadAsync(BlobDownloadByIdInput input) public virtual Task<IRemoteStreamContent> DownloadAsync(BlobDownloadByIdInput input)
{ {
return _service.DownloadAsync(input); return _service.DownloadAsync(input);
} }
[HttpGet("preview/{id}")] [HttpGet("preview/{key}")]
[HttpGet("preview/t/{tenantId}/{id}")]
public async virtual Task<IRemoteStreamContent> PreviewAsync(BlobDownloadByIdInput input) public async virtual Task<IRemoteStreamContent> PreviewAsync(BlobDownloadByIdInput input)
{ {
var content = await _service.PreviewAsync(input); var content = await _service.PreviewAsync(input);

1
aspnet-core/services/LY.MicroService.Applications.Single/GlobalUsings.cs

@ -13,7 +13,6 @@ global using LINGYUN.Abp.Aliyun.Localization;
global using LINGYUN.Abp.Aliyun.SettingManagement; global using LINGYUN.Abp.Aliyun.SettingManagement;
global using LINGYUN.Abp.AspNetCore.HttpOverrides; global using LINGYUN.Abp.AspNetCore.HttpOverrides;
global using LINGYUN.Abp.AspNetCore.Mvc.Idempotent.Wrapper; global using LINGYUN.Abp.AspNetCore.Mvc.Idempotent.Wrapper;
global using LINGYUN.Abp.AspNetCore.Mvc.Localization;
global using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; global using LINGYUN.Abp.AspNetCore.Mvc.Wrapper;
global using LINGYUN.Abp.Auditing; global using LINGYUN.Abp.Auditing;
global using LINGYUN.Abp.AuditLogging.EntityFrameworkCore; global using LINGYUN.Abp.AuditLogging.EntityFrameworkCore;

Loading…
Cancel
Save