Проверка пароля на соответствие требованиям

Доброго дня, господа форумчане. Возникла необходимость проверки пароля на соответствие требованиям информационной безопасности. А именно: 1. Установлена периодичность смены пароля в 90 дней; 2. Пароль должен быть длинной не менее восьми символов; 3. Пароль должен содержать хотя-бы одну заглавную букву; 4. Пароль должен содержать хотя-бы одну цифру; 5. Пароль должен содержать хотя-бы один спецсимвол: !, @, #, $, %, ^, :, &, *, (, ), -, +, _ С первыми двумя пунктами все понятно, но вот с другими тупняк. Я накидал функцию:
function TMainF.CheckPass(s :String; tag :Integer):Boolean;
var
lazha   :Boolean;
i       :Word;
begin
lazha:=false;
case tag of
0:
begin
for I := 1 to Length(S) do
  if (s[i] in ['А'..'Я', 'Ё', 'A'..'Z']) Then
  Begin
  lazha:=False;
  Break
  End
  else
  lazha:=True;
end;//0
1:
begin
 for I := 1 to Length(S) do
  if (s[i] in ['0'..'9'])Then
  Begin
  lazha:=False;
  Break
  End
  else
  lazha:=True;
end;//1
2:
begin
 for I := 1 to Length(S) do
  if (s[i] in ['!','@', '#', '$', '%', '^', ':', '&', '*', '(', ')', '-', '+','_']) Then
  Begin
  lazha:=False;
  Break
  End
  else
  lazha:=True;
end;//2
end;//case
Result:=lazha;
end;
и соответственно вызываю ее
var
w,n,s :Boolean;
st    :String;
begin
st:='Пароль не отвечает требованиям информационной безопасности!' +#10#13+
                         'Пароль должен быть не менее 8 символов, ' +#10#13+
                         'содержать заглавные буквы, ' +#10#13+
                         'цифры от 0 до 9, '+#10#13+
                         'а так же спецсимволы: !, @, #, $, %, ^, :, &, *, (, ), -, +, _';
if Length(Trim(pass1.Text))<8 then
  raise Exception.Create(st);
w:=MainF.CheckPass(Pass1.Text,0);//на наличие заглавных букв
n:=MainF.CheckPass(Pass1.Text,1);//наличие цифр
s:=MainF.CheckPass(Pass1.Text,2);//наличие спецсимволов
if (w) or (n) or (s) then
  raise Exception.Create(st);
end;
Приходится вызывать её трижды. Чую пятой точкой, что есть способ практичнее, но вот допереть не могу.
14 ответов

С первыми двумя пунктами все понятно, но вот с другими тупняк. Я накидал функцию:
то есть как найти в тексте заглавную букву ты понял, а как найти любую цифру -нет? очень странно5 - составь массив из символов и проверяй их наличие
Приходится вызывать её трижды. Чую пятой точкой, что есть способ практичнее, но вот допереть не могу.
напиши другую функцию которая будет вызывать твою сколько нужно раз


С первыми двумя пунктами все понятно
1. Установлена периодичность смены пароля в 90 дней;
Вам и с этим пунктом понятно? Мне вот не совсем... Как и где Вы собираетесь это делать...


Вам и с этим пунктом понятно? Мне вот не совсем... Как и где Вы собираетесь это делать..
В таблицу добавил поле с датой. После аутентификации пользователя идет проверка даты. Если меньше или равна текущей - меняем пароль.
то есть как найти в тексте заглавную букву ты понял, а как найти любую цифру -нет?
Все у меня ищет. И буквы, и цифры, и символы. Код же привел.
if (s[i] in ['А'..'Я', 'Ё', 'A'..'Z'])
if (s[i] in ['0'..'9']) Then
if (s[i] in ['!','@', '#', '$', '%', '^', ':', '&', '*', '(', ')', '-', '+','_']) Then
Вопрос был в исследовании возможности упрощения функции. Мне вот ничего другого в голову не пришло. Поэтому и спрашиваю, может у кого есть идеи получше моей...


возможности упрощения функции
Вот так можно...
function CheckPsw(_text: String): boolean;
var i, Summ: integer;
    A: array [1..5] of integer;
begin
 for i := 1 to 5 do
  A[i] := 0;
 if Length(_text) >= 8 then A[1] := 1;
 for i := 1 to Length(_text) do
  begin
   if (_text[i] in ['а'..'я', 'ё', 'a'..'z']) then A[2] := 1;
   if (_text[i] in ['А'..'Я', 'Ё', 'A'..'Z']) then A[3] := 1;
   if (_text[i] in ['0'..'9']) then A[4] := 1;
   if (_text[i] in ['!','@', '#', '$', '%', '^', ':', '&', '*', '(', ')', '-', '+','_']) then A[5] := 1;
  end;
 Summ := 0;
 for i := 1 to 5 do
  Summ := Summ + A[i];
 result := Summ = 5;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
 if CheckPsw(Edit1.Text) then ShowMessage('y') else ShowMessage('no');
end;
Но учтите, что на новых юникодных версиях это работать не будет/будет, но с косяками...


D1973, спасибо. Так получше будет.


Все у меня ищет.
С первыми двумя пунктами все понятно, но вот с другими тупняк
не понятно
if (_text[i] in ['а'..'я', 'ё', 'a'..'z']) then A[2] := 1;
есть же CharInSet() да и массив лишний


есть же CharInSet()
Я пробовал с ним. У меня ошибку выдает. Delphi XE5.
if CharInSet(s,['A'..'Z']) then lazha:=False;
[dcc32 Error] MainForm.pas(115): E2250 There is no overloaded version of 'CharInSet' that can be called with these arguments


CharInSet - не работает фрагмент кодане ленимся, все что мы хотим уже кто то делал


qwertehok, ну и в итоге ТС не стал использовать charInSet, так как у него тоже не работает он. Но и там тоже идея вроде как хорошая. Попробую тоже.


есть же CharInSet()
Вот в юникодных версиях, где он есть, я предпочитаю вообще с типом Char не связываться...
массив лишний
Точно
Delphi XE5.
Вот с этого всегда и надо начинать - указывать свою версию Delphi. Это делается при создании темы и избавляет от многих непоняток...Вот так работает и в юникодныых версиях:
function CheckPsw(_text: String): boolean;
const aBig: String = 'ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ';
      aSmall: String = 'abcdefghijklmnopqrstuvwxyzабвгдеёжзийклмнопрстуфхцчшщъыьэюя';
      Digit: String = '0123456789';
      Symb: String = '~!@#$%^&*()-_=+';
var i: integer;
    Mask: String;
begin
 Mask := '00000';
 if Length(_text) >= 8 then Mask[1] := '1';
 for i := 1 to Length(_text) do
  begin
   if Pos(_text[i], aBig) > 0 then Mask[2] := '1';
   if Pos(_text[i], aSmall) > 0 then Mask[3] := '1';
   if Pos(_text[i], Digit) > 0 then Mask[4] := '1';
   if Pos(_text[i], Symb) > 0 then Mask[5] := '1';
  end;
 result := Mask = '11111';
end;


указывать свою версию Delphi.
Буду знать Спасибо. D1973, а AnsiPos вместо Pos в данном случае можно использовать?


а AnsiPos вместо Pos в данном случае можно использовать?
А смысл?


D1973, понял. спасибо за ответы


Небольшой забавный факт. Пароли записанные с этими требованиями запоминаются и подбираются человеком плохо, а вот для компьютера такой подбор не сложен. Намного сложнее подобрать пароль содержащий просто несколько слов с небольшим добавлением от себя, например: саша саше моет ротик Даже просто первые три буквы из каждого слова забавной фразы будут намного устойчивее к взлому, чем этот изврат. сашсашмоерот такую фразу и запомнить намного легче