MENU

Python:正規表現10 ~正規表現でパスワード強度判定システムを作る~

※アイキャッチ画像は生成AIを使用して作成しています。
今回は、正規表現を使ったパスワード強度判定システムを作成しました。
最初は「and」や「or」を使った単純な条件分岐で実装しようとしましたが、思ったような判定ができず苦戦しました。
試行錯誤した結果、「条件を満たした数を数える」という考え方にたどり着き、無事に完成させることができました。
この記事では、失敗したコードも含めて、実際にどのように考え、修正していったのかを学習記録としてまとめます。
目次

今回作ったシステム(パスワード強度判定システム)

今回は、入力されたパスワードが

  • 8文字以上か
  • 大文字を含むか
  • 小文字を含むか
  • 数字を含むか

を判定して、パスワードの強度を表示するプログラムを作りました。

最初に作ったコード

目標とした動作

まず、入力されたパスワードが8文字以上かを判定し、8文字未満の場合は再度入力を求めるようにしました。

次に、

  • 大文字を含むか
  • 小文字を含むか
  • 数字を含むか

を正規表現で判定します。

そして、3つの条件をすべて満たしていれば「強力なパスワードです」、2つ満たしていれば「普通のパスワードです」、1つ満たしていれば「弱いパスワードです」と表示することを目標にしました。

まずは、この考え方をそのままコードにしてみました。

実際に作ったコード

import re
#パスワードを入力させて8文字以上なら次へ、8文字未満ならやり直し
while True:
    password=input('>')
    if len(password)>=8:
        break
    else:
        print('パスワードは8文字以上入力して')

#正規表現を定義
upper=re.compile(r'[A-Z]')
lower=re.compile(r'[a-z]')
suji=re.compile(r'\d')

#3つと条件を満たす場合強力なパスワード
if upper.search(password) and lower.search(password) and suji.search(password):
    print('強力なパスワードです')

#1つだけ条件を満たす場合→弱いパスワードです(と表示したかった)
elif upper.search(password) or lower.search(password) or suji.search(password):
    print('弱いパスワードです')

#それ以外(条件を2つ満たす場合)→普通のパスワードです(と表示したかった)
else:
    print('普通のパスワードです')

問題点

最初は、

elif upper.search(password) or lower.search(password) or suji.search(password):

と書いていました。

条件を3つ満たしている場合は「強力なパスワードです」と表示されます。しかし、条件を1つだけ満たす場合も、2つ満たす場合も、どちらも「弱いパスワードです」と判定されてしまいました。

例えば、

  • abcdefg1
  • ABCDEFG1
  • ABCdefgh

はすべて同じ判定になってしまいました。

発想を変えた

カウント用の変数を作る

そこで、「条件を満たした数を数える」という方法に変更しました。

count = 0

まずはカウント用の変数を作ります。

条件を満たすたびに加算

if upper.search(password):
count += 1

if lower.search(password):
count += 1

if suji.search(password):
count += 1

条件を満たした個数が分かれば、あとはその数によって判定できます。

最初は、

if upper.search(password) == True:

のように書く必要があると思っていました。

しかし、re.search() は True や False を返しているわけではありません。

条件に一致した場合は re.Match オブジェクト を返し、

一致しなかった場合は None を返します。

Pythonでは、None は False、オブジェクトは True として扱われるため、

if upper.search(password):

と書くだけで、「検索結果が存在するか」を判定できます。

今回の学習で、Pythonの条件式は True と False だけでなく、オブジェクトの有無でも判定できることを理解できました。

完成版

import re
# パスワードを入力させ、8文字未満なら再入力
while True:
    password=input('>')
    if len(password)>=8:
        break
    else:
        print('パスワードは8文字以上入力して')

# 正規表現を定義
upper=re.compile(r'[A-Z]')#大文字
lower=re.compile(r'[a-z]')#小文字
suji=re.compile(r'\d')#数字

# 条件を満たした数をカウント
count=0 

# 大文字・小文字・数字が含まれているか判定
if upper.search(password):
    count+=1

if lower.search(password):
    count+=1

if suji.search(password):
    count+=1

# パスワードの強度を判定
if count == 3 :
    print('強力なパスワードです')

elif count == 2 :
    print('普通のパスワードです')

else:
    print('弱いパスワードです')

今回学んだこと

今回の学習で学んだこと

  • re.search() は条件に一致するとオブジェクトを返し、if 文では True として扱われる
  • and はすべての条件を満たす場合
  • or は1つでも条件を満たす場合
  • 複数条件の判定は「数える」という考え方が便利
  • 最初から正解を書くより、失敗した方が理解が深まる

感想

今回は「正解を覚える」のではなく、「なぜ間違えたのか」を考えることで理解が深まりました。
独学だと間違えることに抵抗を感じますが、むしろその間違いこそが一番勉強になると実感した1日でした。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

FIREを目指しながら、投資・プログラミング・家庭菜園・資格勉強に取り組んでいます。試行錯誤しながら積み上げる日々を記録するブログです。

コメント

コメントする

目次