FrankKai / FrankKai.github.io

FE blog
https://frankkai.github.io/
363 stars 39 forks source link

如何理解same-origin policy? #144

Open FrankKai opened 5 years ago

FrankKai commented 5 years ago

主要参考文档:https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Original_Document_Information

FrankKai commented 5 years ago

same-origin policy是一个严格的安全策略,它可以用来限制document或者script如何从一个origin加载,然后与另一个origin的资源进行交互。隔离了潜在危险的恶意documents,减少网站被攻击的次数。

origin的定义

如果两个URL协议相同、端口相同、主机也相同,那么它们是same origin。我们看到的一般是一下两种形式:

注释:tuple是一组数据的集合,可以是表单,也可以是2个,3个,4个参数等等。

http://store.company.com/dir/page.html为例:

URL Outcome Reason
http://store.company.com/dir2/other.html Same origin Only the path differs
http://store.company.com/dir/inner/another.html Same origin Only the path differs
https://store.company.com/page.html Failure Different protocol
http://store.company.com:81/dir/page.html Failure Different port (http:// is port 80 by default)
http://news.company.com/dir/page.html Failure Different host

最后http://news.company.com/dir/page.html的不一定,如果在hosts文件中进行映射,例如下面这样,那么它们也是同源: /etc/hosts

192.168.0.23 news.company.com store.company.com:

因为此时它们的host是相同的。

继承origins

源的更改

一般来说,更多的是调用其getter。

const forbiddenDomain = "996.icu";
if(document.domain === forbiddenDomain){
    // Scripts may close only the windows that were opened by it.
    // 仅仅可以关闭由当前window打开的窗口.
    window.close();
}

调用setter,可以将端口更改为null,可以进行端口不同跨域通信。

document.domain = document.domain;
FrankKai commented 5 years ago

跨域网络权限

同源策略主要控制着2个不同源的交互,例如当你使用XMLHttpRequest或者<img>标签。这个交互一般分为3类:

这里有一些跨域的一些资源类型:

拓展: 1.X-Frame-Options是什么? 是一个响应头,用来控制浏览器是否渲染<frame><iframe><embed><object>。可以用来避免clickjacking攻击。

X-Frame-Options: deny
X-Frame-Options: sameorigin
X-Frame-Options: allow-from https://example.com/

nginx配置:add_header X-Frame-Options sameorigin always; 2.什么是clickjacking 攻击? 中文名叫做点击劫持。

Clickjacking(通常被称为用户界面补救攻击),这是一个恶意技术,因为它会触发用户本不会去进行的一些点击,所以会潜在泄露保密信息的危险或者是会被恶意操控计算机。

在Web浏览器中,clickjacking是一个浏览器安全问题,这是很多浏览器和平台都存在的漏洞。Clickjacking可以在浏览器意外的应用程序中发生。

Clickjack采用嵌入式代码或脚本的形式,可以在用户不知情的情况下执行,例如单击看似执行其他功能的按钮。

那么如何避免Clickjacking呢? 凭借我有限的2年前端开发经验,可以通过事件对象events的isTrusted属性进行安全控制。可以查看:一些想不到的前端安全知识点

如何开启跨域权限

CORS,关于CORS,需要前后端的通力协作。

前端配置CORS

axios配置项

withCredentials: true
nodejs koa2 配置CORS

引用依赖koa-cors

var cors = require('koa-cors');
app.use(cors());
java spring-boot 配置CORS
package com.arya.spring.vue.aryaspringvuebe;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@SpringBootApplication
public class AryaSpringVueBeApplication {

    public static void main(String[] args) {
        SpringApplication.run(AryaSpringVueBeApplication.class, args);
    }
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                // 映射项目路由,允许/spring/vue下的所有接口跨域。注意**才是代表所有路由,否则*仅仅是类似/spring/vue/update一级路由,不支持/spring/vue/update?id=1。
                registry.addMapping("/spring/vue/**")
                        // 设置Access-Control-Allow-Method: "GET", "POST", "PUT", "DELETE"
                        .allowedMethods("GET", "POST", "PUT", "DELETE")
                        // 设置Access-Control-Allow-Origin:http://localhost:3000,指定可访问源。注意PUT和DELETE引起的OPTIONS预检请求需要指定源,不可设置为*。
                        .allowedOrigins("http://localhost:3000")
                        // 设置Access-Control-Allow-Headers: content-type。
                        .allowedHeaders("Content-Type")
                        // 设置Access-Control-Max-Age: 3600。注意这里是Long类型的
                        .maxAge(3600L)
                        // 设置响应Access-Control-Allow-Credentials: true。
                        .allowCredentials(true);
            }
        };
    }
}

如何阻止跨域权限

FrankKai commented 5 years ago

跨域脚本API权限

iframe.contentWindow, window.parent, window.open, and window.opener这些API,允许文档直接互相调用。 当两个文档不在同源的情况下,会对window和location的API进行一些限制,就像下面两个部分描述的一样。

为了在不同的document间进行通信,需要用到window.postMessage。可以参考:什么是Web Workers?

Window

下面的这些方法是允许 cross-origin 的。

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.

Location

方法location.replace 属性URLUtils.href 只写

FrankKai commented 5 years ago

跨域数据存储权限

localStorage和IndexedDB也会有源的区分。每个源都有自己独立的storage,而且一个源下的js,不能读写另一个origin下的数据。