|
ASP里最折磨人的同页题不是写代码,是面登登录跳转。你辛辛苦苦搭好一套后台,录后结果用户从不同入口进来,转问登录完直接被甩到404或者首页,同页题那种感觉就像你约了人在商场碰头,面登结果他告诉你“我到了”——但商场有八个门。录后 先说最常见的转问坑:Response.Redirect写死路径。很多老代码喜欢这么干:Response.Redirect("admin/index.asp")。同页题这玩意儿在本地测试没问题,面登一旦部署到虚拟目录或者二级域名下,录后路径直接断掉。转问用户从/shop/login.asp登录,同页题跳转却指向/admin/index.asp——如果网站装在根目录还好,面登装在/shop/下面,录后那跳转地址就变成/shop/admin/index.asp,而真实后台在/admin/,结果自然是404。我见过一个项目上线两周,每天有十几个用户反馈登录后白屏,最后发现就是这个问题。 那怎么办?别写死。用相对路径或者动态拼。比如Response.Redirect("index.asp"),这样浏览器会基于当前目录去解析。但更稳妥的做法是,登录成功后用Session记录用户来源,再根据来源决定跳哪。代码大概长这样: If Session("ReturnUrl") <> "" Then Response.Redirect(Session("ReturnUrl")) Else Response.Redirect("default.asp") End If 这招能解决大部分问题,但有个隐藏bug——如果用户在登录页停留太久,Session过期,ReturnUrl丢了,照样跳回首页。所以得在登录页加载时就把ReturnUrl存到隐藏字段里,而不是Session。 再说另一个真实场景:用户从产品详情页点“立即购买”被拦到登录页,登录完你得让他回到刚才那个产品页,最好还能带着之前的查询参数。这时候光存个路径不够,得把整个URL都存下来。我习惯用Request.ServerVariables("HTTP_REFERER"),但注意这玩意儿不一定可靠——有些浏览器或防火墙会过滤它,用户直接输网址登录的话,Referer是空的。所以还得加个兜底判断: If Request.ServerVariables("HTTP_REFERER") <> "" Then Session("ReturnUrl") = Request.ServerVariables("HTTP_REFERER") Else Session("ReturnUrl") = "default.asp" End If 但别高兴太早,这里有个安全坑。如果Referer带着外部链接,比如用户从百度广告点进来,登录完你把他Redirect回百度,那不等于白登录了吗?我处理过一单,客户说“用户登录后老跳到别的网站”,查了半天才发现是Referer没做域名校验。正确做法是只允许跳回自己站内的地址: Dim referer, host referer = Request.ServerVariables("HTTP_REFERER") host = Request.ServerVariables("HTTP_HOST") If InStr(referer, host) > 0 Then Session("ReturnUrl") = referer Else Session("ReturnUrl") = "default.asp" End If 最后一种情况最隐蔽——AJAX登录。现在很多ASP站点用jQuery异步提交登录,成功后用JS跳转。这时候服务端Response.Redirect根本不起作用,因为这是XMLHttpRequest请求,浏览器不会跟着重定向。你得让服务端返回一个JSON,告诉前端该去哪: Response.ContentType = "application/json" Response.Write "{ ""url"":""" & Session("ReturnUrl") & """}" 前端拿到url后,用window.location.replace(url)跳转。注意别用location.href,因为replace不会在历史记录里留下登录页,用户按后退键不会又回到登录页,体验好很多。 说起来,有一次我调试一个老系统,用户登录后永远跳转到登录页本身,死循环。最后发现是ReturnUrl被存在Application变量里——所有用户共享。A用户登录后,B用户再登录,直接跳到了A用户想去的页面。这属于低级错误,但确实能发生。所以记住:跟用户相关的跳转信息,永远放Session或Cookie,别放Application。 说到底,跳转问题就是三个核心:路径别写死、来源要校验、异步要特殊处理。把这三点记住了,基本能避开90%的坑。剩下那10%,可能就是你遇到了一个把Response.Write写在Redirect前面的同事——那代码直接报错,反而好排查。 |