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ファイルを編集していません。ビューを作成し、routes.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']);

私はLaravelの経験があまりないので、私の無知を許してください。同じことを尋ねる別の質問があることは承知していますが、どちらの回答もうまくいかないようです。読んでくれてありがとう!

編集:

要求に応じて、ここに私の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

post register.blade.phpコード
Chaudhry Waqas

上記のroutes.phpを単に次のものに置き換えることもできますRoute::controllers([ 'auth' => 'Auth\AuthController', 'password' => 'Auth\PasswordController', ]);
Chaudhry Waqas '24

同じ名前のルートがあり、それは間違っています。それらは異なる名前を持つ必要があります
xAoc

@Adamnick投稿しました。置き換えてみます。
mattrick

セッションドライバーの構成はどのように設定されていますか?
2015

回答:


161

セッション状態、CSRF保護などが必要な場合は、Webミドルウェアを使用する必要があります。

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

2
私は実際にそれを持っています、私は関連するルートを含めていました。
mattrick 2015

ああ、あなたが今何を言っているのか分かります、私はルートを内側に移動し、それはうまくいきました。どうもありがとうございます!
mattrick

@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
Josh

1
あなたの解決策は私の問題を修正します@Waiyl_Karim
Bipul Roy

これでうまくいきました。ルートに反応ルーターを使用しているため、ルートグループが機能しないため、反応フロントエンドを使用しています。
テクサイクリスト

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.例外につながる可能性があります。


私はそれをそのように正確に持っています。まだメッセージが表示されます。StartSessionとShareErrorsFromSessionを$ middleware配列に入れてみました。Storate / framewordも書き込み可能です。(私はWampserver 3を使用しています。)
Meddie

'middleware'を使用=> ['web'、 'youanother.log']、
カマロランバート'29

3
うん!私は馬鹿げていて、(OCDのため)アルファベット順に並べ替えるつもりだったので、アプリが壊れました。残念ながら、私は翌日までテストしなかったので、私はここに行きました。参考までに、5.3の「Web」ミドルウェアグループのデフォルトの順序は、EncryptCookies、AddQueuedCookiesToResponse、StartSession、ShareErrorsFromSession、SubstituteBindings、VerifyCsrfTokenです。
Ixalmida 16

19

問題は、コントローラーの関数内でセッションアクセスしようとすることです __constructor()

Laravel 5.3以降では、アップグレードガイドに記載されているように、これはとにかく機能することを意図していないため、これはもう不可能です。

Laravelの以前のバージョンでは、コントローラーのコンストラクターでセッション変数または認証済みユーザーにアクセスできました。これは、フレームワークの明示的な機能を意図したものではありません。Laravel 5.3では、ミドルウェアがまだ実行されていないため、コントローラーのコンストラクターでセッションまたは認証済みユーザーにアクセスできません。

詳しい背景情報については、テイラーの回答もご覧ください。

回避策

これを引き続き使用したい場合は、アップグレードガイドで説明されているように、ミドルウェアを動的に作成してコンストラクターで実行できます。

別の方法として、コントローラーのコンストラクターでClosureベースのミドルウェアを直接定義できます。この機能を使用する前に、アプリケーションで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でセッションにアクセスできました。VerifyCsrfTokenも追加しました。Cookie/セッションが関係する場合、CSRFを処理する必要があるためです。


laravelでAPIを作成している場合、これはあなたが探している答えです:)または追加-> stateless()-> redirect()
Bobby Ax



0

CSRFを使用している場合は、 'before'=>'csrf'

あなたの場合 Route::get('auth/login', ['before'=>'csrf','uses' => 'Auth\AuthController@getLogin', 'as' => 'login']);

詳細については、Laravel 5のドキュメントをご覧くださいセキュリティルートの保護


0

それはlaravelのドキュメントにはありません、私はこれを達成するために1時間を過ごしました:

「保存」方法を使用するまで、セッションは持続しませんでした...

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

0

Laravel 5.3以降のWebミドルウェアグループは、RouteServiceProviderによって、routes / web.phpファイルに自動的に適用されます。

サポートされていない順序でカーネルの$ middlewareGroups配列を変更しない限り、コンストラクターからの通常の依存関係として要求を挿入しようとしている可能性があります。

リクエストを次のように使用

public function show(Request $request){

}

の代わりに

public function __construct(Request $request){

}

0

Laravel Sanctumでこのエラーが発生しました。Kernel.php \Illuminate\Session\Middleware\StartSession::class,apiミドルウェアグループに追加して修正しましたが、私の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がデフォルトでWebガードを使用していることを認識しました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では、セッションCookieにはhttpOnly Cookieを使用し、CSRFにはCookieと安全でないCookieを覚えている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()最小限の設定との最大の使用に期待通りの仕事AuthenticatesUsersRegistersUsers特徴。

ログインユニットテストの例をいくつか示します。

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();
}

Laravel authトレイトのregisteredauthenticatedメソッドをオーバーライドして、204オプションだけでなくユーザーオブジェクトを返すようにしました。

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

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

authトレイトのベンダーコードを確認してください。それらをそのまま使用することができ、さらに上記の2つの方法を使用できます。

  • 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 + authユニットテストがすべて私の標準に達するまでに1週間以上かかったので、ここでの私の回答が将来他の時間を節約するのに役立つことを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.