addCookieToResponse () 这个函数接收了一个 null
我有一个中间件,用于验证用户是否登录的,用户每次访问接口,都会经过这个中间件验证,这时候小部分接口就会报如下错误:
postman 测试接口直接报 500,打断点时,根本没有经过我的接口和中间件,所以有可能是我的配置错误吗?最神奇的是,安卓那边请求接口时,有时会成功,但有时无反应,不涉及头部信息的问题。
环境:本地:homestead,线上:Ubuntu 18.04+apache2; 都是php7.2的,使用的是 php7.2-fpm 进行管理的;
我只写了一个中间件,代码如下:
<?php
namespace App\Http\Middleware;
use Closure;
use App\Models\Users\User;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Log;
class CheckToken
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// 必传参数,u_id 是一个加密的字符串
if(empty($request->token)) {
return JsonResponseArr('缺少必要参数 token');
}
// code = -2 时,说明用户不存在或者用户登陆失效,跳回登陆页面
$token = User::where('token', $request->token)->first();
if (!$token) {
return JsonResponseArr('用户登陆保持已失效,请重新登陆', -2);
}
$uid = Crypt::decryptString($request->token);
session()->put('uid', $uid);
session()->save();
return $next($request);
}
}
上面的函数:JsonResponseArr
是我自定义函数,放在帮助类里了,如下:
function JsonResponseArr($message, $code = 0, $data = null)
{
return response()->json([
'code' => $code,
'message' => $message,
'data' => $data,
])->setEncodingOptions(JSON_UNESCAPED_UNICODE);
}
Kernel 文件如下:
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\EncryptCookies::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\EnableCrossRequestMiddleware::class,
];
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
// 下面是自定义 token 验证
'token' => \App\Http\Middleware\CheckToken::class,
// 这里无所谓,我报错的接口不涉及下面这些中间件
'login' => \App\Http\Middleware\CheckLogin::class,
'phone' => \App\Http\Middleware\CheckPhone::class,
'code' => \App\Http\Middleware\CheckCode::class,
'real-name_auth' => \App\Http\Middleware\CheckRealNameAuth::class,
];
}
本地访问都可以,但线上就是报错,扩展检查了,也没问题。我在社区中也看了一些,说是 addCookieToResponse
这个函数的第一个参数接收的是一个 response 对象,我想请问各位我的程序是哪里出错了呢?
2020-01-11 更新问题
今天在项目中又遇到了这种问题,就查看了一下源码:
public function handle($request, Closure $next)
{
$this->sessionHandled = true;
// If a session driver has been configured, we will need to start the session here
// so that the data is ready for an application. Note that the Laravel sessions
// do not make use of PHP "native" sessions in any way since they are crappy.
if ($this->sessionConfigured()) {
$request->setLaravelSession(
$session = $this->startSession($request)
);
$this->collectGarbage($session);
}
$response = $next($request);
var_dump($response); // 这里
// Again, if the session has been configured we will need to close out the session
// so that the attributes may be persisted to some storage medium. We will also
// add the session identifier cookie to the application response headers now.
if ($this->sessionConfigured()) {
$this->storeCurrentUrl($request, $session);
echo gettype($response); // 这里
$this->addCookieToResponse($response, $session);
}
return $response;
}
两个结果都是 null
。
后来我检查了我的接口,发现我请求的接口其实是不存在的,也就是说,本来应该报404的错误,但报了这个错误,所以应该是执行顺序的问题(具体的顺序没细看,但这个应该是先执行的),错误的接口没有任何响应,导致 addCookieToResponse
此方法第一个参数接收的参数为 null
。
其实还是自己程序的问题。
突然一不小心解决了问题,我配置和程序都没有问题,是因为我服务器上使用了
https
,然后做了一个重定向,当http
访问时重定向到https
,使用http
访问时,有时会被拦截,使用https
则一切正常。感谢@nfangxu的解答