关于作者的程序开发人员,不局限于语言和技术,目前主要从事PHP和前端开发,使用Laravel和VueJs,在App上使用Apicloud混合开发边。合身、够用才是最完美的追求。个人网站:http://www.linganmin.cn最近写了一个手机在线播放的H5电影站:http://www.ifilm.ltd日常填坑笔记关于Larave扩展laravel-cors使用的laravel-cors功能是解决跨域浏览器安装问题。在终端执行安装命令如下:composerrequirebarryvdh/laravel-cors添加服务提供者在Laravel配置文件app.php的providers数组中添加如下配置:Barryvdh\Cors\ServiceProvider::class,执行publish配置file在终端执行发布配置文件命令如下:phpartisanvendor:publish--provider="Barryvdh\Cors\ServiceProvider"执行后会在laravel目录文件下的config目录下添加cors.php配置,如下图所示,至此laravel-Cors安装完成。备注什么是跨域跨域是指从一个域名的网页请求另一个域名的资源。比如从www.baidu.com页面请求www.google.com资源。更严格的跨域定义是:只要协议、域名、端口有任何不同,就认为是跨域。浏览器为什么要限制跨域访问?网站的资源,则可能在客户完全不知情的情况下存在安全问题。为什么需要跨域?既然有安全问题,为什么还要跨域呢?有时公司内部有多个不同的子域,比如一个是b.a.com,申请放在c.a.com。这时候从b.a.com访问location.company.com的资源就是跨域了。如何解决跨域问题跨域访问需要两个东西,一个是JSON,一种基于文本的传输协议;另一个是JSONP,一个由一群编码人员想出的跨域解决方案。服务器需要做什么服务器需要检查访问请求参数。如果没有回调,可以按照前面的流程进行;如果它有一个回调参数,它需要将返回的结果包装在回调中。客户端(浏览器)需要做什么客户端可以通过多种方式实现JSONP调用larave-cors做了什么CORS是一个W3C标准,全称是“跨源资源共享”(Cross-originresourcesharing)。它允许浏览器向跨域服务器发送XMLHttpRequest请求,从而克服AJAX只能在同源上使用的限制。laravel-cors的官方介绍如下:laravel-cors包允许您使用ACL样式的per-url配置发送跨源资源共享标头。也就是说,laravel-cors允许所有跨域资源请求的header都被当作普通请求处理,从服务端解决了跨域资源共享的问题。更多laravel-cors使用配置请移步laravel-cors官方GitHub仓库填坑。入坑之前,想说的就是说说自己遇到的坑。首先介绍一下laravel处理的路由模式。官方文档说:所有的Laravel路由都定义在routes目录下的路由文件中,这些文件由框架自动加载。在routes/web.php文件中定义您的网页路由。这些路由应用了Web中间件套件,该套件提供Session和CSRF保护等功能。routes/api.php中定义的路由是无状态的,并应用api中间件组。可以获取到的信息如下:laravel默认的路由配置有两个,一个是routes目录下的web.php,一个是routes目录下的api.php;web.php中定义的路由默认使用Session和CSRF保护。特性,所以可以直接使用session技术,即正常的页面请求处理默认是web.php中定义的路由或者路由组api.php中的所有路由都是无状态的,不受Session和CSRF特性保护,所以其中定义的路由更适合为应用程序提供接口。默认情况下,当用户的请求路由前缀为api时,laravel会自动调用api.php中定义的路由或路由组。这是因为在laravel的路由服务提供者api中配置了路由前缀,下图是路由服务提供者所在的目录路径。下图是无状态路由组api.php的配置:这样当url类似于www.xxx的时候请求.com/api/route时,api.php路由组定义的路由会是自动叫入坑。上面说了api.php中定义的路由是无状态的,api.php更适合提供api接口,所以为了解决跨域我们安装了laravel-cors,但是安装还不够,还需要在会产生跨域的路由组中使用laravel-cors提供的中间件,所以我们可以这样使用laravel-cors//在需要跨域的路由中添加cors中间件Route::group(['middleware'=>'cors'],function(Router$router){$router->get('api','ApiController@index');});当我们整个api.php路由组需要跨域时,我们也可以配置api.php路由组在laravel框架的appHttpKernel.php文件中添加cors中间件,如下:/***应用的路由中间件组。**@var数组*/protected$middlewareGroups=['web'=>[\App\Http\Middleware\EncryptCookies::class,\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,\Illuminate\Session\Middleware\StartSession::类,\Illuminate\View\Middleware\ShareErrorsFromSession::类,\App\Http\Middleware\VerifyCsrfToken::类,\Illuminate\Routing\Middleware\SubstituteBindings::class,],'api'=>['throttle:60,1','bindings','cors'//安装laravel-cros添加cors中间件解决跨域问题],];注意,如果你在安装laravel-cors后仍然存在跨域问题,一定不要忘记检查你是否添加了cors中间件来谈谈laravel的表单验证。具体的表单验证可以参考官方文档(laravel的中文文档和laravel框架一样优雅),附上laravel表单验证中文文档的地址。我想说的是当ajax请求失败时,如果表单验证失败,会产生一个redirect,然后返回一个HTTP响应,其中包含422状态码和验证错误JSON数据,但是我们在上面看到的客户端可能是ajax跨域错误,因为我们在使用jquery或者其他javascript包的ajax请求方式时,没有将返回的数据类型指定为json,而laravel的错误处理默认解析为普通的web请求.上面在laravel表单验证规则中提到,当验证失败时,会产生一个redirect,但是我们看到的是跨域错误,下面是一个例子:login路由定义在api.php路由中groupasfollows//登录路由,使用依赖注入请求验证$request){//获取请求通过的两个字段$checkInfo=\Illuminate\Support\Facades\Input::only('mobile','password');try{//验证用户,如果验证通过则生成token,如果失败则返回错误if(!$token=JWTAuth::attempt($checkInfo)){returnResponse::json(['error'=>'账号或密码错误'],401);}return['user'=>JWTAuth::toUser($token),'token'=>$token];}catch(\Tymon\JWTAuth\Exceptions\JWTException$e){//返回捕获的异常returnResponse::json($e->getMessage(),500);}});api.php路由组中使用的表单验证类\App\Http\Requests\LoginRequest定义如下{/***确定用户是否有权发出此请求。**@returnbool*/publicfunctionauthorize(){returntrue;}/***获取适用于请求的验证规则。**@returnarray*/publicfunctionrules(){//调用模型静态属性定义的验证规则returnUser::$rules;}publicfunctionmessages(){//调用模型静态属性定义的验证规则提示返回用户::$消息;}}用户模型中定义的验证规则和验证提示如下publicstatic$rules=['mobile'=>'required','password'=>'required'];publicstatic$messages=['mobile.required'=>'手机号不能为空','password.required'=>'密码不能为空'];使用jquery的post请求发送ajax请求$.post('http://192.168.1.6:9999/api/login',{},function(data){console.log(data)});因为post请求没有传递任何参数,所以可能会验证失败,但是我们看到的确实是一个关于跨域失败的错误,如下图,是因为我们在发送的时候没有指定期望的返回数据类型post请求,laravel框架判断为正常的web请求,返回302跳转发送请求的页面在这个过程中产生了跨域,如下图所示,所以当我们指定期望的返回类型时我们发送一个ajax请求,可以看到laravel为我们返回了一个422验证失败的错误,代码和效果如下图所示:错误对应返回的json数据如下图所示:因此,在请求laravel的接口时,一定要指定期望的返回数据类型,安小霞同学
