簡體   English   中英

如何使用 Laravel 密碼保護頁面?

[英]How to password protect a page with Laravel?

我正在嘗試在 Laravel 中設置一些需要密碼才能查看的頁面。

頁面是一個模型,稱為頁面。

每個頁面都有一個關聯的密碼,存儲在頁面數據庫表中。

架構

Schema::create('pages', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('name');
    $table->string('client_id');
    $table->string('url');
    $table->text('content');
    $table->string('password');
    $table->timestamps();
});

我有一條路線,例如Route::get('/page/{url}', 'PageController@index')->middleware('gate'); 這將顯示“頁面”,它只是一個刀片/vue 文件,其中包含注入模板的特定信息。 這些頁面允許用戶通過 AJAX 上傳文件。

目前,我為實際的身份驗證部分創建了一些中間件。

中間件

public function handle($request, Closure $next)
{
    if(Cookie::get($request->route('url'))){
        return $next($request);
    }
    session(['page' => $request->route('url')]);
    return redirect()->route('gate',['page'=> $request->route('url')]);
}

公共控制器.php

public function gate_check(Request $request)
{
  //this part just ensures the correct page is loaded after being authed
  $past = parse_url($request->session()->get('_previous')['url']);

  if(array_key_exists('query', $past)){
    $page = str_replace('page=', '',parse_url($request->session()->get('_previous')['url'])['query']);

    $stored_password = Page::where('url', $page)->first()->password;
    $password = $request->password;  

    if($password === $stored_password){
      //if password matches, then redirect to that page
      return redirect()->route('page', session('page'));
    } else {
      //else redirect them back to the login page to try again
      return back();
    }
  } else {
    //if there is no page information that use should go to, just send them to google instead
    return redirect('https://google.com');
  }

}

中間件/身份驗證方法的想法是將用戶重定向到未經過身份驗證的登錄頁面。 此登錄頁面僅包含您需要輸入的密碼。

一旦他們進入,我就設置了一個 cookie,這樣他們就可以繞過重新登錄的過程。

我現在意識到這是不安全的,或者至少看起來是這樣,因為客戶端/用戶可以操縱 cookie 的到期時間 - 導致他們能夠永遠保持登錄狀態。

只想重申上述方法有效,但不安全。 我還應該重申,這些“頁面”允許用戶通過 ajax 上傳文件。 並且只有當用戶在特定頁面上時才允許上傳,例如通過 CSRF。

我需要一種安全的方式來密碼保護頁面,可以自定義“會話”的到期時間。 我還需要一種在不使用 AJAX 刷新頁面的情況下“刷新”或“擴展”活動會話的方法,以便用戶可以停留在上傳頁面上(以防上傳需要很長時間)。

具有用戶名/電子郵件和密碼的標准用戶帳戶不適用。 只有密碼。

Wordpress 內置了這個功能 - 為什么用 Laravel 做看起來如此微不足道的事情這么難?

你會如何處理這個問題?

這就是我會做的:

具有用戶名/電子郵件和密碼的標准用戶帳戶不適用。 只有密碼。

對於非標准用戶帳戶,您可以自己在輸入的每個正確密碼上生成一個訪客 ID,並將其存儲到會話中。

Schema::create('active_guests', function (Blueprint $table) {
$table->bigIncrements('guest_id'); # on your model specify this as primary key
$table->unsignedBigInteger('page_id'); # authorized for after validating password
$table->integer('expires_at'); # store it as unixtimestamp now()->addHours(5)->timestamp
$table->timestamps();
});

您可以通過這種方式查詢以檢查身份驗證

$page = Page::where('url', $page)->where('password', $password)->first();
if ($page) {
ActiveGuest::updateOrcreate(....);
Session::get('pages_authorized_for', [array_of_pages]);
// push the new page id and store it back to session as array
} else {
// incorrect password or page removed
}

只想重申上述方法有效,但不安全。 我還應該重申,這些“頁面”允許用戶通過 ajax 上傳文件。 並且只有當用戶在特定頁面上時才允許上傳,例如通過 CSRF。

我需要一種安全的方式來密碼保護頁面,可以自定義“會話”的到期時間。 我還需要一種在不使用 AJAX 刷新頁面的情況下“刷新”或“擴展”活動會話的方法,以便用戶可以停留在上傳頁面上(以防上傳需要很長時間)。

從您的 ajax 中,您可以增加active_guests表上的到期時間。

如需延長上傳時間,您可以添加last_activity作為時間戳。

編寫自己的身份驗證解決方案很困難。 是否可以重新考慮保護頁面的策略?

如果您能夠遵循基於普通用戶的身份驗證策略,那么您可以利用 Laravel 提供的身份驗證服務,它還可以通過消除您可能遇到的邊緣情況來提供其他優勢。

根據您必須驗證的頁面數量,可以將每個頁面的布爾列添加到用戶表中,或者您可以添加類型為 sting 的“頁面”列,其中包含該用戶有權訪問的頁面列表。

然后可以使用 Laravel 授權策略 ( https://laravel.com/docs/6.x/authorization#creating-policies ) 來強制訪問頁面,並且在 Blade 中,您可以使用該策略來構建頁面的動態列表可供用戶使用( https://laravel.com/docs/6.x/authorization#via-blade-templates

其他好處: - 避免為每個頁面共享一個通用密碼。 您可能不知道密碼是否已在授權用戶組之外共享,更改密碼會影響頁面的所有用戶。

  • 如果用戶忘記密碼,那么他們可以使用標准的密碼重置過程。

  • 如果用戶可以訪問多個頁面,則用戶不需要跟蹤多個密碼,而當一個域有多個密碼時,密碼管理器會遇到困難。

  • 通過提供列出特定用戶可用的所有頁面的主頁,了解用戶可以訪問哪些頁面可以幫助提高可用性。

使用會話而不是 cookie。 中間件的變化:

public function handle($request, Closure $next)
{   

    if(in_array($request->route('url'), session('pages',[]))){
       return $next($request);
    }

    session(["current-page"=>$request->route('url')]);
    return redirect()->route('gate');
}

控制器的變化:

public function gate_check(Request $request)
{
    if(session()->has("current-page")){

        $stored_password = Page::where('url', session("current-page"))
           ->first()->password;

        if($request->password === $stored_password){
            $pages = session("pages",[]);
            array_push($pages, session("current-page"));
            session(["pages"=> $pages]);
            //if password matches, then redirect to that page
            return redirect()->route('page', ["url" => session("current-page")]);
        } else {
            //else redirect them back to the login page to try again
            return back();
        }
    } else {
        //if there is no page information that use should go to, just send them 
        // to google instead
        return redirect('https://google.com');
    }
}

您可以使用 MD5 或 SHA256 或 SHA512 算法將哈希密碼保存在數據庫中。 有關 session 的更多信息,請研究 Laravel session 文檔,請單擊此處

您可以配置session.php ,位置:根文件夾/config/session.php 例如當用戶關閉瀏覽器然后破壞會話時。

'expire_on_close' => true 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM