c# - 更改 ASP.Net 会话 ID - 通过 AJAX 从桌面应用程序调用
问题描述
我有一个旧的 VB6 应用程序 - 我需要通过 Web 浏览器访问 ASP.net 站点。我打开浏览器并成功调用了 ASP 站点。我需要 VB6 应用程序知道 Web 浏览器会话何时关闭。Web 浏览器会话打开时,需要禁用 VB 应用程序表单(或保存按钮)。(我不想使用windows进程的进程ID来检查这个。)
我的想法是:
- 也许是跨域cookie?(安全?)
- 我的 VB6 应用程序能够调用服务器 WebMethods
- 在两个应用程序都使用的数据库中保存会话 ID?
一些建议会很好。非常感谢。
解决方案
公司内部申请。
桌面应用程序 (VB6)
- 允许 VB6 应用程序联系 Asp 服务的代码。在任何 Asp.Net 页面上创建一个额外的 [WebMethod] 在这种情况下,已将“IsWindowOpen”方法添加到 test.aspx 页面(请参见下面的红色文本)
- 向 ASP.Net 服务发送 JSON 消息以查询是否设置了 WINDOWS_STATUS 会话变量(这告诉我们浏览器窗口是否打开\关闭)。
当使用参数(计划 ID 等)向 Asp.Net 站点发送消息时,我们将发送一个额外的“会话 ID”参数。
在 VB6 应用程序中随机生成一个 Session Id [随机:24 个字符长,小写,以及 0-5 之间的数字],这是复制 Asp.Net 框架将如何生成自己的 Session Id 用于 HTML 和 C# 之间的通信. 然后,我们将使用我们自己随机生成的会话 ID 覆盖 Asp.Net 提供给我们的 Asp.Net 会话 ID。
检查是否在 VB6 中设置了 ASP.Net 会话变量:
Private Sub Command1_Click()
Dim objHTTP As Object
Dim Json As String
Dim result As String
' === Check if Browser Session is open ===
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
url = "http://dub-iisdev/SessionTest/test.aspx/IsWindowOpen"
objHTTP.open "POST", url, False
objHTTP.setRequestHeader("cookie") = "ASP.NET_SessionId=" + txtCookie.Text ' Required twice
objHTTP.setRequestHeader("cookie") = "ASP.NET_SessionId=" + txtCookie.Text ' Required twice
objHTTP.setRequestHeader "Content-type", "application/json"
objHTTP.send (Json)
result = objHTTP.responseText
txtOutput.Text = result
Set objHTTP = Nothing
End Sub
ASP.NET
我们需要一些管道:设置 ASP.Net 会话 ID 的小方法 一个小的关闭 aspx 页面,当我们离开浏览器时将运行一些代码,以及现有页面中的一些额外的 C# 方法和 JavaScript。
1.设置会话ID:
将变量从旧会话复制到新位置
protected void ReGenerateSessionId(string newsessionID)
{
SessionIDManager manager = new SessionIDManager();
string oldId = manager.GetSessionID(Context);
string newId = manager.CreateSessionID(Context);
bool isAdd = false, isRedir = false;
manager.RemoveSessionID(Context);
manager.SaveSessionID(Context, newsessionID, out isRedir, out isAdd);
HttpApplication ctx = (HttpApplication)HttpContext.Current.ApplicationInstance;
HttpModuleCollection mods = ctx.Modules;
System.Web.SessionState.SessionStateModule ssm = (SessionStateModule)mods.Get("Session");
System.Reflection.FieldInfo[] fields = ssm.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
SessionStateStoreProviderBase store = null;
System.Reflection.FieldInfo rqIdField = null, rqLockIdField = null, rqStateNotFoundField = null;
SessionStateStoreData rqItem = null;
foreach (System.Reflection.FieldInfo field in fields)
{
if (field.Name.Equals("_store")) store = (SessionStateStoreProviderBase)field.GetValue(ssm);
if (field.Name.Equals("_rqId")) rqIdField = field;
if (field.Name.Equals("_rqLockId")) rqLockIdField = field;
if (field.Name.Equals("_rqSessionStateNotFound")) rqStateNotFoundField = field;
if ((field.Name.Equals("_rqItem")))
{
rqItem = (SessionStateStoreData)field.GetValue(ssm);
}
}
object lockId = rqLockIdField.GetValue(ssm);
if ((lockId != null) && (oldId != null))
{
store.RemoveItem(Context, oldId, lockId, rqItem);
}
rqStateNotFoundField.SetValue(ssm, true);
rqIdField.SetValue(ssm, newsessionID);
}
您的第一个登录页面将使用上面的 ReGenerateSessionId 类设置发送到服务器的新会话 ID(来自 VB6)参数。
在此代码向 Asp.Net 执行实例后,我们的 VB6 实例将具有相同的 Session Id 用于 HTTP 通信
protected void Page_Load(object sender, EventArgs e)
{
// Simulate Session ID coming in from VB6...
string sessionId;
Random rnd = new Random();
sessionId = "asdfghjklqwertyuiop12345" [24 char - a to z (small) & 0-5]
// Set new session variable and copy variable from old session to new location
ReGenerateSessionId(sessionId);
// Put something into the session
HttpContext.Current.Session["SOME_SESSION_VARIABLE_NAME"] = "Consider it done!";
}
2. 打开\关闭浏览器
ASP.Net 页面之一需要具有三个新的 WebMethod:SetOpenWindow、SetClosingWindow 和 IsWindowOpen
打开浏览器:
C#。SetOpenWindow:这将通过 .ready JavaScript 从您的第一个(或任何需要的)HTML 页面调用。页面加载后,JavaScript 将简单地触发对 SetOpwnWindow Web 方法的 Ajax 调用。该方法会将会话变量 WINDOW_STATUS 设置为 OPEN。
[WebMethod()]
[ScriptMethod(UseHttpGet = false)]
public static string SetOpenWindow()
{
HttpContext.Current.Session["WINDOW_STATUS"] = "OPEN";
return "Status:" + HttpContext.Current.Session["WINDOW_STATUS"];
}
ASPX。页面加载后,从 Ajax 调用 SetOpenWindow。这会将 WINDOW_STATUS 设置为 OPEN
<script src=”Scripts/jquery-1.4.1.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
jQuery.ajax({
url: 'test.aspx/SetOpenWindow',
type: "POST",
dataType: "json",
data: "",
contentType: "application/json; charset=utf-8",
success: function (data) {}//alert(JSON.stringify(data));
});
$("#form1").submit(function () {
submitted = true;
});
});
</script>
关闭浏览器:
在可以关闭浏览器窗口的页面上,调用 JavaScript 以捕获浏览器窗口关闭的时间(方便将其添加到母版页而不是每个页面!)。这会调用 ClosingSessionPage aspx 页面来运行 SetClosingWndow webmethod:
<script type=”text/javascript”>
var submitted = false;
function wireUpWindowUnloadEvents() {
$(document).on('keypress', function (e) { if (e.keyCode == 116) { callServerForBrowserCloseEvent(); } }); // Attach the event keypress to exclude the F5 refresh
$(document).on("click", "a", function () { callServerForBrowserCloseEvent(); }); // Attach the event click for all links in the page
}
$(window).bind("onunload", function () { if (!submitted) { callServerForBrowserCloseEvent(); event.preventDefault(); } });
$(window).bind("beforeunload", function () { if (!submitted) { callServerForBrowserCloseEvent(); event.preventDefault(); } });
window.onbeforeunload = function () { if (!submitted) { callServerForBrowserCloseEvent(); } };
window.onunload = function () { if (!submitted) { callServerForBrowserCloseEvent(); } };
$(window).bind("onunload", function () { if (!submitted) { callServerForBrowserCloseEvent();event.preventDefault();} });
function callServerForBrowserCloseEvent() {
window.open("ClosingSessionPage.aspx", "Closing Page", "location=0,menubar=0,statusbar=1,width=1,height=1"); }
function btn_onclick() { open(location, '_self').close(); }
</script>
上面的关闭 JavaScript 方法重定向到关闭的 aspx 页面以运行一些 ajax,然后关闭自身 - Ajax 调用 SetClosingWindow 会话 WINDOW_STATUS 变量为 CLOSED。
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server" title="Closing Session">
<script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
jQuery.ajax({
url: 'test.aspx/SetClosingWndow',
type: "POST",
dataType: "json",
data: "",
contentType: "application/json; charset=utf-8",
success: function (data) {
window.close();
} }); });
</script>
</head>
<body>
<form id="form1" runat="server">
<p>Closing browser session, please wait.</p>
</form>
</body>
</html>
C# SetClosingWindow 在浏览器窗口关闭并将 WINDOW_STATUS 设置为 CLOSED 时从 Ajax JavaScript 调用:
[WebMethod()]
[ScriptMethod(UseHttpGet = false)]
public static string SetClosingWndow()
{
HttpContext.Current.Session["WINDOW_STATUS"] = "CLOSED";
ScriptManager.RegisterClientScriptBlock((Page)(HttpContext.Current.Handler), typeof(Page), "closePage", "window.close();", true);
return "Status:" + HttpContext.Current.Session["WINDOW_STATUS"];
}
3. 浏览器是否打开?
VB6 在需要知道浏览器窗口是打开还是关闭时调用的 ASP.Net WebMethod。
[WebMethod()]
[ScriptMethod(UseHttpGet = false)]
public static string IsWindowOpen()
{
string isWindowOpen = HttpContext.Current.Session["WINDOW_STATUS"] != null ? HttpContext.Current.Session["WINDOW_STATUS"].ToString() : "CLOSED";
return "IsWindowOpen:" + isWindowOpen;
}
推荐阅读
- ontology - 您如何评估由一个类和数百个人组成的大规模本体(CSO)?
- design-patterns - 使用工厂设计模式如何阻止一个类必须预测它必须创建的对象类
- windows-server - 关闭 RDP 后如何防止注销/丢失屏幕
- json - 尝试替换请求 json 中的整数值(对于使用 request.replace() 的字符串)
- c# - ASP.NET Core 3.1 中基于角色的授权,带有 Identity 和 ExternalLogin
- python - Python - 在传递单个参数时克隆函数
- c# - Automapper:将行连接到带有详细对象列表的标题对象的对象
- javascript - 通过输入搜索栏选择中的过滤选项不适用于 safari
- reactjs - 通过 set-state 反应新的给定值不会更新组件值
- ruby-on-rails - 卡住试图找出 Rails 关联