programing

Larabel - 요청에 따라 세션 저장소가 설정되지 않음

yoursource 2023. 1. 25. 08:53
반응형

Larabel - 요청에 따라 세션 저장소가 설정되지 않음

저는 최근에 새로운 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 파일은 편집하지 않았습니다.뷰를 만들고 루트를 루트에 추가했을 뿐입니다.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']);

저는 라라벨에 대한 경험이 별로 없기 때문에, 저의 무지를 양해해 주십시오.같은 질문을 하는 다른 질문이 있다는 것은 알지만, 어느 대답도 제게는 맞지 않는 것 같습니다.읽어주셔서 감사합니다!

편집:

여기 제 등록기에요.블레이드.요청하신 대로 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

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

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

routes내 the의 web middleware안 .이것을 에 추가해 주세요.$middlewareKernel.php

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

내 경우(Larabel 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',
        ],

Bloem의되지 않는 즉, Cas Bloem을 있는 )web applicable route)는Kernel.middleware의 하는 것이 .

는 " " " 입니다.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,
    ],
];

:VerifyCsrfTokenStartSession이 있다, 될 Session store not set on request.★★★★★★ 。

컨트롤러의 기능 내에서 세션에 액세스하려고 하는 것이 문제일 수 있습니다.

Larabel 5.3+부터는 업그레이드가이드에 기재되어 있는 대로 동작하지 않기 때문에 이 기능은 더 이상 사용할 수 없습니다.

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

자세한 배경 정보는 테일러의 답변도 읽어보십시오.

회피책

그래도 사용할 경우 업그레이드가이드의 설명에 따라 미들웨어를 동적으로 생성하여 컨스트럭터에서 실행할 수 있습니다.

또는 컨트롤러의 컨스트럭터에서 직접 Closure 기반 미들웨어를 정의할 수도 있습니다.이 기능을 사용하기 전에 응용 프로그램이 Larabel 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);
        });
    }
}

라라벨 [5.4]

해결방법은 글로벌세션 도우미 session()을 사용하는 것이었습니다.

기능은 $request->session()보다 조금 어렵습니다.

기입:

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

푸시:

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

취득:

session('key');

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

'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',
],

중요: '스로틀' 및 '바인딩' 앞에 4개의 새 줄을 추가해야 합니다!

그렇지 않으면 "CSRF token not match" 오류가 발생합니다.순서가 중요하다는 걸 깨닫기 위해 몇 시간 동안이나 애를 썼죠

이를 통해 API 세션에 액세스할 수 있습니다.또한 쿠키/세션과 관련된 경우 CSRF를 처리해야 하기 때문에 VerifyCsrfToken을 추가했습니다.

저는 Laravel 7.x를 사용하고 있는데 이 문제가 발생했습니다.다음과 같이 수정했습니다.

kernel.php를 2개의 클래스에 합니다.protected $middleware

\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,

제가 고치다를 붙여서 요.\Illuminate\Session\Middleware\StartSession::class,apiKernel만, 가 Kernel에 되었기 때문에, 있는 것을 .php에 있는 미들웨어 그룹입니다만, 인증 루트가 다음에 추가되었기 때문에, 나중에 이것을 「작동」하고 있는 것을 알게 되었습니다.api.phpweb.php그래서 라라벨은 잘못된 인증가드를 사용하고 있었다.

.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()네, 네, 네.그 후 라라벨이 기본적으로 웹 가드를 사용하고 있다는 것을 깨달았습니다.그것은 루트가 다음 장소에 있어야 한다는 것을 의미합니다.routes/web.php.

Sanctum과 분리된 Vue SPA 앱의 현재 설정은 다음과 같습니다.

커널.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 cookie를 사용하고 CSRF에 대해서는 me cookie 및 unsecure cookie를 사용합니다.webauth 및된 JSON 는 JSON을 사용해야 .auth:sanctum미들웨어

config/auth.displaces

'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특성들.

로그인 유닛 테스트의 몇 가지를 다음에 나타냅니다.

테스트 케이스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();
}

저는 이 명령어를 덮어썼다.registered그리고.authenticated204 OPTIONS가 아닌 사용자 객체를 반환하도록 Laravel auth 특성으로 메서드를 설정합니다.

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 + 인증 유닛 테스트를 모두 제 기준에 맞게 진행하는데 일주일 이상 걸렸습니다.이 답변으로 향후 다른 사용자의 시간을 절약할 수 있기를 바랍니다.

같은 에러가 있었지만, 생텀의 설정이 잘못되어 있었습니다.php 파일.스테이트풀 도메인 블록 내에는 아직 프로덕션 도메인이 아닌 개발 도메인이 있었습니다.

'stateful' => explode(',', env(
        'SANCTUM_STATEFUL_DOMAINS',
        'mydomain.com')
),

똑같은 오류가 발생했습니다.

그게 도움이 됐으면 좋겠어요.
건배.

사용할 수 있습니까?->stateless()이 되기 전에->redirect()그럼 세션은 더 이상 필요하지 않습니다.

sanctum을 사용한SPA 인증 테스트 실행 시 이 문제가 발생합니까?

솔루션:

이 행을 에 추가합니다.tests/TestCase.php:


    public function setUp(): void
    {
        parent::setUp();
        $this->withHeader('origin', config('app.url'));
    }

설명:

SPA 인증에 sanctum을 사용하려면 API 미들웨어에 다음 항목을 추가해야 합니다.

\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class

EnsureFrontendRequestsAreStateful클래스는 정적 메서드가 있는 경우에만 작동합니다.fromFrontendtrue를 반환합니다.

 public static function fromFrontend($request)
    {
        $domain = $request->headers->get('referer') ?: $request->headers->get('origin');

        if (is_null($domain)) {
            return false;
        }
        // ... ommited
}

세션 저장소가 설정되지 않은 이유:$domain유닛 테스트에서 이 메서드가 실행되고 있는 경우는 null이 됩니다.

나의 경우, 그것은 단지 리턴을 넣기 위한 것이었다; 내가 세션을 설정한 기능의 마지막에

CSRF 를 사용하고 있는 경우는, 다음과 같이 입력합니다.'before'=>'csrf'

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

자세한 내용은 Larabel 5 Documentation Security Protecting Routes를 참조하십시오.

라라벨 문서에는 기재되어 있지 않습니다.이것에 1시간이나 걸렸어요.

세션은 "저장" 메서드를 사용할 때까지 지속되지 않았습니다.

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

Larabel 5.3 이상의 웹 미들웨어 그룹은 Route Service Provider에 의해 루트/web.php 파일에 자동으로 적용됩니다.

커널 $middlewareGroups 어레이를 지원되지 않는 순서로 수정하지 않는 한 컨스트럭터로부터의 일반적인 의존관계로서 요구를 주입하려고 합니다.

요청 사용

public function show(Request $request){

}

대신

public function __construct(Request $request){

}

제 경우(Laravel 5.8의 경우)는session.php에 있는 Laravel 프로젝트의 config 파일../[mylaravelapp]/config/디렉토리가 없습니다.다른 에서 누락된 했습니다.config을 사용하다

좋아요, 당신이 직면한 상황은 다음과 같습니다.요청한 요청으로 인스턴스화되지 않은 요청 연결 세션을 호출하고 있습니다.세션 데이터를 사용할 수 있는 요청에 따라 세션을 시작하는 요청에 대해서만 Laravel Session을 설정하면 됩니다.

$request->setLaravelSession(session())

top public/index.displaces를 추가합니다.

ob_start();

공유 호스트를 사용하여 작업합니다.


동작하지 않는 경우는, app/Http/Middleware/TrustProxies 로 이 코드를 변경해 주세요.php

protected $proxies;

로.

protected $proxies = '*';

다음은 나에게 효과가 있다...

사용자가 로그인할 때 세션 만들기

$r->session()->put('usrSession',$r->uName);

여기서 'usrSession'은 내 키이고 'uName'은 요청 변수(실제로 해당 사용자의 고유 사용자 이름)에서 가져옵니다.

사용자가 로그아웃할 때 (모든) 세션 플러시

$r->session()->flush();

언급URL : https://stackoverflow.com/questions/34449770/laravel-session-store-not-set-on-request

반응형