Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 621|回复: 0

Laravel解决预请求和跨域的问题

[复制链接]
  • TA的每日心情
    奋斗
    半小时前
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-21 16:34:48 | 显示全部楼层 |阅读模式

    场景描述

      最近在做公司的一个项目,我们在做这个小项目的时候,决定采用三端分离,数据库、服务器端、前端都分离。这样的分离是好的,但是我们遇到了一个问题,这个问题就是跨域问题和预请求问题。跨域的问题是因为我们将前端和后端放在两台服务器,数据之间的访问是通过RestApi进行的,这个时候的访问就涉及跨域的问题。还有一个问题就是预请求的问题,这个问题的引发就是在访问Api的时候要携带令牌,没有令牌是不能访问的。前端每次在访问接口的时候都要在请求头加上Token,加上token之后就出现了预请求的问题。为了解决预请求太搞脑子。下面我们就来说说预请求的问题。

    CORS描述

    一、CORS定义

      跨来源资源共享(CORS)是一份浏览器技术的规范,提供了 Web 服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比JSONP要来的好,JSONP对于 RESTful 的 API 来说,发送 POST/PUT/DELET 请求将成为问题,不利于接口的统一。但另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。不过现代的浏览器(IE10以上)基本都支持 CORS。

    二、简单请求和非简单请求

      只要同时满足以下两大条件,就属于简单请求。否侧就是非简单请求。

    (1) 请求方法是以下三种方法之一:
    
           HEAD
           GET
           POST
    (2)HTTP的头信息不超出以下几种字段:
    
          Accept
          Accept-Language
          Content-Language
          Last-Event-ID
          Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

    对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。

    GET /cors HTTP/1.1
    Origin: http://api.bob.com
    Host: api.alice.com
    Accept-Language: en-US
    Connection: keep-alive
    User-Agent: Mozilla/5.0...

    非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json或者自定义请求头信息

    非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

    非简单请求两个重要的参数:

      1、Access-Control-Request-Method:该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法。

      2、Access-Control-Request-Headers:该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。

    三、预检请求定义

      在 CORS 中,可以使用 OPTIONS 方法发起一个预检请求(一般都是浏览检测到请求跨域时,会自动发起),以检测实际请求是否可以被服务器所接受。预检请求报文中的 Access-Control-Request-Method 首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。

    预检请求的过程 

      

    由上面图可以看出,解决预请求是靠服务器来解决。

    请求失败的结果:如果失败请求头的Token就不能加上去

    请求成功的结果

    laravel怎么实现OPTIONS请求

      我在网上找了好多资料,看了之后都不能解决预检测的问题,因为项目的需要,需要在所有的Api接口的访问携带Token,这个时候我们注册中间件就要注册全局的,而不是路由的。

    注意:我第一次在路由里面直接注册中间件,还是不能成功响应。通过调试发现Laravel预检测不能放在路由的中间件里面,如果放在哪就不生效。我们要放在全局中间件里面或者直接放在路由里面。

    见代码

    public function handle($request, Closure $next)
        {
            $response = $next($request);
            $response->header('Access-Control-Allow-Origin', '*');
            $response->header('Access-Control-Allow-Headers', 'Origin,No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, token');
            $response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS');
            $response->header('Access-Control-Allow-Credentials', 'true');
            //验证token是否
            $token = $request->header('token');
            if(!$token){
                return Base::response('授权失败,请检查token',0);
            }else{
                $res = (new Token())->verifyToken($token);
                if(!$res){
                    return Base::response('token失效,请重新获取',0);
                }
            }
            return $response;
        }
    

    注册中间件

      protected $middleware = [
            \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
            \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
            \App\Http\Middleware\TrimStrings::class,
            \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
            \App\Http\Middleware\CorsHttp::class,
        ];
    

    最后大功告成,希望可以帮助到大家。

      

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-11-24 16:33 , Processed in 0.058275 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表