zoukankan      html  css  js  c++  java
  • asp.net跨域共享session(不能跨主机名)

    1.首先简要说说asp.net 的session机制,当客户端向服务端发生会话时(不是访问了网站某页面就一定产生了会话),服务端会写一个cookie到客户端,这个cookie保存着sessionid ,名字为“ASP.NET_SessionID” ,在下一次发生向服务端的请求时这个cookie会包含在请求头中,这个cookie仅仅包含了sessionid ,其他信息以(某种形式)保存在服务端并被sessionid标识。

    2.因为我们要实现两个域的session共享,我们采用的方式是session的值保存在SqlServer数据库中(至于为什么要保存在SqlServer数据库中,这里不做探讨),如何用数据库保存session的资料可以很轻易的在博客园中找到,子秋的博客中有记http://www.cnblogs.com/zhangziqiu/archive/2009/03/26/sessionserver.html

    3.表ASPStateTempApplications有两个字段 ,一个appid ,一个appname ,一个应用程序相当于一个网站,这个表中的数据会在网站第一次被访问并产生session时添加,一个网站会产生一条记录,ASPStateTempSessions 表才是真正保存会话信息的表,有个二进制数据类型的字段用来保存session数据,还有创建时间过期时间的字段,当然少不了主键标识字段,也就是sessionid, 注意了!这个sessionid 的保存会在真正的sessionid上加个后缀 ,后缀是相应的ASPStateTempSessions表中应用程序id的十六进制表示形式,这样的话,如果两个应用程序不小心产生了同样的sessionid 也不会出现问题,因为还有后缀标识。

    4.问题出来了,如果让两个域(既是两个应用程序,两个网站)产生同样的sessionid 并且让应用程序名一样,不就可以共享session了吗?这样一来又有问题了?a.会话sessionid是保存在名字为“ASP.NET_SessionId”的cookie中的,我们知道cookie是不能跨域的,但是我们有方法让他能够夸二级多级域名,注意:主域名还是不能跨的方法就是该cookie的主机名,具体代码如:
    HttpCookie  co =  Request.Cookies["ASP.NET_SessionId"];
            co.Domain = ".mysite.com";
            Request.Cookies.Set( co );
    这一步只让sessionid 一样了呀,还差一步,就是让应用程序名一样
    b.如何让应用程序名一样呢 ,我们分析ASPStateTempApplications这张表中的记录是如何的来的,上面也有简单提到,具体分析后,发现记录是通过存储过程TempGetAppID插入的,
    我们将其改为:
    代码
    set ANSI_NULLS ON
    set QUOTED_IDENTIFIER ON
    go



        
    ALTER PROCEDURE [dbo].[TempGetAppID]
        
    @appName    tAppName,
        
    @appId      int OUTPUT
        
    AS
        
    SET @appName = 'fejerry' -- LOWER(@appName)
        SET @appId = NULL

        
    SELECT @appId = AppId
        
    FROM [ASPState].dbo.ASPStateTempApplications
        
    WHERE AppName = @appName

        
    IF @appId IS NULL BEGIN
            
    BEGIN TRAN        

            
    SELECT @appId = AppId
            
    FROM [ASPState].dbo.ASPStateTempApplications WITH (TABLOCKX)
            
    WHERE AppName = @appName
            
            
    IF @appId IS NULL
            
    BEGIN
                
    EXEC GetHashCode @appName@appId OUTPUT
                
                
    INSERT [ASPState].dbo.ASPStateTempApplications
                
    VALUES
                (@appId@appName)
                
                
    IF @@ERROR = 2627 
                
    BEGIN
                    
    DECLARE @dupApp tAppName
                
                    
    SELECT @dupApp = RTRIM(AppName)
                    
    FROM [ASPState].dbo.ASPStateTempApplications 
                    
    WHERE AppId = @appId
                    
                    
    RAISERROR('SQL session state fatal error: hash-code collision between applications ''%s'' and ''%s''. Please rename the 1st application to resolve the problem.'
                                
    181@appName@dupApp)
                
    END
            
    END

            
    COMMIT
        
    END

        
    RETURN 0  
    给一个固定的应用程序名,不管什么网站,只要以当前SqlServer作为session存储机制,都会记录为同一个应用程序,换句话说,就是表ASPStateTempApplications将只会有一条记录。

     5。我这人喜欢钻牛角尖,这条记录是什么时候插入到数据库的呢?于是我手动删除了这条记录,但是即使删除了,仍然不影响应用程序的使用,不影响session的共享,于是我又把应用程序(网站)重启了, 对网站产生第一个会话后,我又去观察表ASPStateTempApplications,奇怪了,仍然一条记录都没有。

      于是很自然的我把iis给重启了, 再对网站产生第一个会话后,又去观察表ASPStateTempApplications,出现了,出现了,终于出现了一条新的记录。总结:表ASPStateTempApplications中的记录是在应用程序产生第一个会话时执行存储过程 TempGetAppID产生的,(并且大胆猜测这条记录的信息也保存在iis中,依据是删掉表中记录也无影响)。

      这是我在博客园的第一篇技术随笔,欢迎拍砖扔鞋,当然最重要的还是不吝赐教文中有问题的地方 。

  • 相关阅读:
    [LeetCode] 965. Univalued Binary Tree
    [LeetCode] 811. Subdomain Visit Count
    [LeetCode] 509. Fibonacci Number
    [LeetCode] 1200. Minimum Absolute Difference
    [LeetCode] 590. N-ary Tree Postorder Traversal
    input单选框美化——自定义样式
    input单选框——获取选中值和设置选中值
    [LeetCode] 933. Number of Recent Calls
    mysql 一次性插入的数据量过大报错max_allowed_packet解决方法
    springboot+mybatis+达梦数据库
  • 原文地址:https://www.cnblogs.com/fejerry/p/1748691.html
Copyright © 2011-2022 走看看