php 防止密码重试,PHP实现虚位密码防偷窥

使用场景

先说一下什么是"虚位密码"

例如微信支付 / 支付宝支付 都有支付密码并且都是六位的长度.

输入密码的时候, 如果旁边的人盯着你输入密码, 密码就极其容易的泄露, 因为密码才六位非常容易记住.

此时虚位密码的作用就来了, 假设支付密码是 147258 , 开启虚位密码之后, 输入 265599465265265914725826526569556 也能验证密码正确, 原因就是这段密码中含有 147258, 而旁观者即使在旁边看了, 也不可能记得住你输入的密码了...

当然, 虚位密码防止了偷窥, 但是也存在一些安全隐患.

例如, 密码是六位的那么六位数字的排序方法无非就是 000000 到 999999, 假如恶意的从 000000 开始排序数字组合进行尝试验证密码, 到最后肯定会验证成功. 那么就需要加一个判断, 验证每次的密码长度及频繁请求, 例如每次密码长度不能大于 64 位, 一分钟最多输入 10 次.

使用 PHP 实现

说一下博主想到的实现原理, 假设如果是交易系统, 设置密码长度都是六位, 那么设置密码(用户注册)的时候将密码进行 哈希 / MD5 / 其他加密 后存入数据库, 验证密码(用户登录)的时候将用户输入的密码进行偏移获取六位, 然后对比数据库存的密码(密码经过了加密, 如果经过了 MD5 则需要将偏移获取到的密码也经过加密后才对比).

博主使用 Laravel 框架简单写写代码实现了一下. 为了简单实现, 不写前端代码, 直接写 API 接口, 然后使用 PostMan 进行请求测试.

首先在 .ENV 文件配置数据库, 例如博主这样的配置(具体要根据自己环境及数据库设置而定):DB_CONNECTION=mysql

DB_HOST=127.0.0.1

DB_PORT=3306

DB_DATABASE=xuwei

DB_USERNAME=root

DB_PASSWORD=root

在 API 的路由文件写下两个路由:Route::post('register', 'Api\AuthController@register');

Route::post('login', 'Api\AuthController@login');

创建 users 表:CREATE TABLE `users` (

`id` INT(11) NOT NULL AUTO_INCREMENT,

`name` VARCHAR(50) NOT NULL DEFAULT '0' COLLATE 'utf8_unicode_ci',

`password` VARCHAR(128) NOT NULL DEFAULT '0' COLLATE 'utf8_unicode_ci',

`length` INT(11) NOT NULL DEFAULT '0',

`created_at` TIMESTAMP NULL DEFAULT NULL,

`updated_at` TIMESTAMP NULL DEFAULT NULL,

PRIMARY KEY (`id`) USING BTREE

)

COMMENT='用户'

COLLATE='utf8_unicode_ci'

ENGINE=InnoDB

;

使用命令创建模型:php artisan make:model Model/User

如果使用 Laravel 自带的用户系统, 则可以直接使用 APP 目录下的 User , 博主是为了方便简单实现, 不使用 Laravel 自带的.

使用命令创建控制器:php artisan make:controller Api/AuthController

在控制器里面写入两个方法:public function register(Request $request)

{

$input = $request->all();

$validator = Validator::make($input, [

'name' => 'required|unique:users|max:50',

'password' => 'required|min:6|max:128',

]);

if ($validator->fails()) {

return response()->json(['msg' => $validator->errors()->first()]);

}

$model_user = new User();

$model_user->name = $input['name'];

$model_user->password = Hash::make($input['password']);

$model_user->length = mb_strlen($input['password']);

$model_user->save();

return response()->json(['msg' => 'success']);

}

public function login(Request $request)

{

$input = $request->all();

$validator = Validator::make($input, [

'name' => 'required|max:50',

'password' => 'required|min:6|max:128',

]);

if ($validator->fails()) {

return response()->json(['msg' => $validator->errors()->first()]);

}

$model_user = new User();

// 博主为了偷懒(快速实现) 直接在这查询 正常应该是写入模型 为后面复用

$row_user = $model_user->where('name', $input['name'])->first();

$password_length = mb_strlen($input['password']);

if (!$row_user || $password_length 

return response()->json(['msg' => 'account or password does not exist']);

}

if ($password_length == $row_user['length']) {

if (!Hash::check($input['password'], $row_user['password'])) {

return response()->json(['msg' => 'account or password does not exist']);

}

// 登录成功 继续操作 这里正常是返回 token 博主就不继续写了...

// code...

return response()->json(['msg' => 'login success']);

}

$offset = 0;

$offset_times = $password_length - $row_user['length'] + 1;

for ($i = 0; $i 

$password = mb_substr($input['password'], $offset, $row_user['length']);

$offset++;

if (Hash::check($password, $row_user['password'])) {

// 登录成功 继续操作 这里正常是返回 token 博主就不继续写了...

// code...

return response()->json(['msg' => 'login success']);

}

}

return response()->json(['msg' => 'account or password does not exist']);

}

别忘了需要引入:use Illuminate\Support\Facades\Validator;

use Illuminate\Support\Facades\Hash;

use App\Model\User;  // 这个应该不用多说了

接下来测试下注册:

watermark

注册是成功的, 这里说一下, 注册方法里面计算了一下密码长度, 这是为了登录(验证密码)的时候可以偏移组合密码, 不然不知道密码真实的长度就没办法做虚位了, 除非定死每个人的密码只能设置为 XX 位.

测试正常登录:

watermark

测试虚位密码登录:

watermark

为了验证是否正确验证(将虚位密码中的 147258 去掉):

watermark

至此, 虚位密码已经成功实现.

博主限制的长度是 128 位, 其实可以减少到 64 位, 另外博主的实现方法没限制请求频率, 如果使用 Laravel 可以通过中间件实现限制.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值