【问题标题】:setPasswordAttribute interfering with password reset (Laravel 5.2)setPasswordAttribute 干扰密码重置(Laravel 5.2)
【发布时间】:2016-07-04 07:25:32
【问题描述】:

我一直在研究密码重置功能,它几乎可以完全正常工作,除非我输入新密码登录被拒绝。

我相信我在 User.php 文件中的 setPasswordAttribute() 函数干扰了密码重置,因为当我将其注释掉时,重置工作正常。我不确定我应该如何修改此函数以使重置生效。

这是我的 setPasswordAttribute() 函数

 public function setPasswordAttribute($value)
{
    $this->attributes['password'] = bcrypt($value);
}

这是我的密码重置代码。我只是遵循 laravel 文档。

路线。

Route::get('password/email', 'Auth\PasswordController@getEmail');
Route::post('password/email', 'Auth\PasswordController@postEmail');
Route::get('password/reset/{token}', 'Auth\PasswordController@getReset');
Route::post('password/reset', 'Auth\PasswordController@postReset');

电子邮件视图

    <form method="POST" action="/password/email">
    {!! csrf_field() !!}

    @if (count($errors) > 0)
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    @endif

    <div>
        Email
        <input type="email" name="email" value="{{ old('email') }}">
    </div>

    <div>
        <button type="submit">
            Send Password Reset Link
        </button>
    </div>
</form>

重置视图

<form method="POST" action="/password/reset">
{!! csrf_field() !!}
<input type="hidden" name="token" value="{{ $token }}">

@if (count($errors) > 0)
    <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
@endif

<div>
    Email
    <input type="email" name="email" value="{{ old('email') }}">
</div>

<div>
    Password
    <input type="password" name="password">
</div>

<div>
    Confirm Password
    <input type="password" name="password_confirmation">
</div>

<div>
    <button type="submit">
        Reset Password
    </button>
</div>

密码控制器使用的特征。

/**
 * Get the name of the guest middleware.
 *
 * @return string
 */
protected function guestMiddleware()
{
    $guard = $this->getGuard();

    return $guard ? 'guest:'.$guard : 'guest';
}

/**
 * Display the form to request a password reset link.
 *
 * @return \Illuminate\Http\Response
 */
public function getEmail()
{
    return $this->showLinkRequestForm();
}

/**
 * Display the form to request a password reset link.
 *
 * @return \Illuminate\Http\Response
 */
public function showLinkRequestForm()
{
    if (property_exists($this, 'linkRequestView')) {
        return view($this->linkRequestView);
    }

    if (view()->exists('auth.passwords.email')) {
        return view('auth.passwords.email');
    }

    return view('auth.password');
}

/**
 * Send a reset link to the given user.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function postEmail(Request $request)
{
    return $this->sendResetLinkEmail($request);
}

/**
 * Send a reset link to the given user.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function sendResetLinkEmail(Request $request)
{
    $this->validateSendResetLinkEmail($request);

    $broker = $this->getBroker();

    $response = Password::broker($broker)->sendResetLink(
        $this->getSendResetLinkEmailCredentials($request),
        $this->resetEmailBuilder()
    );

    switch ($response) {
        case Password::RESET_LINK_SENT:
            return $this->getSendResetLinkEmailSuccessResponse($response);
        case Password::INVALID_USER:
        default:
            return $this->getSendResetLinkEmailFailureResponse($response);
    }
}

/**
 * Validate the request of sending reset link.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return void
 */
protected function validateSendResetLinkEmail(Request $request)
{
    $this->validate($request, ['email' => 'required|email']);
}

/**
 * Get the needed credentials for sending the reset link.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
protected function getSendResetLinkEmailCredentials(Request $request)
{
    return $request->only('email');
}

/**
 * Get the Closure which is used to build the password reset email message.
 *
 * @return \Closure
 */
protected function resetEmailBuilder()
{
    return function (Message $message) {
        $message->subject($this->getEmailSubject());
    };
}

/**
 * Get the e-mail subject line to be used for the reset link email.
 *
 * @return string
 */
protected function getEmailSubject()
{
    return property_exists($this, 'subject') ? $this->subject : 'Your Password Reset Link';
}

/**
 * Get the response for after the reset link has been successfully sent.
 *
 * @param  string  $response
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function getSendResetLinkEmailSuccessResponse($response)
{
    return redirect()->back()->with('status', trans($response));
}

/**
 * Get the response for after the reset link could not be sent.
 *
 * @param  string  $response
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function getSendResetLinkEmailFailureResponse($response)
{
    return redirect()->back()->withErrors(['email' => trans($response)]);
}

/**
 * Display the password reset view for the given token.
 *
 * If no token is present, display the link request form.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string|null  $token
 * @return \Illuminate\Http\Response
 */
public function getReset(Request $request, $token = null)
{
    return $this->showResetForm($request, $token);
}

/**
 * Display the password reset view for the given token.
 *
 * If no token is present, display the link request form.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string|null  $token
 * @return \Illuminate\Http\Response
 */
public function showResetForm(Request $request, $token = null)
{
    if (is_null($token)) {
        return $this->getEmail();
    }

    $email = $request->input('email');

    if (property_exists($this, 'resetView')) {
        return view($this->resetView)->with(compact('token', 'email'));
    }

    if (view()->exists('auth.passwords.reset')) {
        return view('auth.passwords.reset')->with(compact('token', 'email'));
    }

    return view('auth.reset')->with(compact('token', 'email'));
}

/**
 * Reset the given user's password.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function postReset(Request $request)
{
    return $this->reset($request);
}

/**
 * Reset the given user's password.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function reset(Request $request)
{
    $this->validate(
        $request,
        $this->getResetValidationRules(),
        $this->getResetValidationMessages(),
        $this->getResetValidationCustomAttributes()
    );

    $credentials = $this->getResetCredentials($request);

    $broker = $this->getBroker();

    $response = Password::broker($broker)->reset($credentials, function ($user, $password) {
        $this->resetPassword($user, $password);
    });

    switch ($response) {
        case Password::PASSWORD_RESET:
            return $this->getResetSuccessResponse($response);
        default:
            return $this->getResetFailureResponse($request, $response);
    }
}

/**
 * Get the password reset validation rules.
 *
 * @return array
 */
protected function getResetValidationRules()
{
    return [
        'token' => 'required',
        'email' => 'required|email',
        'password' => 'required|confirmed|min:6',
    ];
}

/**
 * Get the password reset validation messages.
 *
 * @return array
 */
protected function getResetValidationMessages()
{
    return [];
}

/**
 * Get the password reset validation custom attributes.
 *
 * @return array
 */
protected function getResetValidationCustomAttributes()
{
    return [];
}

/**
 * Get the password reset credentials from the request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
protected function getResetCredentials(Request $request)
{
    return $request->only(
        'email', 'password', 'password_confirmation', 'token'
    );
}

/**
 * Reset the given user's password.
 *
 * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
 * @param  string  $password
 * @return void
 */
protected function resetPassword($user, $password)
{
    $user->forceFill([
        'password' => bcrypt($password),
        'remember_token' => Str::random(60),
    ])->save();

    Auth::guard($this->getGuard())->login($user);
}

/**
 * Get the response for after a successful password reset.
 *
 * @param  string  $response
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function getResetSuccessResponse($response)
{
    return redirect($this->redirectPath())->with('status', trans($response));
}

/**
 * Get the response for after a failing password reset.
 *
 * @param  Request  $request
 * @param  string  $response
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function getResetFailureResponse(Request $request, $response)
{
    return redirect()->back()
        ->withInput($request->only('email'))
        ->withErrors(['email' => trans($response)]);
}

/**
 * Get the broker to be used during password reset.
 *
 * @return string|null
 */
public function getBroker()
{
    return property_exists($this, 'broker') ? $this->broker : null;
}

/**
 * Get the guard to be used during password reset.
 *
 * @return string|null
 */
protected function getGuard()
{
    return property_exists($this, 'guard') ? $this->guard : null;
}

【问题讨论】:

  • 您尝试注册了吗?你也不应该注册,因为 AuthController 中的 create 方法也会加密密码。

标签: php laravel laravel-5.2


【解决方案1】:

它不起作用,因为密码在 resetPassword() 中被哈希两次。

要修复它,请覆盖 PasswordController.php 中的函数

protected function resetPassword($user, $password)
{
    $user->forceFill([
        'password' => $password, //Removed bcrypt
        'remember_token' => Str::random(60),
    ])->save();

    Auth::guard($this->getGuard())->login($user);
}

【讨论】:

    【解决方案2】:

    您对密码进行了两次哈希处理,这就是它不起作用的原因。你写的PasswordController应该是这样的

        /**
     * Get the name of the guest middleware.
     *
     * @return string
     */
    protected function guestMiddleware()
    {
        $guard = $this->getGuard();
    
        return $guard ? 'guest:'.$guard : 'guest';
    }
    
    /**
     * Display the form to request a password reset link.
     *
     * @return \Illuminate\Http\Response
     */
    public function getEmail()
    {
        return $this->showLinkRequestForm();
    }
    
    /**
     * Display the form to request a password reset link.
     *
     * @return \Illuminate\Http\Response
     */
    public function showLinkRequestForm()
    {
        if (property_exists($this, 'linkRequestView')) {
            return view($this->linkRequestView);
        }
    
        if (view()->exists('auth.passwords.email')) {
            return view('auth.passwords.email');
        }
    
        return view('auth.password');
    }
    
    /**
     * Send a reset link to the given user.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function postEmail(Request $request)
    {
        return $this->sendResetLinkEmail($request);
    }
    
    /**
     * Send a reset link to the given user.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function sendResetLinkEmail(Request $request)
    {
        $this->validateSendResetLinkEmail($request);
    
        $broker = $this->getBroker();
    
        $response = Password::broker($broker)->sendResetLink(
            $this->getSendResetLinkEmailCredentials($request),
            $this->resetEmailBuilder()
        );
    
        switch ($response) {
            case Password::RESET_LINK_SENT:
                return $this->getSendResetLinkEmailSuccessResponse($response);
            case Password::INVALID_USER:
            default:
                return $this->getSendResetLinkEmailFailureResponse($response);
        }
    }
    
    /**
     * Validate the request of sending reset link.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return void
     */
    protected function validateSendResetLinkEmail(Request $request)
    {
        $this->validate($request, ['email' => 'required|email']);
    }
    
    /**
     * Get the needed credentials for sending the reset link.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function getSendResetLinkEmailCredentials(Request $request)
    {
        return $request->only('email');
    }
    
    /**
     * Get the Closure which is used to build the password reset email message.
     *
     * @return \Closure
     */
    protected function resetEmailBuilder()
    {
        return function (Message $message) {
            $message->subject($this->getEmailSubject());
        };
    }
    
    /**
     * Get the e-mail subject line to be used for the reset link email.
     *
     * @return string
     */
    protected function getEmailSubject()
    {
        return property_exists($this, 'subject') ? $this->subject : 'Your Password Reset Link';
    }
    
    /**
     * Get the response for after the reset link has been successfully sent.
     *
     * @param  string  $response
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function getSendResetLinkEmailSuccessResponse($response)
    {
        return redirect()->back()->with('status', trans($response));
    }
    
    /**
     * Get the response for after the reset link could not be sent.
     *
     * @param  string  $response
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function getSendResetLinkEmailFailureResponse($response)
    {
        return redirect()->back()->withErrors(['email' => trans($response)]);
    }
    
    /**
     * Display the password reset view for the given token.
     *
     * If no token is present, display the link request form.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string|null  $token
     * @return \Illuminate\Http\Response
     */
    public function getReset(Request $request, $token = null)
    {
        return $this->showResetForm($request, $token);
    }
    
    /**
     * Display the password reset view for the given token.
     *
     * If no token is present, display the link request form.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string|null  $token
     * @return \Illuminate\Http\Response
     */
    public function showResetForm(Request $request, $token = null)
    {
        if (is_null($token)) {
            return $this->getEmail();
        }
    
        $email = $request->input('email');
    
        if (property_exists($this, 'resetView')) {
            return view($this->resetView)->with(compact('token', 'email'));
        }
    
        if (view()->exists('auth.passwords.reset')) {
            return view('auth.passwords.reset')->with(compact('token', 'email'));
        }
    
        return view('auth.reset')->with(compact('token', 'email'));
    }
    
    /**
     * Reset the given user's password.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function postReset(Request $request)
    {
        return $this->reset($request);
    }
    
    /**
     * Reset the given user's password.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function reset(Request $request)
    {
        $this->validate(
            $request,
            $this->getResetValidationRules(),
            $this->getResetValidationMessages(),
            $this->getResetValidationCustomAttributes()
        );
    
        $credentials = $this->getResetCredentials($request);
    
        $broker = $this->getBroker();
    
        $response = Password::broker($broker)->reset($credentials, function ($user, $password) {
            $this->resetPassword($user, $password);
        });
    
        switch ($response) {
            case Password::PASSWORD_RESET:
                return $this->getResetSuccessResponse($response);
            default:
                return $this->getResetFailureResponse($request, $response);
        }
    }
    
    /**
     * Get the password reset validation rules.
     *
     * @return array
     */
    protected function getResetValidationRules()
    {
        return [
            'token' => 'required',
            'email' => 'required|email',
            'password' => 'required|confirmed|min:6',
        ];
    }
    
    /**
     * Get the password reset validation messages.
     *
     * @return array
     */
    protected function getResetValidationMessages()
    {
        return [];
    }
    
    /**
     * Get the password reset validation custom attributes.
     *
     * @return array
     */
    protected function getResetValidationCustomAttributes()
    {
        return [];
    }
    
    /**
     * Get the password reset credentials from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function getResetCredentials(Request $request)
    {
        return $request->only(
            'email', 'password', 'password_confirmation', 'token'
        );
    }
    
    /**
     * Reset the given user's password.
     *
     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
     * @param  string  $password
     * @return void
     */
    protected function resetPassword($user, $password)
    {
        $user->forceFill([
            'password' => $password,
            'remember_token' => Str::random(60),
        ])->save();
    
        Auth::guard($this->getGuard())->login($user);
    }
    
    /**
     * Get the response for after a successful password reset.
     *
     * @param  string  $response
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function getResetSuccessResponse($response)
    {
        return redirect($this->redirectPath())->with('status', trans($response));
    }
    
    /**
     * Get the response for after a failing password reset.
     *
     * @param  Request  $request
     * @param  string  $response
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function getResetFailureResponse(Request $request, $response)
    {
        return redirect()->back()
            ->withInput($request->only('email'))
            ->withErrors(['email' => trans($response)]);
    }
    
    /**
     * Get the broker to be used during password reset.
     *
     * @return string|null
     */
    public function getBroker()
    {
        return property_exists($this, 'broker') ? $this->broker : null;
    }
    
    /**
     * Get the guard to be used during password reset.
     *
     * @return string|null
     */
    protected function getGuard()
    {
        return property_exists($this, 'guard') ? $this->guard : null;
    }
    

    这可能会解决您的问题。

    【讨论】:

    • PasswordController 不需要所有的代码。只有resetPassword 被覆盖。
    • 我只是重写了'PasswordController',这样用户就可以复制我的代码并运行到他的机器上。
    猜你喜欢
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 2016-09-25
    相关资源
    最近更新 更多