一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 用Python實現web端用戶登錄和注冊功能的教程

用Python實現web端用戶登錄和注冊功能的教程

2020-06-18 08:32廖雪峰 Python

這篇文章主要介紹了用Python實現web端用戶登錄和注冊功能的教程,需要的朋友可以參考下

用戶管理是絕大部分Web網站都需要解決的問題。用戶管理涉及到用戶注冊和登錄。

用戶注冊相對簡單,我們可以先通過API把用戶注冊這個功能實現了:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
_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位Hash字符串,所以服務器端并不知道用戶的原始口令。

接下來可以創建一個注冊頁面,讓用戶填寫注冊表單,然后,提交數據到注冊用戶的API:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{% extends '__base__.html' %}
 
{% block title %}注冊{% endblock %}
 
{% block beforehead %}
 
<script>
function check_form() {
 $('#password').val(CryptoJS.MD5($('#password1').val()).toString());
 return true;
}
</script>
 
{% endblock %}
 
{% block content %}
 
<div class="uk-width-2-3">
 <h1>歡迎注冊!</h1>
 <form id="form-register" class="uk-form uk-form-stacked" onsubmit="return check_form()">
  <div class="uk-alert uk-alert-danger uk-hidden"></div>
  <div class="uk-form-row">
   <label class="uk-form-label">名字:</label>
   <div class="uk-form-controls">
    <input name="name" type="text" class="uk-width-1-1">
   </div>
  </div>
  <div class="uk-form-row">
   <label class="uk-form-label">電子郵件:</label>
   <div class="uk-form-controls">
    <input name="email" type="text" class="uk-width-1-1">
   </div>
  </div>
  <div class="uk-form-row">
   <label class="uk-form-label">輸入口令:</label>
   <div class="uk-form-controls">
    <input id="password1" type="password" class="uk-width-1-1">
    <input id="password" name="password" type="hidden">
   </div>
  </div>
  <div class="uk-form-row">
   <label class="uk-form-label">重復口令:</label>
   <div class="uk-form-controls">
    <input name="password2" type="password" maxlength="50" placeholder="重復口令" class="uk-width-1-1">
   </div>
  </div>
  <div class="uk-form-row">
   <button type="submit" class="uk-button uk-button-primary"><i class="uk-icon-user"></i> 注冊</button>
  </div>
 </form>
</div>
 
{% endblock %}
Try

這樣我們就把用戶注冊的功能完成了:

用Python實現web端用戶登錄和注冊功能的教程

用戶登錄比用戶注冊復雜。由于HTTP協議是一種無狀態協議,而服務器要跟蹤用戶狀態,就只能通過cookie實現。大多數Web框架提供了Session功能來封裝保存用戶狀態的cookie。

Session的優點是簡單易用,可以直接從Session中取出用戶登錄信息。

Session的缺點是服務器需要在內存中維護一個映射表來存儲用戶登錄信息,如果有兩臺以上服務器,就需要對Session做集群,因此,使用Session的Web App很難擴展。

我們采用直接讀取cookie的方式來驗證用戶登錄,每次用戶訪問任意URL,都會對cookie進行驗證,這種方式的好處是保證服務器處理任意的URL都是無狀態的,可以擴展到多臺服務器。

由于登錄成功后是由服務器生成一個cookie發送給瀏覽器,所以,要保證這個cookie不會被客戶端偽造出來。

實現防偽造cookie的關鍵是通過一個單向算法(例如MD5),舉例如下:

當用戶輸入了正確的口令登錄成功后,服務器可以從數據庫取到用戶的id,并按照如下方式計算出一個字符串:

"用戶id" + "過期時間" + MD5("用戶id" + "用戶口令" + "過期時間" + "SecretKey")

當瀏覽器發送cookie到服務器端后,服務器可以拿到的信息包括:

  •     用戶id
  •     過期時間
  •     MD5值

如果未到過期時間,服務器就根據用戶id查找用戶口令,并計算:

MD5("用戶id" + "用戶口令" + "過期時間" + "SecretKey")

并與瀏覽器cookie中的MD5進行比較,如果相等,則說明用戶已登錄,否則,cookie就是偽造的。

這個算法的關鍵在于MD5是一種單向算法,即可以通過原始字符串計算出MD5,但無法通過MD5反推出原始字符串。

所以登錄API可以實現如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@api
@post('/api/authenticate')
def authenticate():
  i = ctx.request.input()
  email = i.email.strip().lower()
  password = i.password
  user = User.find_first('where email=?', email)
  if user is None:
    raise APIError('auth:failed', 'email', 'Invalid email.')
  elif user.password != password:
    raise APIError('auth:failed', 'password', 'Invalid password.')
  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 = '******'
  return user
 
# 計算加密cookie:
def make_signed_cookie(id, password, max_age):
  expires = str(int(time.time() + max_age))
  L = [id, expires, hashlib.md5('%s-%s-%s-%s' % (id, password, expires, _COOKIE_KEY)).hexdigest()]
  return '-'.join(L)
 
對于每個URL處理函數,如果我們都去寫解析cookie的代碼,那會導致代碼重復很多次。
 
利用攔截器在處理URL之前,把cookie解析出來,并將登錄用戶綁定到ctx.request對象上,這樣,后續的URL處理函數就可以直接拿到登錄用戶:
 
@interceptor('/')
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('-')
    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('%s-%s-%s-%s' % (id, user.password, expires, _COOKIE_KEY)).hexdigest():
      return None
    return user
  except:
    return None
Try

這樣,我們就完成了用戶注冊和登錄的功能。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 天若有情1992国语版完整版 | 91最新入口| 暖暖视频高清图片免费完整版 | 手机看片国产免费现在观看 | 久久国产主播福利在线 | 四虎1515hhh co m| 激情婷婷综合久久久久 | 五月婷婷丁香色 | 5278欧美一区二区三区 | 日韩网站在线 | 国产偷啪| 亚洲 欧美 国产 日韩 字幕 | 免费看男女污污完整版 | 国产麻豆麻豆 | 国产精品久久久久久久久久久搜索 | 午夜爱 | 草草草草视频 | 国产三级跑| 91短视频在线观看2019 | 夫承子液by免费阅读 | 久久久久嫩草影院精品 | 亚洲AV无码一区二区三区乱子伦 | 精品国产成人 | 韩国禁片在线观看久 | 美女翘臀跪床被打屁股作文 | 国色天香社区在线视频免费观看 | 亚洲乱码尤物193yw在线播放 | 国产亚洲欧美在线中文bt天堂网 | 精品久久久久久午夜 | 四缺一写的小说 | 欧美另类性xxoo | 国产精品永久免费视频观看 | 日本视频二区 | 亚洲成人中文 | 日本不卡在线一区二区三区视频 | 成在线人免费视频一区二区三区 | 苍井空av| 亚洲va欧美va国产va天堂影 | 白丝vk丨tk失禁 | 青青热久免费精品视频精品 | 欧洲久久|