同源策略的解决方案
Posted surpass123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了同源策略的解决方案相关的知识,希望对你有一定的参考价值。
同源策略的解决方案
1.什么是XSS
攻击,什么是CSRF
,什么是CORS
# 什么是XSS攻击
跨站脚本攻击分为两种方式:反射型攻击(比如,一些含有恶意脚本的URL),持久型攻击(将恶意脚本提交到被攻击网站的数据库中)
# 什么是CSRF攻击
跨站请求伪造攻击:顾明思义,是攻击者通过跨站请求,以被攻击者的合法身份进行非法的操作。比如获取被攻击者的token信息进行一些转账操作。
# 什么是CORS
跨域资源共享(CORS),需要浏览器和服务器的同时支持,目前所有的浏览器都支持该功能,IE浏览器不得低于IE10。
整个CORS的通信过程,都是浏览器自动完成的,不需要用户的参与。对于开发者来说,CORS通信和AJAX通信没有什么区别,浏览器一但发现了AJAX请求跨越,会自动添加一些附加的头信息,有时候还会多出一次的附加请求。
因此实现CORS通信的关键是在服务器。
说到跨域问题,就得提一下同源策略了
2.什么是同源策略
所谓`同源策略`,是由NetSPace提出的一个著名的安全策略。同源就是指协议、域名、端口号相同,浏览器处于安全方面的考虑,只允许本域名下的接口相互交互,不同源的客户端脚本在没有明确的授权情况下,不能读写对方的资源。
假设有这么一个情况:A网站是一家银行,用户登录后又去浏览了一些其他网站(如,网站B),网站B如果可以从A网站中获用户登录时的Cookies信息,那么B网站的管理员是不是可以为所欲为了?
3.CORS
的实现流程
浏览器将CORS请求分为两类请求:简单请求(simple request)和非简单请求(not-so-simple request)
浏览器发出的CORS简单请求,只需要在头信息中增加一个Origin字段。
浏览器发出的CORS非简单请求,需要在正式通信之前,增加一次HTTP查询请求,称为“预检”请求(preflight)。浏览器先询问服务器,当前网页的域名是否在服务器许可的名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到了肯定的回复,浏览器才会正式发出XMLHttpRquest请求,否则就报错
4.CORS
两种请求详解
只要同时满足两个请求,就是简单请求
# 请求方法是以下的几种方法
HEAD
GET
POST
# HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
只限于三个值
application/x-www-form-urlencoded multipart/form-data text/plain
凡是不同时满足以上的两种条件,就属于非简单请求。
浏览器对于这两种请求的处理方式,是不一样的。
对于简单请求,浏览器会发送一次请求,数据会到达浏览器,如果请求地址URL和浏览器不同源(或者不在浏览器允许的域范围内),就会报错。
对于非简单的请求,会发送两次请求,第一次先发送预检请求,只有预检通过了才会发送第二次请求
关于预检
如果复杂请求是PUT请求,则服务端要设置允许某请求通过,否则的话预检不通过;
Access-Control-Request-Method
如果复杂请求设置了请求头,那么服务端要设置允许某请求头通过,否则预检不通过;
Access-Control-Request-Headers
支持跨域
# 简单请求
服务器设置响应头:Access-Control-Allow-Origin = ‘域名‘ 或 ‘*‘
# 非简单请求
对于非简单请求,首先先会发送预检请求,预检请求后才会发送真实的数据
“预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
“预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
5.同源策略演示
请求发起者http://127.0.0.1:8004/test/ 向 http://127.0.0.1:8000/home/test/ 发送get请求(简单请求),收到数据后,判断不同源,则报错。
请求发起者
def test(request):
return render(request, ‘test.html‘)
</head>
<body>
<button onclick="test()">点我</button>
</body>
<script>
function test() {
$.ajax({
url:‘http://127.0.0.1:8000/home/test/‘,
type:‘get‘,
{#contentType:‘application/json‘,#}
{#data:JSON.stringify({‘name‘:‘lqz‘}),#}
success:function (data) {
console.log(data)
}
})
}
</script>
请求响应者
class TestView(APIView):
def get(self, request, *args, **kwargs):
dic = {‘name‘: ‘lqz‘}
print(‘lxx‘)
return APIResponse()
这时候,数据虽然会发送给8004端口的程序,但是由于浏览器存在同源策略,如果在8000中没有设置允许8004跨域的头部信息的话,则会报错:
简单请求的跨域
class TestView(APIView):
def get(self, request, *args, **kwargs):
dic = {‘name‘: ‘lqz‘}
print(‘lxx‘)
return APIResponse(headers={"Access-Control-Allow-Origin": "http://127.0.0.1:8004"}) # 或者 {"Access-Control-Allow-Origin": "*"}
非简单请求的跨越
# 8004 向 8000 发送post请求,且Content-Type是‘application/json‘类型
<script>
function test() {
$.ajax({
url: ‘http://127.0.0.1:8000/home/test/‘,
type: ‘post‘,
contentType: ‘application/json‘,
data: JSON.stringify({‘name‘: ‘lqz‘}),
success: function (data) {
console.log(data)
}
})
}
</script>
会发送两次请求,第一发送options请求,进行请求的预检
def options(self, request, *args, **kwargs):
print(‘我是 options‘)
return APIResponse(headers={"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Origin": "http://127.0.0.1:8004"})
def post(self, request, *args, **kwargs):
print(‘lqz‘)
return APIResponse(headers={"Access-Control-Allow-Origin": "http://127.0.0.1:8004"})
6.跨域请求的中间件
# 低配版
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleware(MiddlewareMixin):
ALLOW_HOST = ‘http://127.0.0.1:8004‘ # 可以放到配置文件中
def process_response(self, request, response):
response[‘Access-Control-Allow-Origin‘] = self.ALLOW_HOST
if request.method == ‘OPTIONS‘:
response[‘Access-Control-Allow-Headers‘] = ‘Content-Type‘
return response
dev.py
MIDDLEWARE = [
...
‘luffyapi.utils.corsmiddleware.CorsMiddleware‘,
]
7.使用第三方的插件
# 安装第三方的插件
pip install django-cors-headers
# 注册app
corsheaders
# 注册中间件
‘corsheaders.middleware.CorsMiddleware‘
MIDDLEWARE = [
# 第三方 cors插件
‘corsheaders.middleware.CorsMiddleware‘,
...
]
# 在dev.py中进行配置(可选择)
CORS_ORIGIN_ALLOW_ALL = True # 选择不限制跨域访问 如果为True将不再使用白名单,默认为False
CORS_ORIGIN_WHITELIST = ( # 选择放行的白名单(授权进行跨站点HTTP请求的来源列表)
‘http://127.0.0.1:8004‘,
‘https://sub.example.com‘,
r‘^https://w+.example.com$‘, # 在有大量子域使用的情况下,可以使用正则
)
CORS_ALLOW_METHODS = ( # 允许跨域的方法
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT"
)
CORS_ALLOW_HEADERS = ( # 允许跨域的请求头
"accept",
"accept-encoding",
"authorization",
"content-type",
"dnt",
"origin",
"user-agent",
"x-csrftoken",
"x-requested-with",
)
CORS_PREFLIFHT_MAX_AGE = 0
客户端/浏览器可以缓存预检响应的秒数。如果该值为0(或任何错误值),则不会发送最大期限标头。默认为 86400(一天)
CORS_ALLOW_CREDENTIALS
如果为True,则将允许将cookie包含在跨站点HTTP请求中。默认为False。
注意:在Django 2.1中,添加了SESSION_COOKIE_SAMESITE设置,‘Lax‘默认情况下设置为 ,这将防止Django的会话cookie跨域发送。更改它以None绕过此安全限制。
8.前后台打通
# 下载axios
pip install axios
# 配置min.js文件
import axios from ‘axios‘
Vue.prototype.$axios = axios;
home.vue
<template>
<div class="Home">
<h1>我是主页</h1>
<button @click="test">点我</button>
</div>
</template>
<script>
// @ is an alias to /src
export default {
name: ‘Home‘,
methods: {
test() {
this.$axios.get(‘http://127.0.0.1:8000/home/test/‘).then(response => {
console.log(response.data) # ES6新语法,支持=>函数
}).catch(errors => {
console.log(errors)
})
}
}
}
</script>
"""
this.$axios.get(‘http://127.0.0.1:8000/home/home/‘). 向某个地址发送get请求
then(function (response) { 如果请求成功,返回的数据再response中
console.log(response)
}).catch(function (error) {
console.log(error)
})
"""
index.js
Vue.use(VueRouter)
const routes = [
{
path: ‘/‘,
name: ‘Home‘,
component: Home
},
]
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<style>
</style>
<script>
export default {
name: ‘App‘,
components: {}
}
</script>
9 X-admin后台
的安装
# 创建superuser
python manage.py createsuperuser
原始的admin后台管理界面
x-admin
的下载
pip install -U https://codeload.github.com/sshwsfc/xadmin/zip/django2 --default-timeout=1000
注册apps
INSTALLED_APPS = [
# ...
# xadmin主体模块
‘xadmin‘,
# 渲染表格模块
‘crispy_forms‘,
# 为模型通过版本控制,可以回滚数据
‘reversion‘,
]
xadmin
需要自己的数据库模型
执行数据库迁移的命令
python manage.py makemigrations
python manage.py migrate
主路由替换掉admin
:主urls.py
# xadmin的依赖
import xadmin
xadmin.autodiscover()
# xversion模块自动注册需要版本控制的 Model
from xadmin.plugins import xversion
xversion.register_models()
urlpatterns = [
# ...
path(r‘xadmin/‘, xadmin.site.urls),
]
修改标题
import xadmin
from xadmin import views
class GlobalSettings(object):
"""xadmin的全局配置"""
site_title = "路飞学城" # 设置站点标题
site_footer = "路飞学城有限公司" # 设置站点的页脚
menu_style = "accordion" # 设置菜单折叠
xadmin.site.register(views.CommAdminView, GlobalSettings)
以上是关于同源策略的解决方案的主要内容,如果未能解决你的问题,请参考以下文章