您的位置:首页 > 运维架构 > 网站架构

架构整合

2014-04-15 13:47 405 查看
架构整合说明

1 文档描述

1.1 编写目的

在实际的项目应用中,总会遇上需要整合多个项目的情况。而这些项目可能使用的技术并不相同,语言不同,部署环境不同(即在不同的域中)。这时,就需要解决诸多问题,比如单点登录(SSO)、Session跨域、JS跨域等。如果要整合异构项目,就需要解决上述问题。本文正是为了解决此类问题。

1.2 术语定义

序号

术语

解释

1

SSO

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
2

P3P

P3P: Platform for Privacy Preferences(隐私偏好平台)
隐私偏好平台(P3P)是允许网络站点来宣告它们收集的关于浏览用户他们的意向使用的信息的一个协议。原意是当用户浏览时,授予用户他们个人信息的更多控制,P3P由世界环球网协会(W3C)发展和正式在2002年4月16号被推荐。

1.3 参考资料

序号

文档名

版本

1

2

2 问题

对于异构项目整合。比如A项目中嵌入B项目。主要需要解决如下问题:
l 统一登录
主从框架:异构(多语言)
能够从A项目中访问B项目,就需要统一登录认证,如果不同库,不同语言的话,就需要提供登录需要的信息,身份认证信息,及签名信息。
l 跨域
场景:A网站提供一个页面供其它网站进行Iframe调用,该页面使用了SESSION,并进行了SESSION判断。现象:B网站IFRAME了A网站的页面,总显示SESSION过期,但直接在浏览器中打开该页面却又是正常的。这是由于浏览器的安全性所致,SESSION依赖于COOKIE,A与B是二个完全不同的域,A网站没法去读取B网站下的COOKIE,所以 SESSION也就失效了。解决办法:A网站的页面在输出头上附加一个P3P属性,值为CP=CAO
PSA OUR即可。如:Response.AddHeader("P3P", "CP=CAO PSA OUR");
跨域有分为以下情况:
1.
完全相同
eg:www.jala.com/A www.jala.com/B
2.
主域相同
eg:www.A.jala.com www.B.jala.com
3.
主域不相同

3 解决方案

3.1 统一登录

解决统一登录的方案比较多,比如SSO。本文采用主URL签名方式,即url?userid=100&sign=xxxxxxxxxxx&username=heshuang
从filter验证信息,放入session中。

3.2 Session跨域

session跨域主要会导致session丢失,session过期。其实要实现session跨域,取决于cookies能不能跨域访问。

3.2.1 域名相同

对于域名相同,不会产生问题

3.2.2 主域相同,子域不同

3.2.1 主域不同

对于主域不同,则需要使用P3P协议,通过Filter追加
response.setHeader("P3P", "CP=CAO PSA OUR");

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

HttpServletResponse res = (HttpServletResponse) response;

// iframe引起的内部cookie丢失

res.setHeader("P3P", "CP=CAO PSA OUR");

if (chain != null)

chain.doFilter(request, response);

}
注:如何测试跨域访问
C:\Windows\System32\drivers\etc \hosts
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
# 127.0.0.1 rockey1.com # A server
# 127.0.0.1 rockey2.com #B server
http://rockey1.com:8080/ http://rockey2.com:8080/

3.3 JS跨域

3.3.1 域名相同

对于域名相同,不会产生问题

3.3.2 主域相同,子域不同

可以采用如下方式解决。document.domain+iframe的设置
对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!代码如下:

www.a.com上的a.html
document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.document;
//在这里操纵b.html
alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};
script.a.com上的b.html
document.domain = 'a.com';
这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。

问题:

1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。

2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

3.3.3 主域不同

对于主域不同,解决方法:

1.
location.hash

Ø location.hash 是什么:

hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)
一个完整的URL地址为:协议://主机:端口/路径名称#hash标识?搜索条件

如果页面中含有锚点连接,可以使用hash标志指定页面中的锚点标志,该标志以“#”开头;搜索条件是指URL中所含有的查询条件,该查询条件以“?”开头,以“变量名称=值”的形式出现,多个查询条件之间使用连接符“&”连接。比如:http://upc.edu.cn:8080/wwwroot/ index.html#topicID?id=3876。
1.hash属性
【功能说明】设置或获取URL中的锚点名称,如果Web页面中使用的锚点连接,通过设置location对象的hash属性可以方便的跳转到页面中的不同部分。
【基本语法】location.hash
下面的代码演示了如何在网页中使用location对象的hash标志快速定位页面中的 内容。
【实例演示】
<script>
function getAnchor(str)
{
window.location.hash=str;
}
</script>
<body>
//创建锚点链接,快速定位网页内容
<a href="javascript:getAnchor('jueju');">杜甫绝句</a>
<a href="javascript:getAnchor('yijianmei');">李清照一剪梅</a>
<a href="javascript:getAnchor('hanghelou');">崔颢黄鹤楼</a>
//下面定义了3个锚点
<a name="jueju"><center>绝句</center>
<!--古诗内容省略,见源代码-->
</a><br><br><br><br><br>
<a name="yijianmei"><center>一剪梅</center>
<!--古诗内容省略,见源代码-->
</a><br><br><br><br><br>
<a name="hanghelou"><center>黄鹤楼</center>
<!--古诗内容省略,见源代码-->
</a>
</body>
这段代码在一个网页文件中创建了3个锚点链接,单击其中任一个链接,程序就会调用getAnchor函数来设置location对象的hash属性为相应的值,以使页面滚动到指定的内容上。运行这段代码,将窗口缩小并单击链接“崔颢 黄鹤楼”则可以看到图16.18所示的效果。
Ø 如何解决跨域问题
页面域关系
主页面a.html所属域为www.taobao.com,被iframe的页面为b.html所属域www.baidu.com/b.html
实现效果
A域名下的页面a.html中通过iframe嵌入B域名下的页面b.html,由于b.html的宽度和高度是不可预知而且会变化的,所以需要a.html中的iframe自适应大小.
问题本质
js对跨域iframe访问问题,因为要控制a.html中iframe的高度和宽度就必须首先读取得到b.html的大小,A、B不属于同一个域,浏览器为了安全性考虑,使js跨域访问受限,读取不到b.html的高度和宽度.
解决方案:
引入代理代理页面proxy.html与a.html所属相同域A,proxy.html是A域下提供好的中间代理页面,假设proxy.html的地址:www.baidu.com/proxy.html,它负责读取location.hash里面的width和height的值,然后设置与它同域下的a.html中的iframe的宽度和高度.
a.html代码
首先a.html中通过iframe引入了b.html

<iframe id=”b_iframe” height=”0″ width=”0″ src=”http://www.baidu.com/b.html” frameborder=”no” border=”0px” marginwidth=”0″ marginheight=”0″ scrolling=”no” allowtransparency=”yes” ></iframe>
b.html代码
<script type=”text/javascript”>

var b_width = Math.max(document.documentElement.clientWidth,document.body.clientWidth);

var b_height = Math.max(document.documentElement.clientHeight,document.body.clientHeight);

var c_iframe = document.getElementById(”c_iframe”);

c_iframe.src = c_iframe.src+”#”+b_width+”|”+b_height; //http://www.taobao.com/c.html#width|height”

}

</script>

<!–js读取b.html的宽和高,把读取到的宽和高设置到和a.html在同一个域的中间代理页面车c.html的src的hash里面–>

<iframe id=”c_iframe” height=”0″ width=”0″ src=”http://www.taobao.com/c.html” style=”display:none” ></iframe>
proxy.html代码
<script type=”text/javascript”>

var b_iframe = parent.parent.document.getElementById(”b_iframe”);

var hash_url = window.location.hash;

var hash_width = hash_url.split(”#”)[1].split(”|”)[0]+”px”;

var hash_height = hash_url.split(”#”)[1].split(”|”)[1]+”px”;

b_iframe.style.width = hash_width;

b_iframe.style.height = hash_height;

</script>

a.html中的iframe就可以自适应为b.html的宽和高了.

location.hash原理:

1、动态改变location.hash,iframe不会重载

2、无论跨域与否,iframe内可以获取自己的location.hash

3、只要域名相同就能通信,即使ABC三层嵌套

location.hash通用解决办法:

被嵌入的跨域的iframe中引入

<script src="/js/crossdomain/crossdomain.js"></script>

location.hash缺点

1、传递数据量有限

2、不太安全

2.
window.name

window.name:name 在浏览器环境中是一个全局/window对象的属性,且当在 frame 中加载新页面时,name 的属性值依旧保持不变。通过在 iframe 中加载一个资源,该目标页面将设置 frame 的 name 属性。此 name 属性值可被获取到,以访问 Web 服务发送的信息

参考demo
总的解决跨域的方案:
1. 即时插入 script元素的方式,会让脚本立即执行,不安全,并且需要与跨域的远端做好约定——比如变量名。细节较为繁琐。
2. 写 iframe的
location.hash的方式,会导致历史记录的产生,且数据量有限,同时,因为 URL的内容可视,既不好看也容易泄露信息。
3. 用代理?虽然算是最“正宗”的完整跨域方案,但太麻烦了点——首先得有代理,如果量大的话,代理的负担会很重,会导致“瓶颈”制约。
4. 利用 Flash跨域,不在考虑之列——复杂了些,并且那不算是
JS跨域。

4 附:

4.1 Session共享

session共享主要存在于负载均衡多个APP间的session数据共享。
主要有如下问题:
Ø session粘滞
Ø session共享
Ø 负载均衡(高压力|高可用)

4.2 什么是跨域

JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:

首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:

URL
说明
是否允许通信
http://www.a.com/a.js http://www.a.com/b.js
同一域名下

允许

http://www.a.com/lab/a.js http://www.a.com/script/b.js
同一域名下不同文件夹

允许

http://www.a.com:8000/a.js http://www.a.com/b.js
同一域名,不同端口

不允许

http://www.a.com/a.js https://www.a.com/b.js
同一域名,不同协议

不允许

http://www.a.com/a.js http://70.32.92.74/b.js
域名和域名对应ip

不允许

http://www.a.com/a.js http://script.a.com/b.js
主域相同,子域不同

不允许

http://www.a.com/a.js http://a.com/b.js
同一域名,不同二级域名(同上)

不允许(cookie这种情况下也不允许访问)

http://www.cnblogs.com/a.js http://www.a.com/b.js
不同域名

不允许

特别注意两点:

第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,

第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。

“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: