安全检测

This commit is contained in:
huqibin 2025-04-16 16:36:47 +08:00
parent f415a19f8f
commit 970ade8a78
7 changed files with 376 additions and 8 deletions

View File

@ -399,6 +399,7 @@ GameObject:
- component: {fileID: 1817104532591070028}
- component: {fileID: 1686064644}
- component: {fileID: 1817104532591070032}
- component: {fileID: 1817104532591070033}
m_Layer: 0
m_Name: "\u6B65\u9AA4\u72B6\u6001"
m_TagString: Untagged
@ -458,3 +459,32 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 41cef5d8cf8e39548a2936da5c981888, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &1817104532591070033
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1817104532591070025}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1300e99c4427bfc40a5300053c4434f9, type: 3}
m_Name:
m_EditorClassIdentifier:
skip_files:
- sec_code.json
- MonoBleedingEdge
- APP_BurstDebugInformation_DoNotShip
- 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

@ -741,7 +741,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 102, y: -37.4726}
m_AnchoredPosition: {x: 389.80002, y: -37.4726}
m_SizeDelta: {x: 204, y: 32}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5989447203773703055

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: a412bec34ebfd5d4583d66e4407497a9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,195 @@
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.Security.Policy;
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: 1300e99c4427bfc40a5300053c4434f9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -5,7 +5,10 @@ using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices.ComTypes;
using Cysharp.Threading.Tasks;
using UnityEngine;
using System.Diagnostics;
using Sirenix.Utilities;
/// <summary>
/// 统一引用单例类
@ -208,14 +211,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 网络加载故障数据
@ -268,6 +271,30 @@ public class GameManager : SingletonAutoMono<GameManager>
InitialTaskUIShow.Instance.Init(); //HQB
}
IEnumerator AsyncLoadScene(bool isReset = false)
{
while(SecurityCheck.instance.check_finish)
yield return null;
if (SecurityCheck.instance.result)
{
EventMgr.EventTrigger<float>(Enum_EventType.UpdateProgress, 0.4f);
ShowUIPanelAndLoadScene(isReset);
}
else
{
UIMgr.ShowPanel<UI_MessagePanel>(E_UI_Layer.System,
(p) => { p.Init("错误", "安全检查失败,请重新启动应用!", E_MessageType.Warning,
() => {
UnityEngine.Debug.Log("爆了!");
Application.Quit();
}); });
}
}
// ReSharper disable Unity.PerformanceAnalysis
/// <summary>
///首次加载和返回模式选择界面
/// </summary>
@ -302,10 +329,31 @@ public class GameManager : SingletonAutoMono<GameManager>
EventMgr.EventTrigger<float>(Enum_EventType.UpdateProgress, 0.9f);
});
}
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>
@ -332,6 +380,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>
@ -375,7 +437,7 @@ 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 进入场景弹出任务说明
}
@ -384,9 +446,9 @@ public class GameManager : SingletonAutoMono<GameManager>
{
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);
}
}