同源策略和跨域请求
同源策略
- 我们与服务器之间通信的三要素:ip, 通讯协议,端口。即域名,协议,端口
- 如果我们和服务器之间通信,这三个要素都相同,那就是同源,如果其中一个不相同,那就是非同源。
- 这是浏览器的一种安全协议,是为了保护本地数据不被JavaScript代码获取回来的数据污染
跨域请求
- 什么是跨域请求:
- 即域名,协议,端口其中有一个不相同就是跨域请求
- 只有在同源的情况下,发送AJax请求才能获得请求的数据,非同源的请求都会受到同源策略影响。
- 这里说的跨域请求是XMLhttpreques请求,而herf,src,script,这些没有跨域请求的概念,不管是同源或者不同源,都可以请求到数据,浏览器也不会拦截。除非后台做了防盗链的处理。
- XMLHTTP是一组API函数集
- XMLHTTP最大的好处在于可以动态地更新网页,它无需重新从服务器读取整个网页,也不需要安装额外的插件。
- XMLHTTP是AJAX网页开发技术的重要组成部分。
- 如果是跨域请求,那么在请求数据时,如果服务区没有任何声明,那么浏览器就会将数据截获,页面不会获得数据。
- 这个数据请求过程中,浏览器已经成功请求了数据,服务器也响应了请求,将数据传递给了浏览器,只是浏览器将数据截获了。页面不能展示。
为什么要跨域请求
- 既然跨域请求很困难,为什么要跨域请求,因为在一些网站,数据体量大,有一些独立且复杂的业务,如果做成一个网站一台服务器也不现实 。因此就需要将这些网站分开,并对应相应的服务器,但是有时候可能需要请求其他服务器的数据,此时就是跨域请求了。
怎么解决跨域请求不数据
-
jsonp进行跨域:只能是get请求。
- 原理:使用不受同源策略限制的标签(script src,img,link her这三个标签)来进行请求。
- 原生的jsonp请求
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <script type="text/javascript"> function sendmsg(data){ alert(data.province); } </script> <script src="https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13259141515&callback=sendmsg"> <!-- 1.script src:用于此标签发送jsonp请求 2.src="https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13259141515&callback=sendmsg" 这是get请求的链接地址 3.jsonp的请求方式和AJAX请求方式不相同,需要在后面拼接回调函数 callback这是回调函数的键,也是大家约定俗成的,所以就是的固定写法 sendmsg 这是回调函数的名称 4.使用回调函数接受请求数据 function sendmsg(data){ alert(data.province); } 注意回调函数的调用必须在写到请求发送的前面 --> </script> <body> </body> </html>
- 原生的jsonp请求只能在后面写固定的参数,而且会自动调用,没有事件控制。想要控制,那就要动态生成src的连接地址。因此我们就会使用JQuery封装过后的jsonp来请求
- JQuery封装过后的请求
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="js/jquery.js" type="text/javascript" charset="utf-8"></script> <style type="text/css"> #box { margin-left:30%; margin-top: 50px; width: 500px; height: 300px; text-align: center; border: 1px,lightgoldenrodyellow,solid; } button { background-color: aquamarine; height: 25px; width: 50px; } #table { width: 500px; height: 300px; text-align: center; } input{ height: 20px; width: 200px; } td { width: 50%; } </style> </head> <body> <div id="bigbox"> <div id="box"> <h3>手机归属地查询</h3> <input type="text" id="iphone" value="" name="telnum" placeholder="请输入手机号码" /> <button type="button">查询</button> <br> <br> <div id="nei"> </div> </div> </div> </body> <!-- <script src="https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15613552070&callback=message" type="text/javascript" charset="utf-8"></script> --> </html> <script type="text/javascript"> var num; $("button").click(function() { num = $("input").val(); $.ajax({ type: "get", url: "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm", data: { tel: num }, success: function(data) { if(data.province==undefined){ alert("请正确输入手机号码") }else{ $("#nei").empty(); $("#nei").append('<table border="1px" cellspacing="0px" cellpadding="0px" id="table"></table>') $("#table").append('<tr><td colspan="2">查询结果</td></tr>') $("#table").append('<tr><td>你查询的手机号码段</td><td id="seek1"></td></tr>') $("#table").append('<tr><td>卡号归属地</td><td id="seek2">${data.province}</td></tr>') $("#table").append('<tr><td>卡类型</td><td id="seek3">${data.province}</td></tr>') $("#table").append('<tr><td>区号</td><td id="seek4">${data.province}</td></tr>') $("#table").append('<tr><td>邮编</td><td id="seek5">${data.province}</td></tr>') $("#table").append('<tr><td>运营商名称</td><td id="seek6">${data.province}</td></tr>') $("#seek1").text(data.telString) $("#seek2").text(data.province) $("#seek3").text(data.carrier) $("#seek4").text(data.mts) $("#seek5").text(data.areaVid) $("#seek6").text(data.catName) } }, jsonp: 'callback', dataType: "jsonp" }) }) </script> //这是请求回来的参数 //111305203147885197457_1596162065780<---回调函数名,在jQuery中我们只定义了回调函数的键 它的值也就是回调函数名是随机生成的。 <!-- jQuery111305203147885197457_1596162065780({ mts:'1561355', province:'河北', catName:'中国联通', telString:'15613552070', areaVid:'30499', ispVid:'137815084', carrier:'河北联通' }) -->
- jsonp和jQuery请求的区别
名称 jsonp jquery 请求方式 type(get) method(get/post) dataType jsonp json jsonp callback 无 - 原生的jsonp请求需要在src赋值链接,而jQuery封装过后的jsonp请求,可以更加便捷,只在发送的JSON字符串中做出体现
-
cros进行跨域:get/post请求都可以。也是现在常用的跨域请求方式。
- cros方案:浏览器检测到是跨域请求时,会在HTTP头部添加一个origin字段。
- 这样发送了请求,在服务器端我们还要设置请求头:Access -Control-Allow-Origin:*,这就是所有的跨域请求都可以,这样发送回来的数据,就不会被浏览器劫持了。
@WebServlet(value = "/login", name = "LoginServlet") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("请求来了"); //获取前台的请求参数 //后台还必须对用户名和密码进行二次校验 String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println(username); System.out.println(password); //调用JDBC 去查询数据库 //假如你查询完数据库,用户登录信息是对的 //给前台响应数据 response.setContentType("application/json;charset=utf-8"); //{"msg":"ok"} //String json2="{'msg':'0k'}"; 这么写JSON字符串不规范 前台JSON.parse() 转换不了为JSON对象 // \" 转意 这个双引号 // {"code":200,"msg":"ok"} //String jsonStr="{\"code\":200,\"msg\":\"ok\"}"; String json="{\"msg\":\"ok\"}"; //设置响应头 告诉浏览器,不管来自哪里的请求,我认为都可以,你浏览器,不要拦截我响应给人家的数据 response.setHeader("Access-Control-Allow-Origin","*"); response.getWriter().write(json); //浏览器同源策略机制 以及跨域请求 } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }