当前位置:Gxlcms >
数据库问题 >
[oldboy-django][2深入django]浏览器同源策略 + JSONP + cros
[oldboy-django][2深入django]浏览器同源策略 + JSONP + cros
时间:2021-07-01 10:21:17
帮助过:7人阅读
-
同源: 同方法,同域名,同端口
http://www.baidu.com:8000
http: 方法
www.baidu.com: 域名
8000
: 端口
-
定义
网上解析非常好的一篇
http://www.ruanyifeng.com/blog/2016/04/same-origin-
policy.html
-
限制 ajax只能发给同源的网址;
限制原理:
浏览器request--->
跨域服务器
浏览器阻止接收<----
跨域服务器响应, 服务器已经做出响应了,而且返回了,只是浏览器阻止接收
-
解决策略JSONP
它的基本思想是,网页通过添加一个<script>
元素,请跨域请求放在src属性上
向服务器请求JSON数据
(注意数据是json,数据是通过回调函数的参数传递回来的,
所以参数必须是经过json话
)
这种做法不受同源政策限制;
服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
JSONP需求:向其他网站发送http请求
- 解决办法:浏览器直接发送请求(到访问其他网站)--
考虑浏览器同源
-
要求:
1
. 客户端
- jsonp发送url, 把funname放到url中 url?callback=
myfun
-
定义myfun函数 function myfun(arg)
2
. 服务端
- 获取callback, fun_name = request.GET.get(
‘callback‘)
-
arg是请求,需要获取的数据,这个数据必须字符串或者是Json字符串
- 字符串 temp =
‘%s(%s)‘ %
(fun_name, arg)
注意,如果arg是列表等类型要先arg =
json.dumps(arg)
-
返回字符串
return HttpResponse(temp)
ps: 不是特别必要
修改django settings.py里面的ALLOWED_HOSTS = [
‘http://www.s4.com‘]
修改C:\Windows\System32\Drivers\etc\hosts里面的内容增加内容
127.0.0.1
www.s4.com
127.0.0.1
www.s5.com
-
原理:
只要页面加载下面语句
<script src=
"http://www.s4.com:8001/user"></script>
内存中就会返回http://www.s4.com:8001/
user页面内容,
并且将内容保存在内存中, 在页面的时候,会将内容当做Js渲染
当请求http://www.s4.com:8001/user?myfun=
callback,
后台返回Json.dumps(‘myfun(arg)‘),
存储在浏览器内存中,就相当于调用函数 myfun(arg),
因此,需要在前端定义callback(arg),这样就不需要考虑什么时候调用函数,
为了节省空间,一般绑定一个事件动态生成script标签,
function xxx(){
var tag = document.createElement(
‘script‘)
tag.src =
‘http://www.s4.com:8001/user?callback=myfun‘;
document.getElementByTag(‘head‘).appendChild(tag);
}
function myfun(arg){
console.log(arg);
}
# JSONP实例--动态创建script标签
# A网站前端
<!DOCTYPE html>
<html lang=
"en">
<head>
<meta charset=
"UTF-8">
<title>Title</title>
</head>
<body>
<input type=
"button" value=
"jsonp" onclick=
"test_jsonp();">
<script>
function test_jsonp(){
var tag = document.createElement(
‘script‘);
tag.src =
‘http://127.0.0.1:8001/users?callback=get_users‘;
document.head.appendChild(tag);
}
function get_users(arg){
alert(123
);
console.log(arg)
}
</script>
</body>
</html>
# B网站处理请求
url(r
‘^users‘, views.users),
def users(request):
fun_name = request.GET.get(
‘callback‘)
user_list = json.dumps([
‘alex‘,
‘egon‘,
‘eric‘])
temp =
"%s(%s)" %
(fun_name, user_list)
return HttpResponse(temp)
# 用jQuery 封装JSONP,
# 主要是前端不同,其他的一一致
<!DOCTYPE html>
<html lang=
"en">
<head>
<meta charset=
"UTF-8">
<title>Title</title>
</head>
<body>
<input type=
"button" value=
"获取用户列表" onclick=
"getUsers();">
</body>
<script src=
"/static/js/jquery-1.12.4.js"></script>
<script>
function getUsers(){
$.ajax({
url: ‘http://127.0.0.1:8001/users‘,
type: ‘GET‘,
dataType: ‘jsonp‘,
jsonp: ‘callback‘, //
指定url传递参数名称
jsonpCallback: ‘myFun‘ //
指定回调函数
})
// jsonp:
‘callback‘, jsonCallback
" :‘myFun‘
// 等效于将?callback=
myFun加到url上
}
function myFun(arg){
console.log(arg);
}
</script>
</html>
# jQuery实现跨越的另一种方式$.getJSON()
利用getJSON来实现,只要在地址中加上callback=
?参数即可
<!DOCTYPE html>
<html lang=
"en">
<head>
<meta charset=
"UTF-8">
<title>Title</title>
</head>
<body>
<input type=
"button" value=
"获取用户列表" onclick=
"getUsers();">
</body>
<script src=
"/static/js/jquery-1.12.4.js"></script>
<script>
function getUsers(){
$.getJSON("http://127.0.0.1:8001/users?callback=?", myFun);
}
function myFun(arg){
console.log(arg);
}
</script>
</html>
# 使用jsonp注意:
-
只能发get请求(生成script标签,里面的src肯定是get请求)
-
客户端和服务端做好约定
-
jsonp是一项技术,方法;目的是解决跨域问题
# 解决跨域请求的另一种方式:cors : cross site
在响应增加一个响应头:Access-Control-Allow-
Origin, 这样就允许ajax跨域发送请求.
浏览器看到这个消息头,就不会阻止接收跨域返回的响应
# 视图函数
obj =
HttpResponse()
obj[‘Access-Control-Allow-Origin ‘]=
‘*‘
# 或者obj[‘Access-Control-Allow-Origin ‘]= ‘www.s4.com:8000‘
return obj
# cros解决浏览器阻止ajax跨域问题 --简单请求
-
实例
# 前端
<body>
<input type=
"button" value=
"cros支持ajax跨域发送请求" onclick=
"JsAjaxSend();">
</body>
<script src=
"/static/js/jquery-1.12.4.js"></script>
<script>
function JsAjaxSend() {
$.ajax({
url: ‘http://127.0.0.1:8001/new_users‘,
type: ‘GET‘,
success:function(arg){
console.log(arg)
}
})
}
</script>
# http://127.0.0.1:8001/new_users视图函数
def new_users(request):
print(
‘请求来了‘)
user_list = [
‘alex‘,
‘egon‘,
‘eric‘]
user_list_str =
json.dumps(user_list)
obj =
HttpResponse(user_list_str)
obj[‘Access-Control-Allow-Origin‘] =
"http://127.0.0.1:8000"
return obj
# cros解决ajax跨域请求问题--复杂请求
复杂请求实际上发送了两个请求: OPTIONS,以及后面的复杂请求。
# 前端
function JsAjaxSend() {
$.ajax({
url: ‘http://127.0.0.1:8001/complicated_users‘,
type: ‘DELETE‘,
success:function(arg){
console.log(arg)
}
})
}
# 视图 --这里取消了csrf
def complicated_users(request):
if request.method ==
‘OPTIONS‘:
# 设置允许delete方法和浏览器接收跨域响应
obj =
HttpResponse()
obj[‘Access-Control-Allow-Methods‘] =
‘DELETE‘
obj[‘Access-Control-Allow-Origin‘] =
"http://127.0.0.1:8000"
return obj
else:
user_list_str = json.dumps([
‘eric‘,
‘alex‘])
obj =
HttpResponse(user_list_str)
obj[‘Access-Control-Allow-Origin‘] =
"http://127.0.0.1:8000"
return obj
# 如何区分复杂请求和简单请求
1
、请求方式:HEAD、GET、POST
2
、请求头信息:
Accept
Accept-
Language
Content-
Language
Last-Event-
ID
Content-
Type 对应的值是以下三个中的任意一个
application/x-www-form-
urlencoded
multipart/form-
data
text/
plain
注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
# 参考博客
http://www.cnblogs.com/wupeiqi/articles/5703697.html
View Code
[oldboy-django][2深入django]浏览器同源策略 + JSONP + cros
标签:如何 script child query ajaxsend users 函数 site 元素