我使用的是Laravel 4.2。
我正在创建一个注册表,用户在其中填写他们的姓名和电子邮件地址,成功验证后,这些地址将作为加密值存储在数据库中,其中Crypt::encrypt()
用于电子邮件字段,Hash::make()
用于密码字段。
我的问题是为电子邮件过滤器生成一个验证规则,该规则需要对每个注册的用户都是唯一的。
由于Crypt::encrypt()
和Hash::make()
每次都为同一个输入字符串生成随机字符串,即使它们可能相同,我似乎也无法将输入值与数据库中的值匹配?
当电子邮件地址(或其他字段)必须始终在数据库中加密时,验证其唯一性的最佳做法是什么?
此外,我将如何修改我的Auth::attempt()
功能以适应电子邮件字段已加密的事实?
这就是实现自定义验证规则的原因。此服务有两种方法:传递和消息。方法传递获取两个变量:$attributes(获取字段的值进行验证)和$value(获取字段值),并返回true或false。Te方法消息在失败的情况下检索消息。
在我提到的客户端示例中,遵循以下步骤:
php artisan make:rule ValidateFieldsClients
在composer创建ValidateFieldsClients的类中,我必须声明一个方法来验证pass中的字段,我使用这个方法来验证这两个字段(code_client和电子邮件)。
接下来,我在视图中完成反方法消息,以向用户检索问题
另外,我声明了一个属性$field,以确定它有错误的字段
ValidateFieldsClients类示例:
/***/class ValidateFieldsClients implements Rule{protected $field; /** * Create a new rule instance. * * @return void */ public function __construct() { } /** * Determine if the validation rule passes. * * @param string $attribute * @param mixed $value * @return bool */ public function passes($attribute, $value) { $clients = client::all(); $this->field = $attribute; foreach ($clients as $client ) { if ($value == Crypt::decryptString($client->$attribute)) return false; } return true; } /** * Get the validation error message. * * @return string */ public function message() { return strtoupper($this->field).' exists, check.'; } }
然后为了验证,我使用表单请求验证(https://laravel.com/docs/8.x/validation#form-请求验证)
php artisan make:request ClientRequest
在最近创建的类的验证方法中:
class ClientRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'code_client'=> ['required', new ValidateFieldsClients], 'email'=>['required', new ValidateFieldsClients], ]; }
最后在控制器中:
public function store(ClientRequest $request) { $clientRequest = $request->validated(); foreach ($clientRequest as $key => $client) { $encryptedClient[$key] = Crypt::encryptString($client); }; client::create($encryptedClient+ [ 'idorga' => 1, 'idcrea' => 1, 'idmodifica' => 1 ]); return redirect('clientes/create')->with('success', 'Registro creado correctamente'); //return redirect('cuadros')->with('success', 'Registro exitoso!'); }
我假设您使用Crypt::encrypt()
加密了电子邮件地址,并且由于该方法每次都会生成不同的IV,因此结果是不可比较的。
当你需要一个可搜索/可比较的字段时,你不能使用IV(加密)或salt(哈希)。解决这个问题的一种方法是使用电子邮件和服务器端密钥作为输入,但不使用salt来计算HMAC。您可以将此哈希与加密电子邮件并排存储。
如果攻击者知道服务器端的密钥,他将能够强行使用电子邮件哈希,但随后他可能也知道加密密钥,并可以直接解密电子邮件。请注意,这不适用于密码,因为它们应该存储为不可检索的。