ホームページ >バックエンド開発 >Python チュートリアル >Python を使用して Web ユーザーのログインおよび登録機能を実装する

Python を使用して Web ユーザーのログインおよび登録機能を実装する

不言
不言オリジナル
2018-04-09 17:28:2213516ブラウズ

この記事では、主に Python を使用して Web ユーザーのログインと登録機能を実装するチュートリアルを紹介します。必要な友人はそれを参照してください。

ユーザー管理は、ほとんどの Web ウェブサイトが解決する必要がある問題です。ユーザー管理には、ユーザーの登録とログインが含まれます。

ユーザー登録は比較的簡単です。まず、API を通じてユーザー登録関数を実装します。

_RE_MD5 = re.compile(r'^[0-9a-f]{32}$')

@api
@post('/api/users')
def register_user():
 i = ctx.request.input(name='', email='', password='')
 name = i.name.strip()
 email = i.email.strip().lower()
 password = i.password
 if not name:
  raise APIValueError('name')
 if not email or not _RE_EMAIL.match(email):
  raise APIValueError('email')
 if not password or not _RE_MD5.match(password):
  raise APIValueError('password')
 user = User.find_first('where email=?', email)
 if user:
  raise APIError('register:failed', 'email', 'Email is already in use.')
 user = User(name=name, email=email, password=password, image='http://www.gravatar.com/avatar/%s?d=mm&s=120' % hashlib.md5(email).hexdigest())
 user.insert()
 return user

ユーザーのパスワードは、MD5 計算後にクライアントによって渡される 32 ビットのハッシュ文字列であることに注意してください。ではありません ユーザーの元のパスワードが不明です。

次に、登録ページを作成し、ユーザーに登録フォームに入力させ、登録済みユーザーの API にデータを送信できます:

{% extends '__base__.html' %}

{% block title %}注册{% endblock %}

{% block beforehead %}

<script>
function check_form() {
 $(&#39;#password&#39;).val(CryptoJS.MD5($(&#39;#password1&#39;).val()).toString());
 return true;
}
</script>

{% endblock %}

{% block content %}

<p class="uk-width-2-3">
 <h1>欢迎注册!</h1>
 <form id="form-register" class="uk-form uk-form-stacked" onsubmit="return check_form()">
  <p class="uk-alert uk-alert-danger uk-hidden"></p>
  <p class="uk-form-row">
   <label class="uk-form-label">名字:</label>
   <p class="uk-form-controls">
    <input name="name" type="text" class="uk-width-1-1">
   </p>
  </p>
  <p class="uk-form-row">
   <label class="uk-form-label">电子邮件:</label>
   <p class="uk-form-controls">
    <input name="email" type="text" class="uk-width-1-1">
   </p>
  </p>
  <p class="uk-form-row">
   <label class="uk-form-label">输入口令:</label>
   <p class="uk-form-controls">
    <input id="password1" type="password" class="uk-width-1-1">
    <input id="password" name="password" type="hidden">
   </p>
  </p>
  <p class="uk-form-row">
   <label class="uk-form-label">重复口令:</label>
   <p class="uk-form-controls">
    <input name="password2" type="password" maxlength="50" placeholder="重复口令" class="uk-width-1-1">
   </p>
  </p>
  <p class="uk-form-row">
   <button type="submit" class="uk-button uk-button-primary"><i class="uk-icon-user"></i> 注册</button>
  </p>
 </form>
</p>

{% endblock %}
Try

このようにして、ユーザー登録機能が完了しました:

2015430102634859.jpg (560×753)

ユーザーログインはユーザー登録よりも複雑です。 HTTP プロトコルはステートレス プロトコルであり、サーバーはユーザーのステータスを追跡する必要があるため、これは Cookie を通じてのみ実現できます。ほとんどの Web フレームワークは、ユーザーの状態を保存する Cookie をカプセル化するセッション機能を提供します。

Session の利点は、シンプルで使いやすく、ユーザーのログイン情報を Session から直接取得できることです。

Session の欠点は、サーバーが 3 つ以上のサーバーがある場合、ユーザーのログイン情報を保存するためにメモリ内にマッピング テーブルを維持する必要があるため、Session を使用した Web アプリを拡張するのが難しいことです。

ユーザーのログインを確認するために Cookie を直接読み取る方法を使用します。この方法の利点は、サーバーがあらゆる URL をステートレスな方法で処理し、確認できることです。複数のサーバーに拡張されました。

サーバーはログイン成功後に Cookie を生成してブラウザに送信するため、この Cookie がクライアントによって偽造されないことを確認する必要があります。

偽造防止 Cookie を実現する鍵は、一方向アルゴリズム (MD5 など) を使用することです。例:

ユーザーが正しいパスワードを入力してログインに成功すると、サーバーはデータベースからユーザーの ID を取得できます。次のように計算します:

"ユーザー ID" + "有効期限" + MD5("ユーザー ID" + "ユーザー パスワード" + "有効期限" + "シークレットキー")

ブラウザが Cookie を送信するときサーバーが取得できる情報には以下が含まれます:

  • ユーザー ID

  • 有効期限

  • MD5 値

有効期限に達していない場合、サーバーはユーザーのパスワードを検索しますユーザー ID に基づいて、

MD5 ("ユーザー ID" + "ユーザー パスワード" + "有効期限" + "シークレットキー")

を計算し、ブラウザー Cookie の MD5 と比較します。それらが等しい場合、それは意味します。それ以外の場合、Cookie は偽造されます。

このアルゴリズムの重要な点は、MD5 が一方向アルゴリズムであるということです。つまり、MD5 は元の文字列から計算できますが、元の文字列を MD5 から推定することはできません。

したがって、ログイン API は次のように実装できます:

@api
@post(&#39;/api/authenticate&#39;)
def authenticate():
  i = ctx.request.input()
  email = i.email.strip().lower()
  password = i.password
  user = User.find_first(&#39;where email=?&#39;, email)
  if user is None:
    raise APIError(&#39;auth:failed&#39;, &#39;email&#39;, &#39;Invalid email.&#39;)
  elif user.password != password:
    raise APIError(&#39;auth:failed&#39;, &#39;password&#39;, &#39;Invalid password.&#39;)
  max_age = 604800
  cookie = make_signed_cookie(user.id, user.password, max_age)
  ctx.response.set_cookie(_COOKIE_NAME, cookie, max_age=max_age)
  user.password = &#39;******&#39;
  return user

# 计算加密cookie:
def make_signed_cookie(id, password, max_age):
  expires = str(int(time.time() + max_age))
  L = [id, expires, hashlib.md5(&#39;%s-%s-%s-%s&#39; % (id, password, expires, _COOKIE_KEY)).hexdigest()]
  return &#39;-&#39;.join(L)

对于每个URL处理函数,如果我们都去写解析cookie的代码,那会导致代码重复很多次。

利用拦截器在处理URL之前,把cookie解析出来,并将登录用户绑定到ctx.request对象上,这样,后续的URL处理函数就可以直接拿到登录用户:

@interceptor(&#39;/&#39;)
def user_interceptor(next):
  user = None
  cookie = ctx.request.cookies.get(_COOKIE_NAME)
  if cookie:
    user = parse_signed_cookie(cookie)
  ctx.request.user = user
  return next()

# 解密cookie:
def parse_signed_cookie(cookie_str):
  try:
    L = cookie_str.split(&#39;-&#39;)
    if len(L) != 3:
      return None
    id, expires, md5 = L
    if int(expires) < time.time():
      return None
    user = User.get(id)
    if user is None:
      return None
    if md5 != hashlib.md5(&#39;%s-%s-%s-%s&#39; % (id, user.password, expires, _COOKIE_KEY)).hexdigest():
      return None
    return user
  except:
    return None
Try

このようにして、ユーザー登録とログイン機能が完了しました。

関連する推奨事項:

Pythonで文字列を接続するいくつかの方法の概要

Pythonでのsortメソッドの使用方法の詳細な説明

以上がPython を使用して Web ユーザーのログインおよび登録機能を実装するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。