多个ASP.NET站点如何通过ASP.NET State服务共享Session会话
笔者想实现多个ASP.NET的站点能够共享Session (会话),
bing, stackoverflow, baidu, FQgoogle找了一大圈,实验N小时,弄到快吐血才找到, 亲测可用,特意转载收藏。
注意: 原作者说到他这种其实是非官方的方式,算是一种hack, 通过反射的方式做的操作,适用于 IIS6 or IIS7 classic mode, IIS7 integrated mode
但不能确保未来更高版本的IIS是否兼容。
转载于:https://weblogs.asp.net/lichen/sharing-session-state-over-multiple-asp-net-applications-with-asp-net-state-server
Sharing session state over multiple ASP.NET applications with ASP.NET state server
具体步骤如下:
1. 启用ASP.NET State Service服务
2.修改注册表项
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\aspnet_state\Parameters
如果有ASP.NET站点与ASP.NET STATE服务不在同一台机器上,必须将AllowRemoteConnection 设置为1
Port默认为42424, 你也可以修改成自定义的端口
3. 配置每个ASP.NET站点的WEB.config,使用State服务作为Session管理的提供者
配置放在system.web节点下
<sessionState cookieName="MySessionId" mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" timeout="30"/>
<machineKey compatibilityMode="Framework20SP1" validationKey="9DBEBFAA6D3AF06F4505D3DA793A784BBB9CC63F2FC2F8CFD90F0E50E7B3E62CF2439C55C83BE1A2704B84B7F7AA720DFB5E2C507F4BB293C2A62E92E183B7AC" decryptionKey="FAC9018DB8D925DA093AB64DA682CB0BBE30B7DA5DF7451F" validation="SHA1" />
mode="StateServer"表示使用asp.net state 服务
stateConnectionString是asp.net state服务的地址, 如果不在本机,将127.0.0.1替换成state服务所在的主机地址,同时
确保防火墙没有限制42424端口或你定义的端口
cookieName是可以将系统默认的存放sessionid的cookie名称改成自定义的,你也可以不设置,使用系统默认的
4. 在Global.asax的init方法里运行下面这段关键代码
public override void Init()
{
base.Init();
foreach (string moduleName in this.Modules)
{
string appName = "MyApp";
IHttpModule module = this.Modules[moduleName];
SessionStateModule ssm = module as SessionStateModule;
if (ssm != null)
{
FieldInfo storeInfo = typeof(SessionStateModule).GetField("_store", BindingFlags.Instance | BindingFlags.NonPublic);
SessionStateStoreProviderBase store = (SessionStateStoreProviderBase)storeInfo.GetValue(ssm);
if (store == null) //In IIS7 Integrated mode, module.Init() is called later
{
FieldInfo runtimeInfo = typeof(HttpRuntime).GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic);
HttpRuntime theRuntime = (HttpRuntime)runtimeInfo.GetValue(null);
FieldInfo appNameInfo = typeof(HttpRuntime).GetField("_appDomainAppId", BindingFlags.Instance | BindingFlags.NonPublic);
appNameInfo.SetValue(theRuntime, appName);
}
else
{
Type storeType = store.GetType();
if (storeType.Name.Equals("OutOfProcSessionStateStore"))
{
FieldInfo uribaseInfo = storeType.GetField("s_uribase", BindingFlags.Static | BindingFlags.NonPublic);
uribaseInfo.SetValue(storeType, appName);
}
}
}
}
}
5. 如果是跨服务器的话,当你从一个asp.net网站重定向到另外一个网站时,由于cookie无法跨域,需要
你自己想办法能够重定向后的网站能够识别你同时生成SessionId。
这里你可以用Url带上参数把sessionId传过去,然后在后台用以下代码给浏览器客户端用cookie传回session id
代码如下: 假设你的URL类似 /index?sid=xxxxxxxxxxxxxx
var Context = System.Web.HttpContext.Current;
var manager = new SessionIDManager();
string newID = sid;
bool redirected = false;
bool isAdded = false;
manager.SaveSessionID(Context, newID, out redirected, out isAdded);
Session["authenticated"] = true;
Return RedirectToAction("xxxx"); // 需要重定向,这样浏览器下次发出请求就能带上session id, 当前还无法访问共享的session
注意 Session["authenticated"] = true 只是个示例, 测试发现至少要给Session赋一个值,才可能后端会给浏览器返回sessionid 的cookie