From d7a76bc1108cf596433268713641fc6c3a9aeaae Mon Sep 17 00:00:00 2001
From: hang <872297557@qq.com>
Date: Mon, 23 Sep 2024 18:01:46 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=8A=A0=E5=AF=86?=
=?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E6=B5=8B=E8=AF=95=E5=80=BC=E8=BD=AC?=
=?UTF-8?q?=E6=8D=A2=E5=99=A8ok?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Encryption/EncryptionRequestMiddleware.cs | 1 +
.../IRaCIS.Core.Application.csproj | 1 -
.../IRaCIS.Core.Application.xml | 14 -----
IRaCIS.Core.Application/TestService.cs | 16 ++++-
.../Converter/PartialEncryptionConverter.cs | 21 +++++++
.../Context/IRaCISDBContext.cs | 25 +++++++-
.../IRaCIS.Core.Infrastructure.csproj | 1 +
.../_IRaCIS}/Encryption/AesEncryption.cs | 60 ++++++++++++++++++-
.../_IRaCIS}/Encryption/RSAEncryption.cs | 4 +-
9 files changed, 124 insertions(+), 19 deletions(-)
create mode 100644 IRaCIS.Core.Infra.EFCore/Context/Converter/PartialEncryptionConverter.cs
rename {IRaCIS.Core.Application/BusinessFilter => IRaCIS.Core.Infrastructure/_IRaCIS}/Encryption/AesEncryption.cs (60%)
rename {IRaCIS.Core.Application/BusinessFilter => IRaCIS.Core.Infrastructure/_IRaCIS}/Encryption/RSAEncryption.cs (97%)
diff --git a/IRaCIS.Core.Application/BusinessFilter/Encryption/EncryptionRequestMiddleware.cs b/IRaCIS.Core.Application/BusinessFilter/Encryption/EncryptionRequestMiddleware.cs
index fdcb0222d..9dd672d1e 100644
--- a/IRaCIS.Core.Application/BusinessFilter/Encryption/EncryptionRequestMiddleware.cs
+++ b/IRaCIS.Core.Application/BusinessFilter/Encryption/EncryptionRequestMiddleware.cs
@@ -1,4 +1,5 @@
using IRaCIS.Core.Domain.Share;
+using IRaCIS.Core.Infrastructure.Encryption;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj
index bf0e815b4..5d385a0b9 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj
@@ -47,7 +47,6 @@
-
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index 86c8e85eb..828c174d7 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -12406,20 +12406,6 @@
测试加密API 返回的结果
-
-
- https://www.cnblogs.com/NBDWDYS2214143926/p/13329231.html
-
-
-
-
- RSA解密
-
- 私钥
- 待解密的字符串(Base64)
- 解密后的字符串
-
-
不生效,不知道为啥
diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs
index 8601bda5f..0c91dbb43 100644
--- a/IRaCIS.Core.Application/TestService.cs
+++ b/IRaCIS.Core.Application/TestService.cs
@@ -6,6 +6,7 @@ using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
+using IRaCIS.Core.Infrastructure.Encryption;
using IRaCIS.Core.Infrastructure.NewtonsoftJson;
using MassTransit;
using Medallion.Threading;
@@ -104,6 +105,19 @@ namespace IRaCIS.Core.Application.Service
public string TestName { get; set; }
}
+ public async Task TestAutoEncretpt([FromServices] IRepository _testLengthRepository)
+ {
+ await _testLengthRepository.AddAsync(new TestLength() { Name = "zhouhang1" });
+ await _testLengthRepository.AddAsync(new TestLength() { Name = "hewentao" });
+
+ await _testLengthRepository.SaveChangesAsync();
+ var list = _testLengthRepository.Where().ToList();
+
+ var exist = await _testLengthRepository.AnyAsync(t => t.Name == "zhouhang1");
+
+ return ResponseOutput.Ok(list, exist);
+
+ }
public async Task TestJson()
{
@@ -280,7 +294,7 @@ namespace IRaCIS.Core.Application.Service
var encreptMd5 = AesEncryption.Encrypt(MD5Helper.Md5("123456"), key);
Console.WriteLine(encreptMd5);
- var decrept= AesEncryption.Decrypt(encreptMd5, key);
+ var decrept = AesEncryption.Decrypt(encreptMd5, key);
Console.WriteLine();
diff --git a/IRaCIS.Core.Infra.EFCore/Context/Converter/PartialEncryptionConverter.cs b/IRaCIS.Core.Infra.EFCore/Context/Converter/PartialEncryptionConverter.cs
new file mode 100644
index 000000000..7465ce706
--- /dev/null
+++ b/IRaCIS.Core.Infra.EFCore/Context/Converter/PartialEncryptionConverter.cs
@@ -0,0 +1,21 @@
+using IRaCIS.Core.Infrastructure.Encryption;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Microsoft.EntityFrameworkCore.ValueGeneration;
+
+namespace IRaCIS.Core.Infra.EFCore;
+
+///
+/// 某列保留前面几位,后续加密
+///
+public class PartialEncryptionConverter : ValueConverter
+{
+ private readonly int _unencryptedPrefixLength;
+
+ public PartialEncryptionConverter(int unencryptedPrefixLength)
+ : base(
+ plainText => AesEncryption.EncryptPartial(plainText, unencryptedPrefixLength),
+ encryptedText => AesEncryption.DecryptPartial(encryptedText, unencryptedPrefixLength))
+ {
+ _unencryptedPrefixLength = unencryptedPrefixLength;
+ }
+}
diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs
index 57ba081f2..67e8ebc3c 100644
--- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs
+++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs
@@ -1,8 +1,12 @@
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infra.EFCore.Common;
+using IRaCIS.Core.Infrastructure.Encryption;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using System.ComponentModel;
using System.Data;
using System.Reflection;
+using System.Security.Cryptography;
+using System.Text;
using UserTypeGroup = IRaCIS.Core.Domain.Models.UserTypeGroup;
namespace IRaCIS.Core.Infra.EFCore;
@@ -54,6 +58,13 @@ public class IRaCISDBContext : DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
+ modelBuilder.Entity(entity =>
+ {
+ // 使用部分加密值转换器,前 2 个字符不加密,方便模糊搜索
+ entity.Property(e => e.Name)
+ .HasConversion(new PartialEncryptionConverter(2));
+ });
+
#region pgsql codefirst 配置 暂时屏蔽
//if (base.Database.IsNpgsql())
//{
@@ -544,6 +555,18 @@ public class IRaCISDBContext : DbContext
public virtual DbSet TrialImageDownload { get; set; }
+ public virtual DbSet TestLength { get; set; }
+
+
+
+
+
+}
+
+public class TestLength : Entity
+{
+ public string Name { get; set; }
+}
+
-}
\ No newline at end of file
diff --git a/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj b/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj
index e942ff3ee..e5a59bc58 100644
--- a/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj
+++ b/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj
@@ -18,6 +18,7 @@
+
diff --git a/IRaCIS.Core.Application/BusinessFilter/Encryption/AesEncryption.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/AesEncryption.cs
similarity index 60%
rename from IRaCIS.Core.Application/BusinessFilter/Encryption/AesEncryption.cs
rename to IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/AesEncryption.cs
index c19d82cf8..884e8b29b 100644
--- a/IRaCIS.Core.Application/BusinessFilter/Encryption/AesEncryption.cs
+++ b/IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/AesEncryption.cs
@@ -3,9 +3,11 @@ using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
+using System;
+using System.Security.Cryptography;
using System.Text;
-namespace IRaCIS.Core.Application.BusinessFilter;
+namespace IRaCIS.Core.Infrastructure.Encryption;
public class AesEncryption
{
@@ -84,4 +86,60 @@ public class AesEncryption
Array.Resize(ref output, length); // 调整输出数组大小以适应实际数据长度
return output;
}
+
+ public static string DefaultKey = "12345678901234567890123456789012";
+
+ public static string EncryptPartial(string plainText, int unencryptedPrefixLength)
+ {
+ if (plainText.Length <= unencryptedPrefixLength)
+ {
+ return Encrypt(plainText, DefaultKey); // 如果文本太短,直接加密
+ }
+
+ var prefix = plainText.Substring(0, unencryptedPrefixLength);
+ var suffix = plainText.Substring(unencryptedPrefixLength);
+
+ return prefix + Encrypt(suffix, DefaultKey); // 前缀保留,后缀加密
+ }
+
+ public static string DecryptPartial(string encryptedText, int unencryptedPrefixLength)
+ {
+ if (encryptedText.Length <= unencryptedPrefixLength)
+ {
+ return Decrypt(encryptedText, DefaultKey); // 如果文本太短,直接解密
+ }
+
+ var prefix = encryptedText.Substring(0, unencryptedPrefixLength);
+ var suffix = encryptedText.Substring(unencryptedPrefixLength);
+
+ return prefix + Decrypt(suffix, DefaultKey); // 前缀保留,后缀解密
+ }
+
+ //public static string Encrypt(string plainText)
+ //{
+ // using var aes = Aes.Create();
+ // aes.Key = Encoding.UTF8.GetBytes(EncryptionKey);
+ // aes.Mode = CipherMode.ECB; // 根据需要选择加密模式,这里使用 ECB 模式
+ // aes.Padding = PaddingMode.PKCS7;
+
+ // var encryptor = aes.CreateEncryptor();
+ // var plainBytes = Encoding.UTF8.GetBytes(plainText);
+ // var encryptedBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
+
+ // return Convert.ToBase64String(encryptedBytes);
+ //}
+
+ //public static string Decrypt(string encryptedText)
+ //{
+ // using var aes = Aes.Create();
+ // aes.Key = Encoding.UTF8.GetBytes(EncryptionKey);
+ // aes.Mode = CipherMode.ECB;
+ // aes.Padding = PaddingMode.PKCS7;
+
+ // var decryptor = aes.CreateDecryptor();
+ // var encryptedBytes = Convert.FromBase64String(encryptedText);
+ // var decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
+
+ // return Encoding.UTF8.GetString(decryptedBytes);
+ //}
}
diff --git a/IRaCIS.Core.Application/BusinessFilter/Encryption/RSAEncryption.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/RSAEncryption.cs
similarity index 97%
rename from IRaCIS.Core.Application/BusinessFilter/Encryption/RSAEncryption.cs
rename to IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/RSAEncryption.cs
index dcc610712..3f7d00cbd 100644
--- a/IRaCIS.Core.Application/BusinessFilter/Encryption/RSAEncryption.cs
+++ b/IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/RSAEncryption.cs
@@ -4,9 +4,11 @@ using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
+using System;
+using System.IO;
using System.Text;
-namespace IRaCIS.Core.Application.BusinessFilter;
+namespace IRaCIS.Core.Infrastructure.Encryption;
///
/// https://www.cnblogs.com/NBDWDYS2214143926/p/13329231.html
From c71b58e0e9344a5af0465637dd8421ab64a01670 Mon Sep 17 00:00:00 2001
From: hang <872297557@qq.com>
Date: Tue, 24 Sep 2024 11:25:08 +0800
Subject: [PATCH 2/2] =?UTF-8?q?=E5=90=8E=E5=A4=84=E7=90=86=E8=AE=BF?=
=?UTF-8?q?=E8=A7=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
IRaCIS.Core.Application/IRaCIS.Core.Application.xml | 2 +-
.../Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs | 2 ++
.../Service/ImageAndDoc/DownloadAndUploadService.cs | 11 +++++++++--
.../ReadingImageTask/ReadingImageTaskService.cs | 10 ++++++++++
4 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index ef881fbd6..fed48da3d 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -11317,7 +11317,7 @@
-
+
IR影像阅片
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs
index 9c8953122..571f4e1f3 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs
@@ -415,6 +415,8 @@ namespace IRaCIS.Core.Application.Contracts
[NotDefault]
public string SubjectCode { get; set; }
+
+ public Guid? VisitTaskId { get; set; }
}
public class IRTaskUploadedDicomStudyQuery
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs
index 29fedaebe..21f87dece 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs
@@ -112,8 +112,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
await SubejctRandomReadingTaskNameDeal(inQuery.SubjectId, inQuery.TrialReadingCriterionId);
+ //要根据标准阅片顺序,确定是否查询单个任务的,还是查询所有的
+ var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
+ .Select(t => new { t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
+
var query = _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SourceSubjectVisitId != null
&& t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect)
+ //满足 有序,或者随机只看到当前任务的dicom 非dicom检查
+ .WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
.Select(u => new SubjectImageUploadDTO()
{
VisitTaskId = u.Id,
@@ -587,10 +593,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
public async Task> GetIRUploadTaskNoneDicomStudyList(IRUploadStudyQuery inQuery)
{
var info = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
- .Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstNotNullAsync();
+ .Select(t => new { t.IsImageFilter, t.CriterionModalitys,t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
var query = from u in _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId
&& t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect)
+ //满足 有序,或者随机只看到当前任务的dicom 非dicom检查
+ .WhereIf(info.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
join ns in _noneDicomStudyReposiotry.Where(t => t.SubjectId == inQuery.SubjectId).WhereIf(info.IsImageFilter, t => ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|"))
on u.SourceSubjectVisitId equals ns.SubjectVisitId
@@ -745,7 +753,6 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
public async Task> GetSubjectImageDownloadSelectList(IRReadingDownloadQuery inQuery)
{
//要根据标准阅片顺序,确定是否查询单个任务的,还是查询所有的
-
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
.Select(t => new { t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs
index 2b1c6b3c8..779c7daf3 100644
--- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs
+++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs
@@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using NPOI.SS.Formula.Functions;
using Panda.DynamicWebApi.Attributes;
using ZiggyCreatures.Caching.Fusion;
@@ -60,6 +61,7 @@ namespace IRaCIS.Core.Application.Service
IRepository _noneDicomStudyFileSystem,
IGeneralCalculateService _generalCalculateService,
IRepository _readingQuestionTrialRepository,
+ IRepository _taskStudyRepository,
ITrialEmailNoticeConfigService _trialEmailNoticeConfigService) : BaseService, IReadingImageTaskService
{
@@ -2603,6 +2605,14 @@ namespace IRaCIS.Core.Application.Service
[HttpPost]
public async Task VerifyVisitTaskQuestions(VerifyVisitTaskQuestionsInDto inDto)
{
+ //验证后处理影像必须传
+ if (_visitTaskRepository.Any(t => t.Id==inDto.VisitTaskId && t.TrialReadingCriterion.ImageUploadEnum != ReadingImageUpload.None))
+ {
+ if (!_taskStudyRepository.Any(t => t.VisitTaskId == inDto.VisitTaskId))
+ {
+ return ResponseOutput.NotOk("ReadingImage_BackImageNotExist");
+ }
+ }
await VerifyTaskIsSign(inDto.VisitTaskId);
await VerifyDefaultQuestionBeAnswer(inDto);