浏览器的同源策略
浏览器安全的基石是"同源政策"(same-origin policy)
含义:
1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。
最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"。
- 协议相同
- 域名相同
- 端口相同
举例来说,http://www.example.com/dir/page.html
这个网址,协议是http://
,域名是www.example.com
,端口是80
(默认端口可以省略)。它的同源情况如下。
http://www.example.com/dir2/other.html:同源 http://example.com/dir/other.html:不同源(域名不同) http://v2.www.example.com/dir/other.html:不同源(域名不同) http://www.example.com:81/dir/other.html:不同源(端口不同)
摘自:http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
下面就是一个同源策略的例子,项目2访问项目1的资源
项目1(http://127.0.0.1:8000):
urls.py
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index), url(r'^send_ajax/', views.send_ajax), ]
views.py
from django.shortcuts import render, HttpResponse def index(request): return render(request, 'index.html') def send_ajax(request): print("index1") return HttpResponse("this is index1")
index.html
{% load staticfiles %} <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>index</title> <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}"> <body> <div class="container-fluid"> <h1> index1页面</h1> <button class="send_ajax">send_ajax</button> </div> <script src="{% static 'js/jquery-3.2.1.min.js' %}"></script> <script> $(".send_ajax").click(function () { $.ajax({ url: "/send_ajax/", success: function (data) { alert(data) } }) }) </script> </body> </html>
同时开启项目2(http://127.0.0.1:8010)
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index), url(r'^send_ajax/', views.send_ajax), ]
urls.py
views.py
from django.shortcuts import render, HttpResponse def index(request): return render(request, 'index.html') def send_ajax(request): print("---------index2----------") return HttpResponse("this is index2")
index.html
{% load staticfiles %} <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>index</title> <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}"> <body> <div class="container-fluid"> <h1> index2页面</h1> <button class="send_ajax">send_ajax</button> </div> <script src="{% static 'js/jquery-3.2.1.min.js' %}"></script> <script> $(".send_ajax").click(function () { $.ajax({ url:"http://127.0.0.1:8010/send_ajax/", success: function (data) { alert(data) } }) }) </script> </body> </html>
此时各自点击都可以正常使用
将项目2的index.html里ajax 的url改一下,去访问项目1的资源
<script> $(".send_ajax").click(function () { $.ajax({ url:"http://127.0.0.1:8000/send_ajax/", success: function (data) { alert(data) } }) }) </script>
此时会被浏览器阻止,因为浏览器的同源策略,这样的请求叫做跨域请求。
谷歌浏览器提示
火狐浏览器提示
请求是发出去了,只是被浏览器阻止了
解决跨域请求的解决方法有两个:
解决跨域请求,script src引入
项目2 index.html
{% load staticfiles %} <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>index</title> <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}"> <body> <div class="container-fluid"> <h1> index2页面</h1> <button class="send_ajax">send_ajax</button> </div> <script src="{% static 'js/jquery-3.2.1.min.js' %}"></script> <script> function lcg(arg) { alert(arg) } </script> <script src="http://127.0.0.1:8000/send_ajax/"></script> </body> </html>
项目1 views.py
from django.shortcuts import render, HttpResponse def send_ajax(request): print("index1") return HttpResponse("lcg('hello LCG')")
项目2访问http://127.0.0.1:8010/index/:
优化index:
{% load staticfiles %} <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>index</title> <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}"> <body> <div class="container-fluid"> <h1> index2页面</h1> <button class="send_ajax">send_ajax</button> </div> <script src="{% static 'js/jquery-3.2.1.min.js' %}"></script> <script> function lcg(arg) { alert(arg) } $(".send_ajax").click(function () { var $script = $("<script>"); $script.attr("src", "http://127.0.0.1:8000/send_ajax/") $("body").append($script); $("body script:last").remove() }) </script> </body> </html>
效果是一样的。script生成使用后立即删除。
优化成函数:
<script> function lcg(arg) { alert(arg) } function kuayu_request(url) { var $script = $("<script>"); $script.attr("src", url); $("body").append($script); $("body script:last").remove() } $(".send_ajax").click(function () { kuayu_request("http://127.0.0.1:8000/send_ajax/") }); </script>
修改项目1的views.py 项目2的index.html
views.py
def send_ajax(request): print("index1") a = "hello lcg" return HttpResponse("lcg('%s')" % a)
index.html
<script> function lcg(arg) { console.log(arg) } function kuayu_request(url) { var $script = $("<script>"); $script.attr("src", url); $("body").append($script); $("body script:last").remove() } $(".send_ajax").click(function () { kuayu_request("http://127.0.0.1:8000/send_ajax/") }); </script>
看似没问题,但是我只需要改一下项目1里的views.py。
def send_ajax(request): print("index1") a = "{'name':'lcg','age':'18'}" return HttpResponse("lcg('%s')" %a)
怎么办,我们想到了json。
关于json,参考这里(http://www.cnblogs.com/0bug/p/7994374.html)
views.py
def send_ajax(request): print("index1") a = json.dumps({'name': 'lcg', 'age': '18'}) return HttpResponse("lcg('%s')" % a)
index.html
<script> function lcg(arg) { console.log(JSON.parse(arg)) } function kuayu_request(url) { var $script = $("<script>"); $script.attr("src", url); $("body").append($script); $("body script:last").remove() } $(".send_ajax").click(function () { kuayu_request("http://127.0.0.1:8000/send_ajax/") }); </script>
效果
优化:
views.py
def send_ajax(request): func_name=request.GET.get("callback") print("index1") a = json.dumps({'name': 'lcg', 'age': '18'}) return HttpResponse("%s('%s')" %(func_name,a))
index.html
<script> function lcg(arg) { console.log(JSON.parse(arg)) } function kuayu_request(url) { var $script = $("<script>"); $script.attr("src", url); $("body").append($script); $("body script:last").remove() } $(".send_ajax").click(function () { kuayu_request("http://127.0.0.1:8000/send_ajax/?callback=lcg") }); </script>
基于jquery 跨域请求 jsonp
views.py
def send_ajax(request): func_name=request.GET.get("callback") print("index1") a = json.dumps({'name': 'lcg', 'age': '18'}) return HttpResponse("%s('%s')" %(func_name,a))
index.html
<script> $(".send_ajax").click(function () { $.ajax({ url: "http://127.0.0.1:8000/send_ajax/", dataType: "jsonp", jsonp: "callback", success: function (data) { console.log(data) } }) }) </script>
应用,访问云南电视台接口
已知接口:http://www.jxntv.cn/data/jmd-jxtv2.html
代码:
<script> $(".send_ajax").click(function () { $.ajax({ url: "http://www.jxntv.cn/data/jmd-jxtv2.html", dataType: "jsonp", jsonp: "callback", jsonpCallback: "list" }); }); function list(shuju) { console.log(shuju) } </script>