Laravel-요청시 세션 저장소가 설정되지 않음


113

최근에 새로운 Laravel 프로젝트를 만들고 인증 가이드를 따르고있었습니다. 로그인 또는 등록 경로를 방문하면 다음 오류가 발생합니다.

ErrorException in Request.php line 775:
Session store not set on request. (View: C:\Users\Matthew\Documents\test\resources\views\auth\register.blade.php)

핵심 Laravel 파일을 편집하지 않았으며보기 만 만들고 route.php 파일에 경로를 추가했습니다.

// Authentication routes
Route::get('auth/login', ['uses' => 'Auth\AuthController@getLogin', 'as' => 'login']);
Route::post('auth/login', ['uses' => 'Auth\AuthController@postLogin', 'as' => 'login']);
Route::get('auth/logout', ['uses' => 'Auth\AuthController@getLogout', 'as' => 'logout']);

// Registration routes
Route::get('auth/register', ['uses' => 'Auth\AuthController@getRegister', 'as' => 'register']);
Route::post('auth/register', ['uses' => 'Auth\AuthController@postRegister', 'as' => 'login']);

라 라벨에 대한 경험이 많지 않으니 실례합니다. 나는 이와 같은 것을 묻는 또 다른 질문 이 있다는 것을 알고 있지만 대답 중 어느 것도 나를 위해 작동하지 않는 것 같습니다. 읽어 주셔서 감사합니다!

편집하다:

여기에 요청한 register.blade.php가 있습니다.

@extends('partials.main')

@section('title', 'Test | Register')

@section('content')
    <form method="POST" action="/auth/register">
        {!! csrf_field() !!}
        <div class="ui input">
          <input type="text" name="name" value="{{ old('name') }}" placeholder="Username">
        </div>
        <div class="ui input">
          <input type="email" name="email" value="{{ old('email') }}" placeholder="Email">
        </div>
        <div class="ui input">
          <input type="password" name="password" placeholder="Password">
        </div>
        <div class="ui input">
          <input type="password" name="password_confirmation"placeholder="Confirm Password">
        </div>
        <div>
            <button class="ui primary button" type="submit">Register</button>
        </div>
    </form>
@endsection

포스트 register.blade.php 코드
— 드리 Waqas

당신은 또한 단지와 위의 routes.php을 대체 할 수 있습니다Route::controllers([ 'auth' => 'Auth\AuthController', 'password' => 'Auth\PasswordController', ]);
— 드리 Waqas에게

와 이름이 같은 경로를 가지고, 그것은 잘못, 서로 다른 이름을 가져야한다
— xAoc

@Adamnick 게시 및 교체를 시도합니다.
— mattrick 2015

세션 드라이버 구성은 어떻게 설정되어 있습니까?
— kipzes

답변:


162

세션 상태, CSRF 보호 등이 필요한 경우 웹 미들웨어 를 사용해야합니다 .

Route::group(['middleware' => ['web']], function () {
    // your routes here
});

2
나는 실제로 그것을 가지고 있습니다, 나는 단지 관련 경로를 포함하고있었습니다.
— mattrick 2015

아 이제 무슨 말인지 알 겠어요. 루트를 내부로 옮겨서 작동했습니다. 정말 고맙습니다!
— mattrick 2015

@mattrick : 안녕하세요 metrix가 동일한 오류를 가져옵니다. 미들웨어 내에서 경로를 이동 한 위치를 설명 할 수 있지만 "지원되는 암호화기를 찾을 수 없습니다. 암호"라는 오류가 표시됩니다.
— Vipin Singh

1
@ErVipinSingh 앱 구성에서 32 자 키를 설정해야합니다. 또는 사용php artisan key:generate
— Cas Bloem

2
로그인 경로가 API에 있으면 어떻게됩니까?
— Jay Bienvenu

56

귀하의 추가하면 routes내부를 web middleware어떤 이유로 작동하지 않음 다음이 추가 시도 $middleware로Kernel.php

protected $middleware = [
        //...
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
];

4
젠장, 이것은 나를 위해 일했지만 해결책이 아니라 "수정"이라는 것이 행복하지 않습니다. 어쨌든 감사합니다!
— Rav

1
이것은 나를 위해 그것을 고쳤습니다. 당신에게 @Waiyi 감사
— 조쉬

1
귀하의 솔루션은 내 문제를 @Waiyl_Karim 수정
— Bipul 로이

이것은 나를 위해 일했습니다. 나는 반응 프런트 엔드를 사용하고 있으므로 경로에 반응 라우터를 사용하고 있으므로 경로 그룹이 작동하지 않습니다.
— techcyclist

44

제 경우에는 (Laravel 5.3 사용) 다음 2 개의 미들웨어 만 추가하면 API 경로의 세션 데이터에 액세스 할 수 있습니다.

  • \App\Http\Middleware\EncryptCookies::class
  • \Illuminate\Session\Middleware\StartSession::class

전체 선언 ( $middlewareGroupsKernel.php에서) :

'api' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Session\Middleware\StartSession::class,
            'throttle:60,1',
            'bindings',
        ],

21

Cas Bloem의 답변이 적용되지 않는 경우 (즉 web, 해당 경로에 미들웨어 가 확실히 있음 ) HTTP 커널에서 미들웨어의 순서를 확인하는 것이 좋습니다.

기본 순서 Kernel.php는 다음과 같습니다.

$middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
    ],
];

VerifyCsrfToken뒤에 오는 것을 참고하십시오 StartSession. 순서가 다른 경우 이들 간의 종속성으로 인해 Session store not set on request.예외가 발생할 수도 있습니다 .


나는 그것을 똑같이 가지고 있습니다. í 여전히 메시지를받습니다. 또한 $ middleware 배열에 StartSession 및 ShareErrorsFromSession을 넣어 보았습니다. 저장 / 프레임 워드도 쓸 수 있습니다. (내가 BTW Wampserver 3을 사용하고 있습니다.)
— Meddie

use 'middleware'=> [ 'web', 'youanother.log'],
— Kamaro Lambert

3
네! 나는 바보 같았고 알파벳순으로 (강박 장애 때문에) 재정렬 할 것이라고 생각했고 앱이 망가졌습니다. 안타깝게도 다음날까지 테스트를하지 않았기 때문에 여기에 왔습니다. 참고로 5.3의 "웹"미들웨어 그룹의 기본 순서는 EncryptCookies, AddQueuedCookiesToResponse, StartSession, ShareErrorsFromSession, SubstituteBindings, VerifyCsrfToken입니다.
— Ixalmida

19

컨트롤러의 기능 내에서 세션 에 액세스 하려고하면 문제가 발생할 수 있습니다 .__constructor()

Laravel 5.3 이상부터는 업그레이드 가이드에 명시된 것처럼 어쨌든 작동하지 않기 때문에 더 이상 불가능합니다 .

이전 버전의 Laravel에서는 컨트롤러 생성자에서 세션 변수 또는 인증 된 사용자에 액세스 할 수있었습니다. 이것은 프레임 워크의 명시적인 기능을 의도 한 것이 아닙니다. Laravel 5.3에서는 미들웨어가 아직 실행되지 않았기 때문에 컨트롤러의 생성자에서 세션이나 인증 된 사용자에 액세스 할 수 없습니다.

더 많은 배경 정보는 Taylor 그의 답변을 읽어보십시오 .

해결 방법

그래도 사용하려면 업그레이드 가이드에 설명 된대로 미들웨어를 동적으로 만들고 생성자에서 실행할 수 있습니다.

대안으로 컨트롤러의 생성자에서 직접 클로저 기반 미들웨어를 정의 할 수 있습니다. 이 기능을 사용하기 전에 애플리케이션이 Laravel 5.3.4 이상을 실행 중인지 확인하십시오.

<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;

class ProjectController extends Controller
{
    /**
     * All of the current user's projects.
     */
    protected $projects;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware(function ($request, $next) {
            $this->projects = Auth::user()->projects;

            return $next($request);
        });
    }
}

1
__constructor () 포인트를 설명해 주셔서 감사합니다. 내 개념을 클리어했다.
— Ashish Choudhary

16

라 라벨 [5.4]

내 해결책은 전역 세션 도우미를 사용하는 것이 었습니다. session ()

그 기능은 $ request-> session () 보다 약간 어렵습니다 .

쓰기 :

session(['key'=>'value']);

미는 :

session()->push('key', $notification);

검색 :

session('key');

이것은 우리가 컨트롤러에서 세션 변수를 작성하고 다른 컨트롤러에서 사용할 때 작동하지 않습니다 :(
— Kamlesh

3

제 경우에는 $ middlewareGroups (app / Http / Kernel.php에서)에 다음 4 줄을 추가했습니다.

'api' => [
    \App\Http\Middleware\EncryptCookies::class,
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \App\Http\Middleware\VerifyCsrfToken::class,
    'throttle:60,1',
    'bindings',
],

중요 : 'throttle'및 'bindings'전에 4 개의 새 줄을 추가해야합니다!

그렇지 않으면 "CSRF 토큰이 일치하지 않음"오류가 발생합니다. 나는 순서가 중요하다는 것을 알기 위해 몇 시간 동안 이것을 고생했습니다.

이를 통해 API의 세션에 액세스 할 수있었습니다. 쿠키 / 세션이 관련 될 때 CSRF가 처리되어야하기 때문에 VerifyCsrfToken도 추가했습니다.


laravel을 사용하여 api를 작성하는 경우 이것이 원하는 답변입니다. :) 또는 추가 -> stateless ()-> redirect ()
— Bobby Ax

2

당신이 사용할 수있는 마십시오 ->stateless()전과 ->redirect(). 그러면 더 이상 세션이 필요하지 않습니다.


0

제 경우에는 단지 반환을하는 것이 었습니다. 내가 세션을 설정 한 기능의 끝에서


0

CSRF를 사용하는 경우 다음을 입력하십시오. 'before'=>'csrf'

귀하의 경우 Route::get('auth/login', ['before'=>'csrf','uses' => 'Auth\AuthController@getLogin', 'as' => 'login']);

자세한 내용은 Laravel 5 문서 보안 보호 경로 를 참조하십시오.


0

laravel 문서에는 없습니다.이 작업을 수행하는 데 한 시간이 걸렸습니다.

내 세션은 "저장"방법을 사용할 때까지 지속되지 않았습니다.

$request->session()->put('lang','en_EN');
$request->session()->save();

0

Laravel 5.3+ 웹 미들웨어 그룹은 RouteServiceProvider에 의해 route / web.php 파일에 자동으로 적용됩니다.

지원되지 않는 순서로 커널 $ middlewareGroups 배열을 수정하지 않는 한 생성자의 일반 종속성으로 요청을 삽입하려고 할 수 있습니다.

다음으로 요청 사용

public function show(Request $request){

}

대신에

public function __construct(Request $request){

}

0

Laravel Sanctum에서이 오류가 발생했습니다. 나는 추가하여 고정 \Illuminate\Session\Middleware\StartSession::class,받는 apiKernel.php에서 미들웨어 그룹,하지만 내 인증 경로가 추가 되었기 때문에이 "일"에서 나중에 생각 api.php대신web.php Laravel 잘못된 인증 가드를 사용 그래서.

이 경로를 여기로 옮겼고 특성 web.php과 함께 제대로 작동하기 시작했습니다 AuthenticatesUsers.php.

Route::group(['middleware' => ['guest', 'throttle:10,5']], function () {
    Route::post('register', 'Auth\RegisterController@register')->name('register');
    Route::post('login', 'Auth\LoginController@login')->name('login');

    Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail');
    Route::post('password/reset', 'Auth\ResetPasswordController@reset');

    Route::post('email/verify/{user}', 'Auth\VerificationController@verify')->name('verification.verify');
    Route::post('email/resend', 'Auth\VerificationController@resend');

    Route::post('oauth/{driver}', 'Auth\OAuthController@redirectToProvider')->name('oauth.redirect');
    Route::get('oauth/{driver}/callback', 'Auth\OAuthController@handleProviderCallback')->name('oauth.callback');
});

Route::post('logout', 'Auth\LoginController@logout')->name('logout');

RequestGuard::logout()존재하지 않음 에 대한 또 다른 이상한 오류가 발생한 후 문제를 파악했습니다 .

내 사용자 지정 인증 경로가 AuthenticatesUsers 특성에서 메서드를 호출하고 있음을 깨달았지만이 Auth::routes()를 수행하는 데 사용하지 않았습니다 . 그런 다음 Laravel은 기본적으로 웹 가드를 사용하며 경로가 routes/web.php.

Sanctum과 분리 된 Vue SPA 앱을 사용하면 내 설정이 다음과 같이 표시됩니다.

Kernel.php

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' => [
        EnsureFrontendRequestsAreStateful::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'throttle:60,1',
    ],
];

참고 : Laravel Sanctum 및 동일한 도메인 Vue SPA를 사용하면 세션 쿠키에 httpOnly 쿠키를 사용하고, me 쿠키를 기억하고 CSRF에 대해 비보안 쿠키를 기억하므로 web인증을 위해 가드를 사용하고 다른 모든 보호 된 JSON 반환 경로는 auth:sanctum미들웨어.

config / auth.php

'defaults' => [
    'guard' => 'web',
    'passwords' => 'users',
],

...

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'token',
        'provider' => 'users',
        'hash' => false,
    ],
],

그런 다음 이와 같은 단위 테스트를 수행 할 수 있습니다. 여기서 비판적 Auth::check()으로 Auth::user(),, 그리고 Auth::logout()최소한의 구성과 최대 사용 AuthenticatesUsers및 RegistersUsers특성 으로 예상대로 작동 합니다.

다음은 몇 가지 로그인 단위 테스트입니다.

TestCase.php

/**
 * Creates and/or returns the designated regular user for unit testing
 *
 * @return \App\User
 */
public function user() : User
{
    $user = User::query()->firstWhere('email', 'test-user@example.com');

    if ($user) {
        return $user;
    }

    // User::generate() is just a wrapper around User::create()
    $user = User::generate('Test User', 'test-user@example.com', self::AUTH_PASSWORD);

    return $user;
}

/**
 * Resets AuthManager state by logging out the user from all auth guards.
 * This is used between unit tests to wipe cached auth state.
 *
 * @param array $guards
 * @return void
 */
protected function resetAuth(array $guards = null) : void
{
    $guards = $guards ?: array_keys(config('auth.guards'));

    foreach ($guards as $guard) {
        $guard = $this->app['auth']->guard($guard);

        if ($guard instanceof SessionGuard) {
            $guard->logout();
        }
    }

    $protectedProperty = new \ReflectionProperty($this->app['auth'], 'guards');
    $protectedProperty->setAccessible(true);
    $protectedProperty->setValue($this->app['auth'], []);
}

LoginTest.php

protected $auth_guard = 'web';

/** @test */
public function it_can_login()
{
    $user = $this->user();

    $this->postJson(route('login'), ['email' => $user->email, 'password' => TestCase::AUTH_PASSWORD])
        ->assertStatus(200)
        ->assertJsonStructure([
            'user' => [
                ...expectedUserFields,
            ],
        ]);

    $this->assertEquals(Auth::check(), true);
    $this->assertEquals(Auth::user()->email, $user->email);
    $this->assertAuthenticated($this->auth_guard);
    $this->assertAuthenticatedAs($user, $this->auth_guard);

    $this->resetAuth();
}

/** @test */
public function it_can_logout()
{
    $this->actingAs($this->user())
        ->postJson(route('logout'))
        ->assertStatus(204);

    $this->assertGuest($this->auth_guard);

    $this->resetAuth();
}

204 OPTIONS 대신 사용자 객체를 반환하도록 Laravel 인증 특성 의 registered및 authenticated메서드를 재정의했습니다 .

public function authenticated(Request $request, User $user)
{
    return response()->json([
        'user' => $user,
    ]);
}

protected function registered(Request $request, User $user)
{
    return response()->json([
        'user' => $user,
    ]);
}

인증 특성에 대한 공급 업체 코드를 살펴보십시오. 손대지 않고 위의 두 가지 방법을 사용할 수 있습니다.

  • vendor / laravel / ui / auth-backend / RegistersUsers.php
  • vendor / laravel / ui / auth-backend / AuthenticatesUsers.php

로그인을위한 Vue SPA의 Vuex 작업은 다음과 같습니다.

async login({ commit }, credentials) {
    try {
        const { data } = await axios.post(route('login'), {
            ...credentials,
            remember: credentials.remember || undefined,
        });

        commit(FETCH_USER_SUCCESS, { user: data.user });
        commit(LOGIN);

        return commit(CLEAR_INTENDED_URL);
    } catch (err) {
        commit(LOGOUT);
        throw new Error(`auth/login# Problem logging user in: ${err}.`);
    }
},

async logout({ commit }) {
    try {
        await axios.post(route('logout'));

        return commit(LOGOUT);
    } catch (err) {
        commit(LOGOUT);

        throw new Error(`auth/logout# Problem logging user out: ${err}.`);
    }
},

Laravel Sanctum + 동일한 도메인 Vue SPA + 인증 단위 테스트가 모두 내 표준에 맞게 작동하는 데 일주일 이상 걸렸으므로 여기에있는 내 답변이 향후 다른 사람들의 시간을 절약하는 데 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.