最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 您所在的位置:网站首页 二级域名共享session 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

2023-03-24 20:41| 来源: 网络整理| 查看: 265

简要介绍,本文主要内容是实现通过ASP.NET自己的Sql Server的Session存储机制实现,通过存储过程实现忽略程序标识的区别,达到多程序池间Session数据共享的目的。详细原文:

本文转载人数己经太多,所以不知道原文地址何处,敬请谅解!

我的链接地址是http://space.itpub.net/12639172/viewspace-675757

大致思路:

采用SqlServer方式存储Session,分析数据库表结构、原理、流程,大致可以得到SqlServer存储Session的方法:

表结构:

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

            ASPStateTempApplications表存储应用程序Id及名称

            ASPStateTempSessions表存储具体的Session值

            不同的应用程序会在ASPStateTempApplications中注册不同的数据,从而在ASPStateTempSessions中有不同的Session,如果要实现Session共享,可以用欺骗SqlServer的方法:用某种方法使得不同的应用程序访问数据库时用相同的App!为了达到这个目的,分析[dbo].[TempGetAppID]这个存储过程,代码如下:

 1 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    ALTER PROCEDURE [dbo].[TempGetAppID]

 2

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    @appName    tAppName,

 3

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    @appId      int OUTPUT

 4

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    AS

 5

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    SET @appName = LOWER(@appName)

 6

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    SET @appId = NULL

 7

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]  8 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    SELECT @appId = AppId

 9

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    FROM [Herald.Session].dbo.ASPStateTempApplications

10

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    WHERE AppName = @appName

11

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 12 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    IF @appId IS NULL BEGIN

13

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

        BEGIN TRAN        

14

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 15 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

        SELECT @appId = AppId

16

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

        FROM [Herald.Session].dbo.ASPStateTempApplications WITH (TABLOCKX)

17

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

        WHERE AppName = @appName

18

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 19 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

        IF @appId IS NULL

20

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

        BEGIN

21

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

            EXEC GetHashCode @appName, @appId OUTPUT

22

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 23 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

            INSERT [Herald.Session].dbo.ASPStateTempApplications

24

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

            VALUES

25

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

            (@appId, @appName)

26

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 27 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

            IF @@ERROR = 2627 

28

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

            BEGIN

29

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

                DECLARE @dupApp tAppName

30

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 31 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

                SELECT @dupApp = RTRIM(AppName)

32

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

                FROM [Herald.Session].dbo.ASPStateTempApplications 

33

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

                WHERE AppId = @appId

34

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 35 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

                RAISERROR('SQL session state fatal error: hash-code collision between applications ''%s'' and ''%s''. Please rename the 1st application to resolve the problem.', 

36

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

                            18, 1, @appName, @dupApp)

37

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

            END

38

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

        END

39

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 40 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

        COMMIT

41

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]

    END

42

最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转] 43 最好的(自我感觉)实现多个ASP.NET跨程序池共享Session [转]     RETURN 0

可以看到传入参数是AppName,通过AppName获取AppId,如果不存在则在ASPStateTempApplications表中插入该条记录,这里AppName参数在传入时是不同的应用程序不同的,当然我们可以在这里小改一下...注意第5行SET @appName = LOWER(@appName) 我们可以毫不客气的改成SET @appName = 'Everything you want ^_^' 

            好了(不知道这样做微软会不会很不悦...),大功告成,清理残留的Session,最好重启一下IIS,不用修改旧程序本身丝毫(配置web.config除外),实现了Session共享...以后凡是使用该数据库作为Session存储的都可以共享Session了...

      其他的一些配置说明如下:

            配置web.config节: 

  < sessionState  mode ="SQLServer"  sqlConnectionString ="data source=[Server];initial catalog=[DataBase];user id=[UserName];password=[Password]"  allowCustomSqlDatabase ="true"   timeout ="120" />

            配置SQLServer:

aspnet_regsql.exe  - sstype c  - ssadd  - d [DataBase]  - U [UserName]  - P [Password]  - S [Server]

           修改[dbo].[TempGetAppID]:将@appName设为一个定值,修改保存。

            清理Session,重启IIS,KO!

       另外:这个方法其实很Bug 嘿嘿 再多研究下数据库的存储过程或者用某种方法定制appName的话,可能可以实现更多的功能。

只这样还不够,需要将Session的Cookie写到客户端,可以让多个程序进行读取。

今天, 我要写的是如何在二级域名站点之间,主站点和二级域名站点之间共享Session。

首先, Session要共享,站点之间SessionID必须要一致,那怎么保证SessionID一致呢?

ASP.NET中的SessionID是存储在客户端的cookie之中键值为ASP.NET_SessionId用来维护浏览者Session对应关系的一个字符串,要想在二级域名站点之间,主站点和二级域名站点共享SessionID就必须先共享,那么我们就必须先实现ASP.NET_SessionId这一cookie的共享。

CrossDomainCookieModule

------------------------------------------------------------------------------------------------

public class CrossDomainCookie : IHttpModule

{

private string m_RootDomain = string .Empty;

#region IHttpModule Members

public void Dispose()

{

}

public void Init(HttpApplication context)

{

m_RootDomain = ConfigurationManager.AppSettings[ " RootDomain " ];

context.EndRequest += new System.EventHandler(context_EndRequest);

}

void context_EndRequest( object sender, System.EventArgs e)

{

HttpApplication app = sender as HttpApplication;

for ( int i = 0 ; i < app.Context.Response.Cookies.Count; i ++ )

{

app.Context.Response.Cookies[i].Domain = m_RootDomain;

}

}

#endregion

}

上面的Module重设了所有cookie的domain到root domain, root domain在web.config中设置。也许有人会说这是眉毛胡子一把抓重写了所有cookie的domain, 那他也可以判断一下cookie的name, 如果为ASP.NET_SessionId的话才重写。

如果主站点和二级域名站点是同一站点,那么做到这一步,你的session就已经共享了,因为Session的ID是相同的,而且Session容器也是同一个。

如果主站点和二级域名站点是两个不同站点,则需要进行更多的操作了。

如果两个站点是不同的服务器的话,解决方法要简单点:

1) 使用相同的state server来存储Session.

2) 在两个站点的web.config设置相同的machineKey.

MachineKey的设置请参考http://msdn.microsoft.com/zh-cn/asp.net/w8h3skw9.aspx

3) 给两个站点设置相同name

这样做是为了确保两个站点的siteID相同,siteID是site name的hash值,注意请不要使用默认站点,因为默认站点的siteID并非site name的hash.

如果两个站点是在同一的服务器的话,需要对CrossDomainCookie再作一下修改,此方法也可应用于两个站点在不同服务器的情况:

1) 使用相同的state server来存储Session.

2) 用反射来设置System.Web.SessionState.OutOfProcSessionStateStore的静态字段s_uribase的值

public class CrossDomainCookie : IHttpModule

{

private string m_RootDomain = string .Empty;

#region IHttpModule Members

public void Dispose()

{

}

public void Init(HttpApplication context)

{

m_RootDomain = ConfigurationManager.AppSettings[ " RootDomain " ];

Type stateServerSessionProvider = typeof (HttpSessionState).Assembly.GetType( " System.Web.SessionState.OutOfProcSessionStateStore " );

FieldInfo uriField = stateServerSessionProvider.GetField( " s_uribase " , BindingFlags.Static | BindingFlags.NonPublic);

if (uriField == null )

throw new ArgumentException( " UriField was not found " );

uriField.SetValue( null , m_RootDomain);

context.EndRequest += new System.EventHandler(context_EndRequest);

}

void context_EndRequest( object sender, System.EventArgs e)

{

HttpApplication app = sender as HttpApplication;

for ( int i = 0 ; i < app.Context.Response.Cookies.Count; i ++ )

{

app.Context.Response.Cookies[i].Domain = m_RootDomain;

}

}

#endregion

}

完成这样的修改之后就可以实现Session的共享了。

同样如果你是使用SQL server来存储Session, 也可以使用类似的方法来解决Session共享问题。

转载于:https://www.cnblogs.com/angrybird/archive/2011/11/22/2258508.html



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有