LoginSignup
3
4

More than 5 years have passed since last update.

cakephp3で暗号化したパスワードで認証する方法「絶対やるなよ!」

Last updated at Posted at 2017-01-20
cake version 3.3.11

ここに絶対やるなよ!って書いてありますが、どうしてもやりたい人のために記載しておきます。
https://book.cakephp.org/3.0/ja/core-libraries/security.html

ハッシュでの比較をしない(絶対やるなよ!)パスワードハッシャを作成。

src/Auth/NonPasswordHasher.php
<?php
namespace App\Auth;

use Cake\Auth\AbstractPasswordHasher;

class NonPasswordHasher extends AbstractPasswordHasher
{

    public function hash($password)
    {
           return $password;
    }

    public function check($password, $hashedPassword)
    {
         return $password === $hashedPassword;
    }
}

ユーザマスタのEntityにパスワード暗号・復号化のSetterとGetterを書く。

※Usersテーブルのpasswordフィールドは、大きめのvarcharかtextで。

src/Model/Entity/User.php
<?php

use Cake\Utility\Security;
..
class User extends Entity{
    private $passwordKey = '33 Keta Ijou No Mojiretu Wo Iretene';
//configに宣言してもOK。ほんとはレコード毎に用意しなくちゃ偉い人に怒られます!
    ....
    protected function _getPassword($value)
    {
        if ($value) {
            //↓これ大切!!
            return $this->dirty('password') ?
              $value :
              Security::decrypt(hex2bin($value), $this->passwordKey);
        }
    }
    protected function _setPassword($value)
    {
        if ($value) {
        return bin2hex(Security::encrypt($value, $this->passwordKey))
        }
    }
}

APPコントローラに認証設定

src/Controller/AppController.php
class AppController extends Controller
{
    public function initialize() {

        $this->loadComponent('Auth', [
            'loginAction' => [
                'controller' => 'Users',
                'action' => 'login'
            ],
            'loginRedirect' => [
                'controller' => 'Users',
                'action' => 'index'
            ],
            'authenticate' => [
                'Form' => [
                    'userModel' => 'Users',
                    'fields' => [
                        'username' => 'username',
                        'password' => 'password'
                    ],
                    'passwordHasher' => [
                        'className' => 'Non',//NonPasswordHasherを指定
                    ]
                ]
            ]
        ]);
        $this->Auth->sessionKey = 'Auth.User';
        $this->Auth->allow(['login','logout']);
    }
}

ご注意!!

テーブル挿入・更新時などsetterが呼ばれた後にまさかgetterが呼ばれているとは気づかず、生パスでDB登録されることがわかりましたorz

とりあえずgetterでdirty判定をつけてやれば、登録できましたが、本当にこんなんでいいのか分からないです。
たとえばテーブル挿入・更新時にserializeして、取り出す時はunserializeする時とか正しい方法はどうやるんでしょうね。
詳しい方教えてください。

class UsersController extends AppController
  ...
  public function edit($id = null)
  {
    $user = $this->Users->get($id);
    $user = $this->Users->patchEntity($users, $this->request->data);
    //↑ここでは、ちゃんとUser::_setPasswordが呼ばれて暗号化されてる
    if(!$user->errors()) {
      if ($this->Users->save($user)) {
        //↑ここで$entity->extractからのUser::_getPasswordが呼ばれて復号化されてupdate実行..orz
        ...
      }
    }
  }
}
3
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4