安全检测

This commit is contained in:
huqibin 2025-04-16 15:56:40 +08:00
parent 077d7ef8d0
commit d2390f691a
6 changed files with 346 additions and 15 deletions

View File

@ -468,7 +468,23 @@ MonoBehaviour:
m_GameObject: {fileID: 1817104532591070025}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 50fb6698959dc034e865fdc90070cff0, type: 3}
m_Script: {fileID: 11500000, guid: af02d028713f8b34eb6aae6fb65b5341, type: 3}
m_Name:
m_EditorClassIdentifier:
isOnceAddFun: 0
skip_files:
- sec_code.json
- APP_BurstDebugInformation_DoNotShip
- MonoBleedingEdge
- realtimeStat.json
- info.ini
- MissionData
- ticket_ForReC.json
- fault_ForReC.json
- unins000.dat
- unins000.exe
- start.ini
total: 0
read: 0
check_finish: 0
result: 0
debugStr:

View File

@ -0,0 +1,59 @@
using UnityEngine;
using System.IO;
using System;
public static class PathUtils
{
// 核心方法:获取相对路径(自动处理路径格式)
public static string GetRelativeToStreamingAssets(string targetPath, bool allowOutside = false)
{
string streamingAssetsPath = Application.streamingAssetsPath;
#if UNITY_EDITOR
streamingAssetsPath = "E:\\HQB\\文件打包\\0402\\10002\\App_Data\\StreamingAssets";
#endif
// 规范化路径格式(统一斜杠和大小写)
string normalizedBase = NormalizePath(streamingAssetsPath);
string normalizedTarget = NormalizePath(targetPath);
// 检查是否在StreamingAssets目录下
bool isInside = normalizedTarget.StartsWith(normalizedBase, StringComparison.OrdinalIgnoreCase);
if (isInside)
{
// 直接截取子路径
return normalizedTarget.Substring(normalizedBase.Length + 1);
}
else if (allowOutside)
{
// 使用Uri计算可能包含上级目录的相对路径
return GetRelativePathUsingUri(normalizedBase, normalizedTarget);
}
else
{
Debug.LogError($"路径不在StreamingAssets下: {targetPath}");
return null;
}
}
// 路径规范化工具
private static string NormalizePath(string path)
{
return Path.GetFullPath(path)
.Replace('\\', '/')
.TrimEnd('/')
.ToLower(); // 根据平台需求调整大小写敏感
}
// 使用Uri计算相对路径支持跨目录
private static string GetRelativePathUsingUri(string basePath, string targetPath)
{
var baseUri = new Uri(basePath + "/");
var targetUri = new Uri(targetPath);
Uri relativeUri = baseUri.MakeRelativeUri(targetUri);
string relativePath = Uri.UnescapeDataString(relativeUri.ToString())
.Replace('/', Path.DirectorySeparatorChar);
return relativePath;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 84c96bea59e16c84c8508b0d54c88b32
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,194 @@
using Newtonsoft.Json;
using System.Collections;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using System.Security.Cryptography;
using Sirenix.Utilities;
using System.Text;
public class SecurityCheck : MonoBehaviour
{
private string hashFileName = "sec_code.json";// 用于存储文件路径和对应哈希值的字典
private Dictionary<string, string> AS_fileHashes = new Dictionary<string, string>();//文件中Hash
private Dictionary<string, string> fileHashes = new Dictionary<string, string>();//当前文件Hash
private string appFolderPath = Application.streamingAssetsPath + "\\..\\..\\";
public List<string> skip_files = new List<string>();//读取跳过的文件
[HideInInspector]
public int total = 0;//总文件数量
[HideInInspector]
public int read = 0;
[HideInInspector]
public bool check_finish = false;
[HideInInspector]
public bool result = false;
public static SecurityCheck instance;
List<string> files = new List<string>();
[HideInInspector]
public string debugStr = "";
// 获取文件哈希值的方法
private string GetHash(string path)
{
using (var hash = SHA256.Create())
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] hashBytes = hash.ComputeHash(stream);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
IEnumerator CalculateHashes(List<string> files)
{
if (AS_fileHashes == null || AS_fileHashes.Count == 0)//没有校验文件
{
Debug.Log("缺少校验文件");
result = false;
check_finish = true;
yield break;
}
if (files.Count != AS_fileHashes.Count)
{
Debug.Log("文件数量不对");
#if UNITY_EDITOR
foreach (var item in files)
{
bool find = false;
string f_name = Path.GetFileName(item).ToLower();
foreach (var item2 in AS_fileHashes)
{
//string f_name2 = Path.GetFileName(y.Key);
//Debug.Log("===>" + f_name);
if (item2.Key.Contains(f_name))
{
find = true;
break;
}
}
if (!find)
{
Debug.Log("缺少文件:" + f_name);
}
}
#endif
result = false;
check_finish = true;
yield break;
}
check_finish = false;
total = files.Count;
read = 0;
foreach (string filePath in files)
{
try
{
string absolutePath = Path.GetFullPath(filePath);
string hash = GetHash(absolutePath);
string relativePath = PathUtils.GetRelativeToStreamingAssets(absolutePath, true);
debugStr = relativePath;
if (!AS_fileHashes.ContainsKey(relativePath) || !hash.Equals(AS_fileHashes[relativePath]))
{
if (!AS_fileHashes.ContainsKey(relativePath))
Debug.Log("缺少文件:" + absolutePath + "=>" + relativePath);
else
Debug.Log("值不对:" + relativePath + "\n" + hash + "\n" + AS_fileHashes[relativePath]);
//Debug.LogError($"MD5错误");
result = false;
check_finish = true;
yield break;
}
//}
//fileHashes[filePath] = hash;
}
catch (Exception ex)
{
Debug.LogError($"Error calculating hash for file {filePath}: {ex.Message}");
result = false;
check_finish = true;
yield break;
}
read++;
yield return null;
}
result = true;
check_finish = true;
}
private void Awake()
{
instance = this;
check_finish = false;
fileHashes.Clear();
AS_fileHashes.Clear();
files.Clear();
AS_fileHashes = LoadHashesFromJson(Application.streamingAssetsPath + "\\" + hashFileName);
#if UNITY_EDITOR
appFolderPath = "E:\\HQB\\文件打包\\0402\\10002\\";
#endif
try
{
string[] allFiles = Directory.GetFiles(appFolderPath, "*", SearchOption.AllDirectories);
allFiles.ForEach(x =>
{
bool skip = false;
foreach (var item in skip_files)
{
if (x.Contains(item.Trim()))
{
skip = true;
break;
}
}
if (!skip)
files.Add(x);
});
total = files.Count;
}
catch (Exception ex)
{
Debug.LogError("校验文件读取故障:" + ex.Message);
}
StartCoroutine(CalculateHashes(files));
}
public string DecodeFromBase64(string encoded)
{
byte[] encodedBytes = Convert.FromBase64String(encoded);
return Encoding.UTF8.GetString(encodedBytes);
}
private Dictionary<string, string> LoadHashesFromJson(string filePath)
{
if (!File.Exists(filePath))
{
Debug.LogError($"File not found at path: {filePath}");
return null;
}
try
{
string json64 = File.ReadAllText(filePath);
string json = DecodeFromBase64(json64);
Dictionary<string, string> hashes = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
Debug.Log($"Hashes loaded from {filePath}");
return hashes;
}
catch (Exception ex)
{
Debug.LogError($"Failed to load hashes from {filePath}: {ex.Message}");
return null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: af02d028713f8b34eb6aae6fb65b5341
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -6,6 +6,8 @@ using System.Reflection;
using System.Runtime.InteropServices.ComTypes;
using Cysharp.Threading.Tasks;
using UnityEngine;
using System.Diagnostics;
using Sirenix.Utilities;
/// <summary>
/// 统一引用单例类
@ -124,7 +126,7 @@ public class GameManager : SingletonAutoMono<GameManager>
/// 故障管理类
/// </summary>
public static FaultManager FaultManager { get; private set; }
/// <summary>
/// 任务管理类
/// </summary>
@ -208,14 +210,14 @@ public class GameManager : SingletonAutoMono<GameManager>
}
else
{
Debug.Log("科目不对");
UnityEngine.Debug.Log("科目不对");
}
}
else
{
UIMgr.ShowPanel<UI_MessagePanel>(E_UI_Layer.System,
(p) => { p.Init("错误", "试卷数据没有获取到", E_MessageType.Warning, () => { }); });
Debug.Log("数据不对");
UnityEngine.Debug.Log("数据不对");
}
//HQB 1106 网络加载故障数据
@ -255,6 +257,7 @@ public class GameManager : SingletonAutoMono<GameManager>
tokenUrl = NetMgr.GetTokenURL();
OnRefreshToken();
//StartCoroutine(AsyncLoadScene());
ShowUIPanelAndLoadScene();
}
else
@ -266,9 +269,10 @@ public class GameManager : SingletonAutoMono<GameManager>
});
});
InitialTaskUIShow.Instance.Init();//HQB
InitialTaskUIShow.Instance.Init(); //HQB
}
// ReSharper disable Unity.PerformanceAnalysis
/// <summary>
///首次加载和返回模式选择界面
/// </summary>
@ -282,6 +286,7 @@ public class GameManager : SingletonAutoMono<GameManager>
UIMgr.ShowPanel<UI_BGPanel>(E_UI_Layer.Bot);
UIMgr.ShowPanel<UI_MainTitlePanel>(E_UI_Layer.Bot, (panel) => { panel.Init(); });
// StartCoroutine(AsyncFinalLoadScene());
//显示UI菜单列表
if (NetMgr.operationType != "3")
{
@ -291,7 +296,7 @@ public class GameManager : SingletonAutoMono<GameManager>
{
//修改本地文件
NetMgr.SaveInfo("1");
EventMgr.EventTrigger<float>(Enum_EventType.UpdateProgress, 0.9f);
EventMgr.EventTrigger<float>(Enum_EventType.UpdateProgress, 0.8f);
});
}
else
@ -300,13 +305,34 @@ public class GameManager : SingletonAutoMono<GameManager>
{
UIMgr.HidePanel<UI_BGPanel>();
NetMgr.SaveInfo("1");
EventMgr.EventTrigger<float>(Enum_EventType.UpdateProgress, 0.9f);
EventMgr.EventTrigger<float>(Enum_EventType.UpdateProgress, 0.8f);
});
}
StartCoroutine(AsyncSecurityCheck());
}
public void ModeTypeIsExam()
IEnumerator AsyncSecurityCheck()
{
while (!SecurityCheck.instance.check_finish)
{
//debugInfo = "check_finish";
yield return null;
}
while (Process.GetProcessesByName("AppStart").Length != 0)
{
//debugInfo = "AppStart";
yield return null;
}
EventMgr.EventTrigger<float>(Enum_EventType.UpdateProgress, 0.1f);
if (!SecurityCheck.instance.result)
{
//debugInfo = "okkkk";
UnityEngine.Debug.LogError("安全检查失败,请重新启动应用!");
Application.Quit();
}
}
/// <summary>
@ -333,6 +359,20 @@ public class GameManager : SingletonAutoMono<GameManager>
});
}
//#if UNITY_EDITOR
// void OnGUI()
// {
// // 设置GUI样式可选
// GUIStyle style = new GUIStyle();
// style.fontSize = 20;
// style.normal.textColor = Color.red;
// // 在屏幕上绘制调试信息
// GUILayout.Label(" " + SecurityCheck.instance.debugStr + "\n " + SecurityCheck.instance.read + "/" + SecurityCheck.instance.total, style);
// GUILayout.Label(" " + debugInfo, style);
// }
//#endif
/// <summary>
/// 学习调用
/// </summary>
@ -377,21 +417,21 @@ public class GameManager : SingletonAutoMono<GameManager>
if (SubjectControllerBase.Instance != null)
SubjectControllerBase.Instance.OnInit();
RunModelMgr.startTime = DateTime.Now;
Debug.Log("重置开始时间");
UnityEngine.Debug.Log("重置开始时间");
RunModelMgr.isOnceOfficeAni = false;
InitialTaskUIShow.Instance.Init(); //HQB 进入场景弹出任务说明
ClearTicketsInfo();//HQB 清除各项工作票信息
WorkorderMgr.ClearLeftBtnActionMap();
}
public async void OnRefreshToken()
{
while (true)
{
Debug.Log("NetMgr.Get(tokenUrl)11111111");
{
UnityEngine.Debug.Log("NetMgr.Get(tokenUrl)11111111");
await NetMgr.Get(tokenUrl);
Debug.Log("NetMgr.Get(tokenUrl)");
UnityEngine.Debug.Log("NetMgr.Get(tokenUrl)");
await UniTask.Delay(300000);
}
}
@ -411,7 +451,7 @@ public class GameManager : SingletonAutoMono<GameManager>
}
public void ClearTicketsInfo()
{
{
FaultManager.Instance.selectedFaultsInReg.Clear();
MissionMgr.Instance.Reset();
}