From feb517dd8da9c2a51caabf8e23463dc43e773240 Mon Sep 17 00:00:00 2001
From: geh <1923421292@qq.com>
Date: Thu, 13 Nov 2025 17:32:14 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AD=90=E5=85=AC=E5=8F=B8=E9=9B=86=E6=88=90?=
=?UTF-8?q?=E9=9B=86=E5=9B=A2=E5=8D=95=E7=82=B9=E7=99=BB=E5=BD=95=E4=BF=AE?=
=?UTF-8?q?=E6=94=B9=E5=86=85=E5=AE=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
SUBQHSE/BLL/BLL.csproj | 1 +
SUBQHSE/BLL/TokenHelper.cs | 127 +++++++++++++++++++++++
SUBQHSE/FineUIPro.Web/common/PageBase.cs | 94 +++++++++++++----
3 files changed, 200 insertions(+), 22 deletions(-)
create mode 100644 SUBQHSE/BLL/TokenHelper.cs
diff --git a/SUBQHSE/BLL/BLL.csproj b/SUBQHSE/BLL/BLL.csproj
index e3ca3e0..33a221d 100644
--- a/SUBQHSE/BLL/BLL.csproj
+++ b/SUBQHSE/BLL/BLL.csproj
@@ -895,6 +895,7 @@
+
diff --git a/SUBQHSE/BLL/TokenHelper.cs b/SUBQHSE/BLL/TokenHelper.cs
new file mode 100644
index 0000000..9ce6b09
--- /dev/null
+++ b/SUBQHSE/BLL/TokenHelper.cs
@@ -0,0 +1,127 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace BLL
+{
+ ///
+ /// Token加密解密工具类
+ /// 用于iframe跨域自动登录的token处理
+ ///
+ public static class TokenHelper
+ {
+ // 默认密钥,建议从配置文件中读取
+ private static readonly string SecretKey = "cncec-subqhse-256bit-secret-key-for-auth-token";
+
+ ///
+ /// 加密Token
+ ///
+ /// 明文
+ /// 加密后的Base64字符串
+ public static string EncryptToken(string plainText)
+ {
+ try
+ {
+ // 确保密钥长度为32字节(256位)
+ string key = SecretKey.PadRight(32, '0').Substring(0, 32);
+
+ using (var aes = Aes.Create())
+ {
+ aes.Key = Encoding.UTF8.GetBytes(key);
+ aes.IV = new byte[16]; // 使用固定IV,简化实现
+ aes.Mode = CipherMode.CBC;
+ aes.Padding = PaddingMode.PKCS7;
+
+ using (var encryptor = aes.CreateEncryptor())
+ using (var msEncrypt = new MemoryStream())
+ {
+ using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
+ using (var swEncrypt = new StreamWriter(csEncrypt))
+ {
+ swEncrypt.Write(plainText);
+ }
+ return Convert.ToBase64String(msEncrypt.ToArray());
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"Token加密失败: {ex.Message}", ex);
+ }
+ }
+
+ ///
+ /// 解密Token
+ ///
+ /// 加密的Base64字符串
+ /// 解密后的明文
+ public static string DecryptToken(string cipherText)
+ {
+ try
+ {
+ // 确保密钥长度为32字节(256位)
+ string key = SecretKey.PadRight(32, '0').Substring(0, 32);
+
+ using (var aes = Aes.Create())
+ {
+ aes.Key = Encoding.UTF8.GetBytes(key);
+ aes.IV = new byte[16]; // 使用固定IV,与加密一致
+ aes.Mode = CipherMode.CBC;
+ aes.Padding = PaddingMode.PKCS7;
+
+ using (var decryptor = aes.CreateDecryptor())
+ using (var msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
+ using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
+ using (var srDecrypt = new StreamReader(csDecrypt))
+ {
+ return srDecrypt.ReadToEnd();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"Token解密失败: {ex.Message}", ex);
+ }
+ }
+
+ ///
+ /// 生成认证Token
+ ///
+ /// 用户ID
+ /// 来源标识
+ /// 加密的Token
+ public static string GenerateAuthToken(string userId, string source = "qhse.cncecoa.com")
+ {
+ var tokenData = new
+ {
+ user_id = userId,
+ timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(),
+ source = source,
+ random = Guid.NewGuid().ToString("N").Substring(0, 8) // 添加8位随机数增强安全性
+ };
+
+ string json = JsonConvert.SerializeObject(tokenData);
+ return EncryptToken(json);
+ }
+
+ ///
+ /// 验证Token格式
+ ///
+ /// Token字符串
+ /// 是否为有效的Base64格式
+ public static bool IsValidTokenFormat(string token)
+ {
+ try
+ {
+ Convert.FromBase64String(token);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SUBQHSE/FineUIPro.Web/common/PageBase.cs b/SUBQHSE/FineUIPro.Web/common/PageBase.cs
index 0e1c492..0bb9fe5 100644
--- a/SUBQHSE/FineUIPro.Web/common/PageBase.cs
+++ b/SUBQHSE/FineUIPro.Web/common/PageBase.cs
@@ -131,37 +131,87 @@ namespace FineUIPro.Web
protected override void OnInit(EventArgs e)
{
- string url = HttpContext.Current.Request.Path;
-
- string a = Request.ServerVariables["HTTP_REFERER"];
- string Referer = Request.Headers["Referer"];
- if (a==null)
+ string fullPath = HttpContext.Current.Request.Path;
+ string appPath = HttpContext.Current.Request.ApplicationPath; // 获取应用程序根路径
+ // 确保应用程序路径以 "/" 开头并移除它
+ if (!string.IsNullOrEmpty(appPath) && fullPath.StartsWith(appPath, StringComparison.OrdinalIgnoreCase))
{
- bool IsDataShowPage = ConstValue.drpConstItemList(ConstValue.Group_InterfacePopup).FirstOrDefault(x => url.Contains(x.ConstValue)) != null;
- bool IsSafeReferer = ConstValue.drpConstItemList(ConstValue.Group_SafeReferer).FirstOrDefault(x => x.ConstValue == url) != null;
-
- if (!IsDataShowPage && !IsSafeReferer)
- {
- if (this.Page.Request.AppRelativeCurrentExecutionFilePath != "~/Login.aspx")
- Response.Redirect("~/Login.aspx");
- return;
- }
-
+ fullPath = fullPath.Substring(appPath.Length); // 去掉应用程序根路径
}
- else
+ //去除fullPath 开头的 /
+ if (fullPath.StartsWith("/"))
{
- Uri uri = new Uri(a);
- Uri uri2 = new Uri(SysConstSetService.CNCECPath);
- if (uri.Host==uri2.Host)
+ fullPath = fullPath.Remove(0, 1);
+ }
+ // 检查auth_token参数实现iframe自动登录
+ string authToken = Request.QueryString["auth_token"];
+ if (!string.IsNullOrEmpty(authToken) && this.CurrUser == null)
+ {
+ try
{
- if (this.CurrUser == null)
+ // 解密并验证token
+ string decryptedToken = BLL.TokenHelper.DecryptToken(authToken);
+ var tokenData = JsonConvert.DeserializeObject(decryptedToken);
+
+ // 验证时间戳(2小时有效期)
+ long timestamp = tokenData.timestamp;
+ if (DateTimeOffset.Now.ToUnixTimeSeconds() - timestamp <= 7200) // 2小时 = 7200秒
{
- this.Session["CurrUser"] = UserService.GetUserByUserId(Const.sysglyId);
+ // 验证用户ID
+ string userId = tokenData.user_id;
+ if (userId == Const.sysglyId)
+ {
+ var user = UserService.GetUserByUserId(Const.sysglyId);
+ if (user != null)
+ {
+ this.Session["CurrUser"] = user;
+ BLL.LogService.AddLog(Const.sysglyId, "iframe Token自动登录成功");
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ BLL.LogService.AddLog("", $"iframe Token自动登录失败:{ex.Message}");
+ }
+ }
+ string httpRefere = Request.ServerVariables["HTTP_REFERER"];
+ if (httpRefere==null) //判断是否为空。目的是为了防止直接在浏览器地址栏输入网址访问
+ {
+ bool IsDataShowPage = ConstValue.drpConstItemList(ConstValue.Group_InterfacePopup).FirstOrDefault(x => fullPath.Contains(x.ConstValue)) != null;
+ bool IsSafeReferer = ConstValue.drpConstItemList(ConstValue.Group_SafeReferer).FirstOrDefault(x => x.ConstValue == fullPath) != null;
+
+ // 如果不在安全页面列表中且用户未登录,重定向到登录页面
+ if (!IsDataShowPage && !IsSafeReferer && this.CurrUser == null)
+ {
+ string loginform = ConfigurationManager.AppSettings["LoginForm"];
+ if (!string.IsNullOrEmpty(loginform))
+ {
+ if (this.Page.Request.AppRelativeCurrentExecutionFilePath != "~/Login_ZJ.aspx")
+ Response.Redirect("~/Login_ZJ.aspx");
+ return;
}
}
}
+ /*if (CurrUser == null && HttpContext.Current.Request.Path != FormsAuthentication.LoginUrl)//防止没有登录直接访问通用界面
+ {
+ Response.Redirect(FormsAuthentication.LoginUrl);
+
+ }*/
+ //var menuModel = (from x in Funs.DB.Sys_Menu where x.Url.Contains(fullPath) select x.MenuId).ToList();//判断访问的页面是否在菜单中
+ //if (menuModel!=null&&menuModel.Count>0)
+ //{
+ // var thisUserAllMenuIdLis = CommonService.GetAllMenuList(this.CurrUser.LoginProjectId, this.CurrUser.UserId);
+ // if (menuModel.Intersect(thisUserAllMenuIdLis).Count()==0)
+ // {
+ // Response.Redirect(FormsAuthentication.LoginUrl);
+
+ // }
+
+ //}//没有在菜单中则不做权限判断(暂时没有控制弹窗的统一权限校验)
+
var pm = PageManager.Instance;
if (pm != null)
{
@@ -264,7 +314,7 @@ namespace FineUIPro.Web
System.Web.UI.HtmlControls.HtmlGenericControl linkCtrl = new System.Web.UI.HtmlControls.HtmlGenericControl("link");
linkCtrl.Attributes["rel"] = "stylesheet";
linkCtrl.Attributes["type"] = "text/css";
- linkCtrl.Attributes["href"] = ResolveClientUrl("~/res/css/common.css?v" + GlobalConfig.ProductVersion);
+ /*linkCtrl.Attributes["href"] = ResolveClientUrl("~/res/css/common.css?v" + GlobalConfig.ProductVersion);*/
Header.Controls.AddAt(GetHeadStyleCSSIndex(), linkCtrl);