首页 新闻 会员 周边

使用HttpWebRequest模拟登陆后30分钟后会话失效问题

0
悬赏园豆:50 [已解决问题] 解决于 2017-01-06 13:36

背景:
有一个asp.net网站(简称为A网站),基于net frameworkd1.1,form认证方式,有个功能页面是显示合同.系统集成的需要,其他系统希望调用一个web服务,拿到合同数据后进行打印

实现方案:
保持A网站不变,用c#创建了一个web服务(简称B服务),基于net framework4.0,内部使用HttpWebRequest实现了模拟登陆,拿到了身份认证cookie,然后调用合同页面,传入身份认证cookie,获取输出流,转换成pdf字节码输出。
模拟登陆内含两个步骤:1.访问登陆页面,解析返回,获取隐藏字段_viewstate的值 2.再次访问登陆页面,完成登陆,拿到身份认证cookie。

因此一个打印合同的接口调用,B服务实际会进行三次请求(取viewstate,模拟登陆、请求合同页面),总耗时约6-8秒,进行优化,缓存了身份认证cookie,首次登陆耗时较长,以后登陆,跳过了模拟登陆,直接请求合同页面,只需要1-2秒。

存在问题:
实际测试发现,开始一段时间内,B服务运行正常,但是每间隔半小时,身份认证会失效,自动跳转到登陆页面,导致需要重新进行身份认证过程,也就是每隔半小时,会有一次接口调用需要6-8秒,耗时太长,影响用户体验(打印服务在自助设备上)。

查了A网站Web.config,是默认的20分钟会话超时时间。会话失效时间非常规律,每隔半小时(自己写个小程序,定时调用,测试结果可靠)。

疑问
对这个问题非常疑惑,对于A网站,用户登陆后,会话超时时间是20分钟,20分钟以内,若用户有请求,如点击按钮,刷新页面,则会话时间会延长,实际超时时间是从用户无操作时开始计算20分钟。B接口服务,首次访问模拟登陆后再缓存身份认证cookie,以1分钟的时间间隔去频繁调用合同功能页面,正常情况下不应该出现半小时会话失效的现象。

推测
使用httpWebRequest方式,与用户使用浏览器进行真实操作,实际上还是有差异,但这种差异在哪,哪位清楚?

求助
哪位有这方面的经验?如何才能实现保持会话一直有效?

大浪淘沙的主页 大浪淘沙 | 初学一级 | 园豆:57
提问于:2016-11-04 14:54
< >
分享
最佳答案
0

猜测是Session超时了,设置 HttpWebRequest的CookieContainer属性,并保证每次请求的CookieContainer是同一个实例。

收获园豆:50
ArthurLi | 小虾三级 |园豆:686 | 2016-11-04 15:37

CookieContainer一直通不过身份认证,用的另外一种方式,模拟登陆时读取string cookie=response.Headers["Set-Cookie"],缓存,请求后续页面时request.Headers.Add("Cookie", cookie);本质应该是一样的

大浪淘沙 | 园豆:57 (初学一级) | 2016-11-04 15:42

@大浪淘沙: CookieContainer可以保证Session不丢失,不用CookieContainer的话,Session会丢失。new一个CookieContainer就可以了,保证每个HttpWebRequest的实例用的都是同一个CookieContainer实例,模拟登陆设置的Cookie还可以继续使用request.Headers.Add("Cookie", cookie);

ArthurLi | 园豆:686 (小虾三级) | 2016-11-04 15:49

@Don'tWorryBeHappy: 非常感谢,我尝试下,其实主要是想搞清楚原理和机制

大浪淘沙 | 园豆:57 (初学一级) | 2016-11-04 15:59

@Don'tWorryBeHappy: 问题确定了,是A网站比较老,cookie名称不规范,中间有空格,在web.config的配了这么一个东西name='login Cookie',然后模拟登陆完成后,response.Cookies取到的cookie为空,只能用response.Headers["Set-Cookie"]方式把身份认证cookie拿到,这样带空格的cookie名,往cookieContainer里加,会报错,之前验证过,将这个身份认证cookie与ASP.NET_SessionId 一块通过request.Headers.Add("Cookie", cookie);方式加上,发现到了半小时左右就会强制失效。

请教下,如果不使用CookiesContainer,想办法拼装起来加到request.Header里,跟CookiesContainer干的工作应该是一样的吧?

大浪淘沙 | 园豆:57 (初学一级) | 2016-11-09 16:40

@大浪淘沙: 理论上你通过第一次的request认证能拿到一个存储session的header,下次request再把这个session发送给服务器就可以了,没有这么做过,不确定可行性。

ArthurLi | 园豆:686 (小虾三级) | 2016-11-14 15:14
其他回答(4)
0

你用浏览器访问不也是超过了多长时间就超时了么?

顾晓北 | 园豆:10844 (专家六级) | 2016-11-04 15:01

用户在不断请求的情况下,会话时间会顺延,失效时间20分钟,是指无交互后20分钟才会超时失效

支持(0) 反对(0) 大浪淘沙 | 园豆:57 (初学一级) | 2016-11-04 15:03
0

如果一个Asp.Net 应用长时间没有执行请求,那么它默认会关闭(shutdown)。如果你想让后台工作一直在web应用中执行(这是默认行为),那么你要确保web应用配置成了总是运行。否则,会话就会失效。

很多技术来实现这个目的。最简单的方法是从外部应用定期向你的web应用发送请求。这样,你可以检查web应用是否开启并且处于运行状态。

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 15:25

我当前的测试就是在不间断的发请求啊,用定时器每分钟调用一次接口服务B,接口服务B去访问网站A,正常情况下,接口服务B与网站A的会话不应当在半小时候失效,因为期间,接口服务B不断使用缓存的身份cookie,用HttpWebRequest方式去请求网站A取数据,会话应该一直顺延。

支持(0) 反对(0) 大浪淘沙 | 园豆:57 (初学一级) | 2016-11-04 15:38

@大浪淘沙: 怕是你们的服务器每隔半小时就会有个特别消耗资源的程序会运行,造成你现在看到的效果,看你的描述应该不是你自己的问题,多看看外部因素。

支持(0) 反对(0) 刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 15:44
0

你文中“20分钟以内,若用户有请求,如点击按钮,刷新页面,则会话时间会延长”——也未见你如何证实是可靠的;

首先得验证一下是否Session的可靠性吧 —— 这也不排除Session自己搞过,尤其是这种老版本存在sesion丢失严重,微软是喊了大家自己去数据库实现的。

在通讯中需要保持回话的有一种东西叫心跳,用户的点击实际上你是无法预知的,如果session是可靠的,那么可增加一个接口或者用现成的轻量级接口来充当心跳。没有实际数据不敢妄言,我认为你最好把浏览器的请求及发送数据都抄上去,如果写了什么特许代码也是说不清楚的——这个是遇到过的。

如果证实Session就是个错误,那就只有把心跳逻辑再改改,每到时间进行预加载,加载完成后进行“Session”切换。

花飘水流兮 | 园豆:13560 (专家六级) | 2016-11-04 17:19
0

最终定位问题发生在A网站web.config配置中的身份认证cookie名称问题,中间有空格,使用net framework 4.0 创建的B服务,CookieContainer一直无法解析处理,尝试了各种方式,无法在身份验证和会话保持都完美解决,最终还是将那个cookie名称中间空格去掉了,才从根源上解决问题,谢谢大家

大浪淘沙 | 园豆:57 (初学一级) | 2017-01-06 13:36
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册