- 本文作者: Yarving Liu
- 本文鏈接: http://yarving.historytale.com/2018/06/05/python-sum-map-filter-reduce/
- 版權(quán)聲明:本博客所有文章除特別聲明外刽宪,均采用 CC BY-NC-SA 4.0 許可協(xié)議。轉(zhuǎn)載請(qǐng)注明出處!
需求
需要設(shè)計(jì)一個(gè)系統(tǒng)(采用Django)咳蔚,專門管理另一個(gè)系統(tǒng)的用戶。用戶登錄在另一個(gè)系統(tǒng)中進(jìn)行帆精,那邊的密碼采用bcrypt進(jìn)行校驗(yàn)柴墩,所以Django系統(tǒng)中密碼保存也要用bcrypt加密保存。
而Django雖然自帶的User中提供了Password功能(輸入明文铃岔、自動(dòng)生成加密字符串),但是model中卻并不提供一個(gè)所謂的PasswordField峭火。
因此毁习,需求就是如何在自己實(shí)現(xiàn)的注冊(cè)功能中,將明文密碼用bcrypt加密保存
設(shè)計(jì)
以前沒有安全方面“專業(yè)”知識(shí)累積卖丸,所以決定自己創(chuàng)建路由纺且、視圖、表單等組件稍浆,但是在查找資料的過程中發(fā)現(xiàn)了許多可用的資料载碌。
但是提前優(yōu)化是萬惡之源,我沒有決定中途改換技術(shù)方案衅枫,而是等待下一版再更改為更專業(yè)的方案嫁艇。
創(chuàng)建路由、視圖弦撩、表單步咪、模板等過程都比較簡(jiǎn)單,就不在贅述了益楼,著重講下如何將明文密碼進(jìn)行加密的過程歧斟。
下載bcrypt
Python 版的 bcrypt 的 網(wǎng)站,安裝命令:pip install bcrypt
實(shí)現(xiàn)
接下來偏形,在form的 clean_password()
函數(shù)里静袖,返回加密后的字符串。
import bcrypt
class SignUpForm(forms.Form):
password1 = forms.CharField(
required=True,
widget=forms.PasswordInput(attrs={'placeholder': '輸入密碼', 'class': 'input pass'})
)
password2 = forms.CharField(
required=True,
widget=forms.PasswordInput(attrs={'placeholder': '再次輸入密碼', 'class': 'input pass'})
)
def clean_password2(self):
cleaned_data = super(SignUpForm, self).clean()
password2 = cleaned_data.get('password2')
return bcrypt.hashpw(password2, bcrypt.gensalt())
在views里取值時(shí)用form.cleaned_data['password2']
即可取到加密后的字符串俊扭,驗(yàn)證功能在需求部分已經(jīng)做過介紹队橙,不需要django這部分負(fù)責(zé)。
排坑
我的django是基于python3的,在python2里測(cè)試生成加密字符串的過程沒有問題捐康,但是在python3會(huì)報(bào)如下錯(cuò)誤:
Unicode-objects must be encoded before hashing
查找了下原因仇矾,是因?yàn)閜ython3里,字符串有str
和bytes
兩種形態(tài)解总,所以需要改成
bcrypt.hashpw(password2.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
另外贮匕,bcrypt有多種標(biāo)準(zhǔn),我們需要的是2a
花枫,所以還要改成:
bcrypt.hashpw(password2.encode('utf-8'), bcrypt.gensalt(prefix=b'2a')).decode('utf-8')
這樣就得到正確結(jié)果了刻盐。
結(jié)果
可以看到password的值已經(jīng)是bcrypt加密后的字符串了。