首页 新闻 会员 周边

request跨域获取session失效

0
悬赏园豆:100 [已解决问题] 解决于 2016-08-08 17:11

如下代码,传到另外一个域名就获取不到session了

(localhost:12402/Home/Index)

 Session["MemberUser"]=123456;

            string url = "api/Home/GetTop8FileDown";
            string result = CrossJs.DoGet(ApiUrl + url );

 

public static string DoGet(string url)
        {
            CookieContainer cookieContainer = new CookieContainer();
            string serviceAddress = url;
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceAddress);
            request.Method = "GET";
            request.ContentType = "application/json";
            HttpWebResponse response =(HttpWebResponse)request.GetResponse();
            
            
            using (StreamReader dataStream = new StreamReader(response.GetResponseStream()))
            {
                var result = dataStream.ReadToEnd();
                return result;
            }
        }

 

(localhost:2412/Home/Index)

 public string GetTop8FileDown()
      {
          
                int MemberId = Convert.ToInt32(HttpContext.Current.Session["MemberUser"]);
                var member = (from a in db.ec_Member where a.MemberID == MemberId select a).FirstOrDefault();

  }

一直获取不到这一个HttpContext.Current.Session["MemberUser"] 。

渴死的鱼丶的主页 渴死的鱼丶 | 初学一级 | 园豆:124
提问于:2016-04-07 16:23
< >
分享
最佳答案
1

session 因该是应用程序级的  换句话说 共享的媒介是 应用程序

cookie才是浏览器级的 也就是同一个浏览器可以共享cookie 然后基于域名隔离 (但是父子域名可以不受限)

收获园豆:60
小眼睛老鼠 | 老鸟四级 |园豆:2731 | 2016-04-08 00:36
其他回答(3)
1

哈哈哈,好奇,刻舟求剑吗。

收获园豆:20
写代码的小2B | 园豆:4371 (老鸟四级) | 2016-04-07 16:48

表示不懂!

支持(0) 反对(0) 渴死的鱼丶 | 园豆:124 (初学一级) | 2016-04-07 17:32

@渴死的鱼丶: 

好吧,针对你的需求,建议你不要通过Session来传递值。

可以通过Cookie,Url或者Form。

支持(0) 反对(0) 写代码的小2B | 园豆:4371 (老鸟四级) | 2016-04-07 17:35

@写代码的小2B: 需要一个安全的传递方式,为什么Session不可以

支持(0) 反对(0) 渴死的鱼丶 | 园豆:124 (初学一级) | 2016-04-07 17:37

@渴死的鱼丶: 

Session没有跨域的概念,也不是这样用的。

如果需要安全的方式加密后使用Form传递。

支持(0) 反对(0) 写代码的小2B | 园豆:4371 (老鸟四级) | 2016-04-07 17:39

@写代码的小2B: Session不是可以资源共享么,在配置里面写个sessionState 存数据库的配置不是可以多域名共享吗,我通过ajax传递跨域都可以读取到Session ,就是换了这个方法不行了

支持(0) 反对(0) 渴死的鱼丶 | 园豆:124 (初学一级) | 2016-04-07 17:44

@渴死的鱼丶: 

这···,我井底之蛙了。没有接触过,帮你查了下资料

Sharing SQL Server Session State across Web Applications

支持(0) 反对(0) 写代码的小2B | 园豆:4371 (老鸟四级) | 2016-04-07 17:56

@写代码的小2B: 我想你可能没有理解我的意思,我说的存储会话状态的这种方法我已经试过了,通过AJAX跨域调用时可以的,现在我用的是request.GetResponse()响应,就获取不到Session了。

支持(0) 反对(0) 渴死的鱼丶 | 园豆:124 (初学一级) | 2016-04-07 18:09
1

如果你的session是存在进程中,那么session是无法这样跨程序调用的。

你这个端口不一样(等价于两个域名),所以cookie也无法使用。

 

这种场景,建议你使用token,或者把session存储在数据库中。

收获园豆:20
幻天芒 | 园豆:37175 (高人七级) | 2016-04-09 09:01

存数据库的意见试过了通过Ajax访问是有Session的,通过request.GetResponse()这个访问就没有了!

支持(0) 反对(0) 渴死的鱼丶 | 园豆:124 (初学一级) | 2016-04-11 18:03

@渴死的鱼丶: ajax和一般请求没有本质上的差异,所以应该是你用法不对。

支持(0) 反对(0) 幻天芒 | 园豆:37175 (高人七级) | 2016-04-12 09:21
1

在本回复中,我会以最详细的文字从原理上给你解答,并提出一些修改方案和替代方案。

你之所以遇到这个问题,本质上是对asp.net 的Session这个黑盒子不了解。你试图在服务端帮前端去其它服务实例获取数据,这是可行的设计,问题在于通过Session来验证客户端,导致问题解决起来比较棘手。

方案1:

假设你的代码里很多以方都用了Session,如果弃用Session重构量比较大的话,建议你还是保持使用Session,要做修改的地方是:修改方法是DoGet和修改Session的保存方式或Session的提供者。

默认的Session提供者的配置是把Session数据保存到服务实例进程中,所以其它服务实例比如服务B通过一样的Key去B的进程空间找对应的Session是找不到;如果把配置改为Asp.net状态服务器上,也就是多个服务器实例的都共用同一Session数据,貌似可行,但其实还是不行,因为Session还区分域名,跨了域Session还是不共;把配置改为保存到SqlServer,貌似可以作到多服务实例Session共享,我没有试;我以前自己用memcache来保存Session,自己实例了Session提供者,而不用默认自带的Session提供者,达到Session共享的效果。

除了Session共享配置好之后,你上面的DoGet方法是有问题的,这个方法你是用来帮前端的js从其它服务实例获取数据,你应该把前端传过来的Cookie也进行提交,因为Session的本质是Cookie里的Asp.netSessionID这个Key对应Session服务器里的一个字典,Session["key"]的值是字典的一个名为"Key"的键的值。所以在请求之前,cookieContainer这个实例应该把Request所带的Cookie添加上来,同时为了满足Cookie变化的场景,在请求完成之后,把cookieContainer里的Cookie取出,追加到Response里,达到更新前端的cookie的目的。

方案2:

不使用Session了,因为实在太麻烦了,用token吧,开源有一些项目,或者自己代码实现一个简单的token服务也可以,本质上还是跟Session类似,登录时,把用户信息保存到Token服务器,返回Token,Token设置一个过期时间,反过来,在验证用户时,将用户提交的token去token服务器查询获取用户信息。token服务可以用redis来写一个。

jiulang | 园豆:437 (菜鸟二级) | 2016-04-10 14:51

额这个Token没用过,不知道是什么,能不能帮忙弄个填补一下,或者写一个简单的例子

支持(0) 反对(0) 渴死的鱼丶 | 园豆:124 (初学一级) | 2016-04-11 17:49
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册