2019/02/12 更新
我目前找到核心位置是在Illuminate\Auth\Passwords\DatabaseTokenRepository
目前用下方連結這個方式去做繼承以及覆蓋方法,但是目前卡在答案的 For Laravel 5.2 第4步驟
Overwrite the resolve() method to return a new PasswordBroker with your token repository from step 1
https://stackoverflow.com/questions/40483634/password-reset-table-column-name-override-laravel-5
請教各位大大 這個步驟我該怎麼修改才能運作(我使用 5.5版本)
LARAVEL原本由內建的忘記密碼功能,只需要輸入email即可以傳送忘記密碼連結。
但目前系統需求。
有可能 兩個帳號 但 EMAIL是一樣的,
所以我做了必須去查詢資料表兩個皆符合才會產生token並寄送email
但 password_resets 資料表只有 三個欄位 email 以及 token 和 建立時間 三欄位,所以沒有紀錄 使用者帳號
會有個問題,兩個帳號但email相同
雖然申請 token時 可能用 A帳號 和 email 申請token
但修改密碼時 可以 B帳號 和 email 修改 B帳號的密碼
想請教各位大大!laravel 寫入token的位置在哪邊?
我覺得,你是否找錯方向了。
你找token位置作什麼。
再加上,你居然不知道你的token放在哪?
不是在程式宣告時,就會要求你的資料庫欄位建立了?
還是你想要找其模組的程式位置。
基本而言並不太建議直接改核心模組處理。
最好還是用繼承的方式來處理會比較安全。
正常來說,帳號也最好是email唯一性,如果有非唯一性的需求。
那在忘記密碼操作,就得要多一個值來處理。
依照你目前的情況,除了email之外,還需要帳號做為條件才行。
畢竟你的email並不是唯一性,這是一個麻煩。
yoching 大大你好!確實有Email 非唯一性的需求,
我目前只有在要生產token時會去判斷 user 資料表有沒有 帳號與Email 皆符合的會員,若有才會產生token 並發送email 給該使用者
但是因為「內建」的功能只有 在password_resets 資料表中記錄 token、email、created_at 三個欄位
我是想請問該如何去做如你所說的繼承的動作,
昨天我有找到laravel 框架把這部分寫在哪裡,但想請教大大該如何去做繼承。
原則上還是並不太建議改核心。
不過對於laravel我並不是很熟。但依照所有的框架特性而言。
都因該會有核心擴展的方式處理。
沒有的話,也可以自行去設計一個clasee來去繼承原password物件後。再自行加入自已的處理模式。
真沒辦法不懂到如何去做擴展的話。你就直接改核心吧。
不建議改核心的因素是,框架會有更新版本。如哪天不小心忘了或是有其它人手賤,將它更新版本的話。你所改的核心就又會被還原了。
(至少我自已就笨笨的發生過,差點沒被自已給氣死)
看到這串,我這幾天才開始去看 laravel 的 auth
目前我的想法是自己處理忘記密碼的流程
因為他忘記密碼的 controller 本來就是跟身分驗證分開的
大致上如下:
不知道您現在解決了沒有...,沒關係,我還是留下解答,可供參考。
版本: Laravel 5.5
假定你 User 模型帳號欄位為 username
,因此重設密碼資料表也加此欄位。
database/migrations/2014_10_12_100000_create_password_resets_table.php
...
Schema::create('password_resets', function (Blueprint $table) {
$table->string('username')->index();
$table->string('email');
$table->string('token');
$table->timestamp('created_at')->nullable();
});
...
開始覆寫 Laravel 預設的密碼重設 Controller
app/Http/Controllers/Auth/ForgotPasswordController.php
...
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
class ForgotPasswordController extends Controller
{
...
public function sendResetLinkEmail(Request $request)
{
$this->validateEmail($request);
$response = $this->broker()->sendResetLink(
$request->only('username', 'email')
);
return $response == Password::RESET_LINK_SENT
? $this->sendResetLinkResponse($response)
: $this->sendResetLinkFailedResponse($request, $response);
}
protected function validateEmail(Request $request)
{
$this->validate($request, [
'username' => 'required',
'email' => 'required|email',
]);
}
}
app/Http/Controllers/Auth/PasswordController.php
...
use Illuminate\Http\Request;
class PasswordController extends Controller
{
...
public function showResetForm(Request $request, $token = null)
{
return view('auth.passwords.reset')->with([
'token' => $token,
'username' => $request->username,
'email' => $request->email,
]);
}
protected function credentials(Request $request)
{
return $request->only(
'username', 'email', 'password', 'password_confirmation', 'token'
);
}
protected function rules()
{
return [
'token' => 'required',
'username' => 'required',
'email' => 'required|email',
'password' => 'required|confirmed|min:6',
];
}
protected function sendResetFailedResponse(Request $request, $response)
{
return redirect()->back()
->withInput($request->only('username', 'email'))
->withErrors(['email' => trans($response)]);
}
}
新增相關須覆寫的檔案
PasswordBrokerManager
是生產 PasswordBroker
的 class
app/Passwords/PasswordBrokerManager.php
<?php
namespace App\Passwords;
use Illuminate\Auth\Passwords\PasswordBrokerManager as BasePasswordBrokerManager;
use Illuminate\Support\Str;
class PasswordBrokerManager extends BasePasswordBrokerManager
{
protected function createTokenRepository(array $config)
{
$key = $this->app['config']['app.key'];
if (Str::startsWith($key, 'base64:')) {
$key = base64_decode(substr($key, 7));
}
$connection = $config['connection'] ?? null;
// 讀取複寫的 DatabaseTokenRepository
return new DatabaseTokenRepository(
$this->app['db']->connection($connection),
$this->app['hash'],
$config['table'],
$key,
$config['expire']
);
}
}
DatabaseTokenRepository
是管重設密碼資料表跟 Token 的 class
app/Passwords/DatabaseTokenRepository.php
<?php
namespace App\Passwords;
use App\User;
use Carbon\Carbon;
use Illuminate\Auth\Passwords\DatabaseTokenRepository as BaseDatabaseTokenRepository;
class DatabaseTokenRepository extends BaseDatabaseTokenRepository
{
public function create(User $user)
{
$this->deleteExisting($user);
$token = $this->createNewToken();
$this->getTable()->insert($this->getPayload(
$user->username, $user->email, $token
));
return $token;
}
protected function deleteExisting(User $user)
{
return $this->getTable()->where('username', $user->username)->delete();
}
protected function getPayload($username, $email, $token)
{
return [
'username' => $username,
'email' => $email,
'token' => $this->hasher->make($token),
'created_at' => new Carbon,
];
}
public function exists(User $user, $token)
{
$record = (array) $this->getTable()->where(
'username', $user->username
)->first();
return $record &&
! $this->tokenExpired($record['created_at']) &&
$this->hasher->check($token, $record['token']);
}
}
最後,註冊新的 PasswordBrokerManager
app/Providers/AppServiceProvider.php
...
use App\Passwords\PasswordBrokerManager;
class AppServiceProvider extends ServiceProvider
{
...
public function register()
{
$this->app->singleton('auth.password', function ($app) {
return new PasswordBrokerManager($app);
});
}
}