Warm tip: This article is reproduced from serverfault.com, please click

laravel-为什么响应中的CORS错误Access-Control-Allow-Credentials标头为“”?

(laravel - Why CORS Error Access-Control-Allow-Credentials' header in the response is ''?)

发布于 2020-11-30 08:01:44

我使用从Laravel 7后端REST中读取的数据制作了@ vue / cli 4.5.9 / axios应用程序(使用“ tymon / jwt-auth”:“ ^ 1.0”,“ barryvdh / laravel-cors”:“ ^ 1.0.5”)使用axios的API并出现错误:

has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.

但是在这里,我检查所有凭据是否都已填写: 我在客户端具有https://prnt.sc/vsngs5

        console.log('+login settingCredentialsConfig::')
        console.log(settingCredentialsConfig)

        axios.post(apiUrl + '/login', userCredentials, settingCredentialsConfig)
            .then((response) => {
                if (typeof response.data.access_token === 'undefined' || typeof response.data.user === 'undefined') {
                    commit('auth_error') // call auth_error mutation to make changes to vuex store
                    bus.$emit('authLoggedError')
                    return
                }

我从定义为的设置文件中导入settingCredentialsConfig:

export const settingCredentialsConfig = {
    withCredentials:true,
    headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials':true
    }
}

并在src / main.js中定义了axios:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'

export const bus = new Vue()

axios.defaults.crossDomain = true
let apiUrl = process.env.VUE_APP_API_URL
Vue.config.productionTip = false
Vue.prototype.$http = axios

Vue.config.productionTip = false

import Vue2Filters from 'vue2-filters'
Vue.use(Vue2Filters)

new Vue({
  router,
  store,
  bus,
  render: h => h(App)
}).$mount('#app')

Vue.use({
  install (Vue) {
    Vue.prototype.$api = axios.create({
      baseURL: apiUrl
    })
  }
})

在其他Vue页面中,我请求使用相同的settingCredentialsConfig var后端,它工作正常。但是它不引用后端用户模型的身份验证。在backenbd部分,我有app / User.php:

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject; // JWT SUPPORT

class User extends Authenticatable implements JWTSubject  // JWT SUPPORT
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function getJWTIdentifier()  // JWT SUPPORT
    {
        return $this->getKey();
    }
    public function getJWTCustomClaims()  // JWT SUPPORT
    {
        return [];
    }


}

在app / Http / Controllers / API / AuthController.php中:

<?php

namespace App\Http\Controllers\API;

use Auth;
use Config;
use DB;
use Validator;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;

//use Illuminate\Support\Str;

class AuthController extends Controller
{

    protected $maxAttempts = 1; // Default is 5
    protected $decayMinutes = 1; // Default is 1

    /**
     * Create a new AuthController instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('jwt.auth', ['except' => ['login', 'register', 'activate']]);
    }

    public function login(Request $request)
    {
        $credentials = $request->only('email', 'password');

        \Log::info('LOGIN +1 $credentials ::');


        if ($token = $this->guard('api')->attempt($credentials /*,['exp' => \Carbon\Carbon::now()->addHours(4)->timestamp]*/)) {
            $loggedUser = $this->guard('api')->user();

            \Log::info('LOGIN +2 $loggedUser ::');

            return $this->respondWithToken($token);
        }

        \Log::info('LOGIN -3 ::');

        return response()->json(['error' => 'Unauthorized'], 401);
    }

    public function getAuthenticatedUser()
    {
        try {
            \Log::info('-1 getAuthenticatedUser ::');
            if ( ! $user = JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 404);
            }


        } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
            \Log::info('-2 getAuthenticatedUser ::');

            return response()->json(['token_expired'], $e->getStatusCode());


        } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
            \Log::info('-3 getAuthenticatedUser ::');

            return response()->json(['token_invalid'], $e->getStatusCode());


        } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {
            \Log::info('-4 getAuthenticatedUser ::');

            return response()->json(['token_absent'], $e->getStatusCode());
        }

        // the token is valid and we have found the user via the sub claim
        return response()->json(compact('user'));
    }

    public function me()
    {
        return response()->json($this->guard('api')->user());
    }

    public function logout()
    {
        \Log::info('-1 logout ::' . print_r(-1, true));

        $this->guard('api')->logout();

        return response()->json(['message' => 'Successfully logged out']);
    }

    public function refresh()
    {
        return $this->respondWithToken($this->guard()->refresh());
    }

    protected function respondWithToken($token)
    {
        $loggedUser = $this->guard()->user();

        return response()->json([
            'access_token' => $token,
            'user'         => $loggedUser,
            'token_type'   => 'bearer',
            'expires_in'   => $this->guard('api')->factory()->getTTL() * 999360 // TOFIX
        ]);
    }

    public function guard()
    {
        return \Auth::Guard('api');
    }
}

并在config / cors.php中:

<?php

return [

    'paths' => ['api/*'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => false,

];

我用命令生成了文件config / jwt.php:

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

并保持不变。在文件app / Http / Kernel.php中:

    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,

        'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken',
        'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken',
...

我错过了什么 ?

谢谢!

Questioner
mstdmstd
Viewed
0
tamrat 2020-11-30 16:15:52

supports_credentialsconfig/cors.php文件中更改true