Как замаскировать номер кредитной карты с помощью регулярного выражения?

Имеется тело POST-запроса:

cc_number=4111111111111111&amount=1500


Для записи в лог требуется привести его к виду

cc_number=XXXXXXXXXXXXXXX&amount=1500


Это можно сделать следующим образом:

$data = preg_replace(
    '/(?<=cc_number=)([^&]+)/e',
    'str_repeat("X", strlen("$1"))',
    $data);



Но, поскольку использование модификатора eval является дурным тоном и в PHP 5.5 отмечено устаревшим, я переделал регулярное выражение с использованием preg_replace_callback:

$data = preg_replace_callback(
    '/(?<=cc_number=)([^&]+)/',
    function ($matches) { return str_repeat('X', strlen($matches[0])); },
    $data);



Однако хотелось бы получить идеальный вариант с использованием чистого regexp.

Что-то вроде

$data = preg_replace($pattern, 'X', $data);


Возможно ли это? Потребуется ли рекурсия?
  • Вопрос задан
  • 6143 просмотра
Решения вопроса 1
@1x1
s/(?<=cc_number=)|\G\d/X/g

Насколько я помню, \G в PHP поддерживается.
Ответ написан
Пригласить эксперта
Ответы на вопрос 9
FilimoniC
@FilimoniC
Вы работаете в сертифицированной по PCI конторе?
Если нет, то вы не имеете права запрашивать CVV\CVC и номер карты. Хранить карту можно в формате «Первые шесть+последние четыре», это разрешено для передачи в открытом виде.

Раз уж так пошло, зачем вам вообще знать длину номера карты? Замените просто на «HIDDEN»
Ответ написан
@Vampiro
Для записи в лог лучше делать примерно так:
cc_number=HIDDEN_CC_NUMBER&amount=1500&CVV=HIDDEN_CVV
А то через пару недель вы будите лепить регулярки для поисков по логам 3-4-12-14-16 последовательных «X»
Ответ написан
@SleepingLion
s/(?<=cc_number=)?(\d)/X/g;
Perl запись, не уверен в конкретной форме записи в PHP.
Ответ написан
Комментировать
@SleepingLion
Попробуйте
$data=preg_replace_all('(?<=cc_number=)?(\d)','X',$data);
Ответ написан
@evgabd Автор вопроса
(удалено, не туда ответил)
Ответ написан
Комментировать
Есть ли возможность обратиться к массиву $_POST?
Если да, то можно попробовать обойтись и без регулярного выражения.

$data = str_replace('cc_number='.$_POST['cc_number'], 'cc_number='.str_repeat('X', strlen($_POST['cc_number'])), $data);
Ответ написан
Комментировать
@Push_Ok
тут был не правильный комментарий
Ответ написан
Комментировать
CodeByZen
@CodeByZen
php, js, my/mssql, sqlite, html, css, it-consult
Исключительно как поиграться. Все-же предпочтительнее с колбеком.

$data[1] = "cc_number=1234567890123456&amount=1500";
$data[2] = "cc_number=12345678901234&amount=1500";
$data[3] = "amount=1500&cc_number=12345678901234&otherNumber=123123123";

$patterns = array ('/\d{16}/','/\d{14}/');
$replace = array ('xxxxxxxxxxxxxxxx','xxxxxxxxxxxxxx');
echo preg_replace($patterns, $replace, $data[1]);
echo "<br>";
echo preg_replace($patterns, $replace, $data[2]);
echo "<br>";
echo preg_replace($patterns, $replace, $data[3]);
Ответ написан
Комментировать
имхо, надежнее так:
<?php
$data = parse_str($data);
 if (isset($data["cc_number"])) {
    $data["cc_number"] = str_repeat("X", strlen($data["cc_number"])); 
} 
$data = http_build_query($data);
?>
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы