跨域解决方案

因为浏览器可以同时打开很多页面,可以同时保存很多授权信息,浏览器为了安全问题,采用了同源策略(浏览器存在跨域问题,服务器不存在跨域问题)

同源策略:是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到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函数中返回。

从原理也能看出,JSONP并不要求必须传递JSON格式的数据,只要是JS函数能够认可的数据都是可以传递的

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小江小河点、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值