关于跨域

近期接到一个需要不同部门之间的web页面合作的项目,中间的接入方案涉及到跨域的方面,特记录如下:

我们部门,暂称A部门,域名www.domain1.com;兄弟部门,暂称B部门,域名www.domain2.com。

需求背景:A部门需要开发一个在线办公的独立web应用,但是没有在线编辑word,excel等office文件的相关工具,正好B部门开发了相关的在线编辑、导入、导出office文件的独立web应用,所以A部门需要B部门协助开发针对A部门的在线编辑工具

第一套方案:A部门负责前端编辑器代码+自己的独立web应用,B部门负责后端的解析存储服务+自己的独立web应用。

涉及到的跨域部分:A部门的前端---B部门的后端,即ajax跨域


第二套方案:A部门使用iframe套用B部门的独立web应用,各自负责自己独立的web应用

涉及到的跨域部分:A部门的前端--B部门的前端,js之间的跨域


OK,背景描述完了,现在看看,什么是跨域。跨域的产生是由于浏览器的同源策略导致的,那么什么是同源策略:

同源即相同协议,相同的域名【主域名与子域名不是相同的域名】,相同的端口。那么同源策略就是针对同源的客户端脚本在访问上存在限制,客户端脚本一般指javascript,至于vbscript什么的用的少,也就不说了,存在限制是指这个同源策略是W3C提出的,为的是保证不同源之前的安全性,但是不用的浏览器在实现上存在不同,这个可以针对下面讲到的几个方式具体用到了具体分析


那么同源策略都涉及到哪些具体影响呢?


1、ajax请求的URL必须与当前页面同源

2、不同源的页面之间的互相访问会受到限制,说白了,类似frame的结构,frame之间只提供有限的访问,具体有限到什么程度,可以看一下面这个url地址:

https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy

这是火狐官方对于同源的说明,算是比较通用的,具体来说呢就是,如果两个不同源的页面想要交互,只能通过window和window.location对象进行交互,其他方法要不就是访问,要不就是只提供只读访问

以上两个影响分别针对我们上面提到的两个实现方案,先说说第一个方案的ajax跨域3种实现方式:

1、CORS【跨域资源共享】,就是指在B部门的后端声明,如果是来自A部门的ajax请求,就通过。具体参数是:

Access-Control-Allow-Origin

1.1、可以在ngnix当中的response增加头部信息:addheader access-control-allow-origin:http://www.domain1.com,这样domain2.com就能为domain1提供后端服务支持。

优点:易处理,缺点:所有ngnix返回页面都会增加这种头,适合大量ajax跨域请求的情况。

1.2、还是这个参数,但是可以在具体页面的使用header,手动增加开关,下面是php的方式:

header('Access-Control-Allow-Origin:http://www.domain1.com');

优点:不会影响其他页面,比较独立,缺点:需要一个一个手动添加,适合少量ajax跨域请求的情况


具体实现:

www.domain1.com

<script>
    $(function(){

        var post_data = new Object();
        post_data.name = "test-cors";

        $.ajax({
            url: 'http://www.domain2.com/cors/',
            //type:'POST',
            type:'GET',
            dataType:'json',
            data:post_data,
            success:function(response){
               alert(response);
            }
        });
    });
</script>

www.domain2.com

header('Access-Control-Allow-Origin:http://www.domain1.com');
echo json_encode($_REQUEST['name']);

或者设置ngnix:

location / {
 add_header Access-Control-Allow-Origin http://www.domain1.com
}

2、JSONP

JSONP的原理是什么,原理是由于在同源策略当中设定了页面的dom结构当中有部分语法是不受跨域影响的,同样是摘自火狐官方的一段话:

Here are some examples of resources which may be embedded cross-origin:

  • JavaScript with <script src="..."></script>. Error messages for syntax errors are only available for same-origin scripts.
  • CSS with <link rel="stylesheet" href="...">. Due to the relaxed syntax rules of CSS, cross-origin CSS requires a correct Content-Typeheader. Restrictions vary by browser: IEFirefoxChromeSafari (scroll down to CVE-2010-0051) and Opera.
  • Images with <img>. Supported image formats include PNG, JPEG, GIF, BMP, SVG, ...
  • Media files with <video> and <audio>.
  • Plug-ins with <object><embed> and <applet>.
  • Fonts with @font-face. Some browsers allow cross-origin fonts, others require same-origin fonts.
  • Anything with <frame> and <iframe>. A site can use the X-Frame-Options header to prevent this form of cross-origin interaction
JSONP其实就是利用到了这点,即script标签,如果我的前端页面是引用了一个前端页面,然后这个前端页面其实是后端页面生成的JS代码块呢?那么我的前端页面就可以使用了这段代码块了

www.domain1.com
<script>
    function show(name){
        alert(name);
    }
</script>
<script src="http://www.domain2.com/jsonp/index.php?callback=show"></script>

www.domain2.com
header('Content-Type: text/javascript');
$callback = $_GET['callback'];

$name = 'test-jonp';
echo $callback."('$name')";

这样www.domain2.com实际返回的是一段儿javascript代码块:show('test-jonp')
返回到www.domain1.com,由于show方法已经声明过了,所以就会成功的调用show方法完成跨域


3、其他




火狐:https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy

Cross-origin script API access

JavaScript APIs such as iframe.contentWindowwindow.parentwindow.open and window.opener allow documents to directly reference each other. When the two documents do not have the same origin, these references provide very limited access to Window and Location objects, as described in the next two sections.

To communicate further between documents from different origins, use window.postMessage.

Window

Specification:  http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#security-window.

The following cross-origin access to Window properties is allowed:

Methods
window.blur
window.close
window.focus
window.postMessage
Attributes  
window.closed Read only.
window.frames Read only.
window.length Read only.
window.location Read/write.
window.opener Read only.
window.parent Read only.
window.self Read only.
window.top Read only.
window.window Read only.

Some browsers allow access to more properties than the specification allows.

Location

Specification:  http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#security-location.

The following cross-origin access to Location properties is allowed:

Methods
location.replace
Attributes  
URLUtils.href Write only.
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

Browser compatibility

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support 1.0 6.0 (6.0)[1]
8.0 (8.0)[2]
8.0[3]
10.0[4]
9.5 4.0
transferargument ? 20.0 (20.0) Not supported ? ?


在 Webkit 的 Document.idl 源码中对 domain 有这样的定义:

#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
    [TreatNullAs=NullString, SetterRaisesException] attribute DOMString domain;
#else
    readonly attribute DOMString domain;
#endif

这也说明了 domain 设置为“writable” 仅用于页面脚本:即允许主子域脚本进行通信,但不涉及 localStorage 、indexedDB 和 XMLHttpRequest 的共享。目前市场上主流浏览器都支持 domain可写,可以满足几乎所有主子域脚本通信需求,但在特殊情况下也有些许不同

http://yanni4night.com/blog/setting-document-domain.html


location.hash 是什么:
hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从  # 号开始的部分)
location.hash原理:
1、动态改变location.hash,iframe不会重载
2、无论跨域与否,iframe内可以获取自己的location.hash

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


window.name
window.name 是什么:
name 在浏览器环境中是一个全局window对象的属性
当在 iframe 中加载新页面时,name 的属性值依旧保持不变
name 属性仅对相同域名的 iframe 可访问
window.name 的优势:
数据量更大(2M)
更安全
可传递多种数据格式
window.name 的劣势:
只适用于隐藏iframe的情形


window.name 传输技术,原本是 Thomas Frank 用于解决 cookie 的一些劣势(每个域名 4 x 20 Kb 的限制、数据只能是字符串、设置和获取 cookie 语法的复杂等等)而发明的(详细见原文:《Session variables without cookies》),后来 Kris Zyp 在此方法的基础上强化了 window.name 传输 ,并引入到了 Dojo dojox.io.windowName),用来解决跨域数据传输问题。

window.name 的美妙之处:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

http://www.planabc.net/2008/09/01/window_name_transport/


https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/The_structured_clone_algorithm

Supported types

Object type Notes
All primitive typesHowever not symbols
Boolean object 
String object 
Date 
RegExpThe lastIndex field is not preserved.
Blob 
File 
FileList 
ArrayBuffer 
ArrayBufferViewThis basically means all typed arrays like Int32Array etc.
ImageData 
Array 
ObjectThis just includes plain objects (e.g. from object literals)
Map 
Set 

<think>嗯,用户想了解身份认证的方法,结合之前的对话历史和系统指令,需要系统整理相关信息。用户引用了多个资料片段,重点提到了Session-Cookie的局限性和JWT的优势,特别是场景下的适用性。从技术角度看,认证的核心痛点是浏览器同源策略对Cookie的限制。Session-Cookie方案在时需要额外配置CORS和withCredentials属性,安全性也容易受CSRF攻击影响。而JWT的无状态特性天然适合Token可以放在请求头里自由传递,但要注意Token存储安全性和过期机制。用户可能是前端开发者或全栈工程师,正在设计系统认证方案。ta提到的单点登录需求值得重点关注,需要解释JWT如何配合OAuth2实现多系统间的信任传递。引用[3]中提到的统一身份认证场景很典型,应该用SSO方案展开说明。回复结构上先分Session和JWT两类方法,再补充单点登录场景。重点对比两者的实现差异,比如JWT如何解决Cookie问题,以及服务端如何验证Token签名。引用资料时要把参考标记自然地融入说明文字里,比如提到Express框架的使用就可以关联引用[1][4]。用户可能还有隐含需求,比如想了解具体代码实现或性能考量。可以准备回答Session共享方案(Redis集群)、CORS配置细节、JWT加解密开销等问题。</think> 身份认证的常用方法及适用场景如下: --- ### 一、Session-Cookie 方案(需配置) 1. **基本原理** - 服务端存储用户Session,通过Set-Cookie返回Session ID给前端 - 浏览器后续请求**自动携带Cookie**(需开启`withCredentials`) 2. **问题解决** ```java // Spring Boot示例(引用[2]) @CrossOrigin(origins = "https://client-domain.com", allowCredentials = "true") ``` - **必要条件**: - 前端:`axios.defaults.withCredentials = true` - 后端:`Access-Control-Allow-Credentials: true` - 名白名单:`Access-Control-Allow-Origin: https://client-domain.com` 3. **缺点**: - 需服务端维护Session存储 - 配置复杂(引用[1][4]) - CSRF攻击风险 --- ### 二、JWT(JSON Web Token)方案(推荐使用) 1. **核心机制**(引用[1][4]): ```mermaid graph LR A[用户登录] --> B[服务端生成JWT] B --> C[返回Token给前端] C --> D[前端存储Token] D --> E[请求时携带Authorization头] ``` 2. **优势**: - 无状态:服务端不存储会话 - 天然支持:通过HTTP Header传递 - 典型Token格式:`Bearer eyJhbGci...` 3. **Express实现示例**(引用[1]): ```javascript // 生成Token const token = jwt.sign({userId: 123}, 'secretKey', {expiresIn: '2h'}); // 验证中间件 const auth = (req, res, next) => { const token = req.header('Authorization')?.replace('Bearer ', ''); jwt.verify(token, 'secretKey', (err, decoded) => { if(err) return res.status(401).send(); req.user = decoded; next(); }); } ``` --- ### 三、单点登录(SSO)方案(引用[3]) 1. **系统认证流程**: ``` 用户访问A系统 → 重定向至认证中心 → 登录后携带Token返回A系统 → 访问B系统时认证中心自动授权 ``` 2. **关键技术**: - 中央认证服务器 - Token共享(如JWT) - Cookie + OAuth2.0协议 --- ### 四、方案对比表 | **方案** | 复杂度 | 安全性 | 适用场景 | |----------------|------------|------------|------------------------| | Session-Cookie | 高⭐ | 易受CSRF | 同主下的子系统 | | JWT | 低✅ | 需防XSS | API/微服务架构 | | SSO | 中⚠️ | 最高🔒 | 企业级多系统统一认证 | --- **总结建议**: 1. 纯前端调用API → **优先JWT方案**(引用[4]) 2. 企业内部系统整合 → **SSO + JWT组合** 3. 传统Web应用(同) → Session方案更简单 > 附:前端存储Token的安全方式 > ```javascript > // 避免LocalStorage(防XSS),使用HttpOnly Cookie > document.cookie = `token=${token}; Secure; SameSite=None; HttpOnly`; > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值