利用脚本文件引用解决跨域数据传递问题

3 篇文章 0 订阅

今天遇到了一个问题. 公司有两个产品需要整合, 需要实现一个SSO... 后台做完了, 到前台这里发现了个巨大的问题:

因为这两套系统是在两个域名, 系统A在完成验证后, 用户在A系统页面关闭前, 超时范围内打开B系统都不需要再次登录.

但是, B系统凭什么认为一个新发起的请求(HttpRequest)是已经验证过身份的呢? 众所周知, Cookie不能跨域. 两系统共用Cookie的方式难度较大.安全性也有问题.

头疼, 开论坛. 手贱一般的点击了 "查看网页源代码"... 这个网页的源码中有一句话让我眼前一亮:

<script language="javacript" src="http://ad.baidu.com/......."></script>...

对阿, 对script脚本的引用是可以跨域的啊!! 恩, 好办法. 写个测试试一下. 下图为设计思路:

大体思路为: 首先在B系统的那个需要A系统数据的那个页面, 添加一个脚本引用. 注意, 这里的脚本引用不指向一个真实的JS文件, 而是指向A系统的一个WebHandler或者ASHX.

这样在打开B系统的页面时, 就会调用A系统的那个WebHandler(或ASHX), 而这个WebHandler(或ASHX)因为属于A系统, 所以可以调用A系统中当前请求的Session或者Cookie.

然后以脚本输出的方式输出成几个带有来自A系统数据的Javascript字段. 然后B系统的页面就可以通过脚本访问到字段的值. 也就是说这个WebHandler(ASHX)就充当了桥梁.

至于之后是直接显示在页面上啊还是提交到服务器就是后话了..

不明白啊? 举个例子: B公司需要A公司提供一些文本资料, 可是B公司的员工无权直接去A公司拿取资料, 因为A公司的人不认识他. 那么有一个办法, 就是B公司请求A公司派一个 "大使" 将资料送来.

那么这个 "大使" 既可以从A公司拿取资料, 因为他本身就是A公司的人, 也可以将资料交付给B公司. 因为身在B公司的办公室.

好, 首先建立两个Web工程, 分别部署在两个域名下(不过我这儿只有localhost, 就用两个端口分开). 一个是信息提供方, 一个是数据接受方. 这个是信息提供方的主页面.

因为是测试, 所以页面什么都没有. 我们在默认页中在Cookie中添加一些东西... (Session也行. 如果想要做A系统成功登陆关闭页面后超时前B系统自动登陆的话, 就用cookie)

            public partial class _Default : System.Web.UI.Page 
            {
                protected void Page_Load(object sender, EventArgs e)
                {
                    Random r=new Random(10000);
                    Int32 i = r.Next();
                    i += (((DateTime.Now.Year + DateTime.Now.Month + DateTime.Now.Day + DateTime.Now.Hour + DateTime.Now.Minute + DateTime.Now.Second + DateTime.Now.Millisecond) / 2) * i);
                    //这里只是为了提高随机性..

                    HttpCookie c= new HttpCookie("TEA", i.ToString());
                    c.Expires = DateTime.Now + TimeSpan.FromMinutes(50);
                    //必须设置超时时间, 否则还没等你开第二个浏览器窗口的时候Cookie就已经过期了!

                    Response.SetCookie(c);


                    Response.Write(i);
                    //测试结果应该是B系统的Default.aspx也显示这个.
                }
            }
        

下面这个就是用于处理从B系统页面发出的“伪JS”请求的HttpHandler了.
            public class JSRequetHandler:IHttpHandler /*,IRequiresSessionState (HttpHandler如果要用Session的话必须继承这个)*/
            {
                #region IHttpHandler 成员

                public bool IsReusable
                {
                    get { return true; }
                }

                public void ProcessRequest(HttpContext context)
                {
                    if (context.Request.Cookies["TEA"] == null)
                    {
                        context.Response.Write("var login_status = 0"); //可能是Session丢失或者非法请求.
                    }
                    else
                    {
                        context.Response.Write("var login_status = '" + context.Request.Cookies["TEA"].Value + "';");
                        //将上面存入Cookie中的 "TEA" 的值输出为 JS字段 "login_status" 的值. 这样B系统的页面脚本就能拿到值了.
                    }
                }

                #endregion
            }
    

因为我这里用的是HttpHandler, 所以配置文件中还得写点东西. 如果是ASHX的话就不用写了.
        <?xml version="1.0" encoding="utf-8"?>
        <configuration>
        <!--.....-->
        <system.web>
            <!--.....-->
            <httpHandlers>
                <add verb="*" path="A.cj" validate="false" type="Handler.JSRequetHandler, Handler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
                <!--所有访问A.cj(忽略路径)的请求都会由 "JSRequetHandler" 处理.-->
                <!--.....-->
            </httpHandlers>
        </system.webServer>
        </configuration>
    

调用页
        <%@ Page Language="C#" AutoEventWireup="true"  %>

        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

        <html xmlns="http://www.w3.org/1999/xhtml">
        <head runat="server">
            <title>B</title>
            <script language="javascript" type="text/javascript" src="http://201.86.189.40:5678/TestWebSite01/A.cj"></script>
            <script  runat="server">
                public void OnButtonServerClick(Object sender, EventArgs arg)
                {
                    String fromA = mk.Value;
                    //A系统的数经过千辛万苦终于抵达B系统的后台.
                }
            </script>
        </head>
        <body>
          <br />
          <br />
          <br />
          <br />
          <center style="font-size:60pt; font-family:黑体;" id="t"></center>
          <br />
          <br />
          
          <form id="f" runat="server" style="text-align:center;">
            <input type="hidden" id="mk" runat="server" />  
            <button id="btn" runat="server" onserverclick="OnButtonServerClick">提交到服务器</button>
          </form>

          <script language="javascript" type="text/javascript">

           var _t = document.getElementById("t");

           if(typeof(login_status) != 'undefined')
           {
             //A系统由JSRequestHandler输出的脚本已经完成输出, 数据已经保存在字段里了.
              _t.innerHTML = login_status;
              document.getElementById("mk").value = login_status;
              
           }
           else
           {
              _t.innerHTML="-";
               //如果未定义, 那么表明A系统并未提供数据.
           }
        </script>

        </body>
        </html>

    
测试结果: 先打开A系统(就是从上数第一个Default页所在的那个Web工程) 启动后页面会输出一串数字, 然后启动B系统(调用页所在的Web工程), 所看到的数字是一致的. 测试成功.

Ps:据说W3C已经出了CrossDomain的规范了? 不过无论怎样, IE6还是不支持这个规范的... 毕竟中国还有好多人还在用IE6...
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值