php - 如何使用 Laravel 对页面进行密码保护?
问题描述
我正在尝试在 Laravel 中设置一些需要密码才能查看的页面。
页面是一个模型,称为 Page。
每个页面都有一个关联的密码,存储在 Pages 数据库表中。
架构
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
时间戳。
推荐阅读
- node.js - 如何解决代码更改未反映在 PM2 中的问题?
- amazon - Amazon Seller Central API::GetOrders 在使用 OrderStatuses 查询参数调用时返回不正确的订单
- java - 安装黑名单应用时如何阻止应用访问互联网
- amazon-web-services - 删除消息时 SQS 轮询失败
- c# - .Net 不在 SOAP 中序列化枚举
- jmeter - 打开jmeter时显示白屏,任何人都可以帮助解决这个错误
- python - 如何防止标签编码器将 y 列添加到 X numpy.array
- python - 如何仅在调用 django python 时在后台运行函数?
- azure-devops - 如何使用在组织级别安装的扩展找到 Azure DevOps 项目
- c# - 如果存在 UseIdentityServer,是否需要 AddAuthentication 和 AddAuthorization?