因为浏览器可以同时打开很多页面,可以同时保存很多授权信息,浏览器为了安全问题,采用了同源策略(浏览器存在跨域问题,服务器不存在跨域问题)
同源策略:是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
比如,浏览器的地址是baidu.com,页面通过ajax请求京东,就存在跨域,浏览器就阻止了该行为
现在有一个需求,两个服务器A和B,浏览器通过请求服务器A获取页面A,然后在页面A下通过ajax请求访问网页B,浏览器是不允许这样操作的,但是可以通过一些条件可以去实现
1.浏览器的页面A通过Ajax请求访问B页面时,浏览器可以先询问服务器B是否同意
如果页面A通过ajax直接访问页面B,会报错 cors -> cross origin resources sharing error,MissingAllowOriginHeader(跨域资源共享,丢失了允许跨域的头)
解决方案:
@RestController
public class UserController {
//方式一:手动添加请求头
@RequestMapping("/user")
public User getUser(HttpServletResponse response){
//第一个参数是添加一个请求头,第二个参数是允许请求的来源地址
response.addHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8081");
//10秒钟之内再次请求的时候,就不用发送预检请求了
response.addHeader("Access-Control-Max-Age", "10");
//允许你发送的请求是GET请求还是POST请求
response.addHeader("Access-Control-Allow-Method", "GET");
return new User("java", "java");
}
//方式二:添加注解@CROSSORIGIN
@RequestMapping("/user")
@CROSSORIGIN(origin = {"http://127.0.0.1:8081"})//添加来源地址
public User getUser(HttpServletResponse response){
return new User("java", "java");
}
}
浏览器的页面A访问页面B的时候,会发送两个请求,第一个请求是option——预检请求,第二请求是get——获取数据
2.服务器与服务器之间是不存在跨域问题的,因为浏览器可以同时打开十几个网站,这时,浏览器既有A页面的授权信息,也有B页面的授权信息,而服务器不可能打开十几个网站,并获取到别的页面的授权信息,否则A网站就相当于做了B网站的认证了,浏览器使得客户端能够将多个网站的用户信息都存在同一物理环境,而服务器只能保存自己所提供服务的信息
解决方案:浏览器通过网页A访问服务器A,服务器A再去访问服务器B,这样服务器A就相当于一个中间代理,去获取服务器B的网页信息
实现一:可以通过http请求服务器B获取网页B的数据,例如restTemplate,相当于手写一个方向代理服务器
实现二:nginx(方向代理,动静分离,负载均衡),修改配置文件
server {
listen 80;
server_name localhost;
##添加以下标红的部分
location /api {
proxy_pass http://127.0.0.1:8082; ##路径带有api的请求转发到端口为8082的服务器
}
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
正向代理:用户A访问Google,由于存在墙,用户A只能通过先访问香港的服务器,由香港的服务器转发请求到Google服务器,这种代理模式是,用户明确要访问的地址,由于无法直接访问到最终的服务器,只能通过中间服务器去访问,直接输入Google的地址就可以了
反向代理:用户B访问代理服务器,但是服务器B要访问哪获取数据,用户不知道
3.jsonp利用浏览器天然支持跨域的标签<script>
<script>标签天然支持跨域,只支持GET请求,例如
前端代码
<script>
function callback(data){
console.log(data)
}
</script>
<script src="http://127.0.0.1:8082/cross"></script>
后端代码
@RequestMapping("/cross")
public String cross(HttpServletResponse response){
return "callback('123')"
}
请求返回后,返回的字符串会调用前端方法cross,最终打印出123
当使用script请求地址时,会将返回的字符串,默认当成js解析。由于后端返回是的callback(xxx),所以会调用本地的callback函数。
从原理上来看,要使用JSONP,必须要后端返回相应的数据,这个就是JSONP的模式了,允许客户端传递一个callback函数,后端将数据包裹在callback函数中返回。文章来源:https://www.toymoban.com/news/detail-477190.html
从原理也能看出,JSONP并不要求必须传递JSON格式的数据,只要是JS函数能够认可的数据都是可以传递的文章来源地址https://www.toymoban.com/news/detail-477190.html
到了这里,关于跨域解决方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!