機(jī)遇總是有的际长,如果把握不住,不要怨天憂人兴泥,只因自己不夠優(yōu)秀工育;不要把時間當(dāng)垃圾處理,唯有珍惜光陰搓彻,才能提升生命的質(zhì)量如绸!
總結(jié):
- 用戶注冊登錄名重復(fù)怎么解決;
- 如何對密碼進(jìn)行加密旭贬;
- 如果要發(fā)一些數(shù)據(jù)發(fā)送到第三方客戶端怔接,有沒有第三種解決方案jwt(防篡改);
密碼
使用郵箱 + 密碼方式登錄稀轨。
郵箱要求唯一就行了扼脐,但是,密碼如何存儲奋刽?
早期瓦侮,都是明文的密碼存儲。
后來杨名,使用MD5存儲,但是猖毫,目前也不安全台谍,網(wǎng)上有很多MD5的網(wǎng)站,使用反查方式找到密碼吁断。
加鹽趁蕊,使用hash(password + salt)的結(jié)果存入數(shù)據(jù)庫中,就算拿到數(shù)據(jù)庫的密碼反查仔役,也沒有用了掷伙。如果是固定加鹽,還是容易被找到規(guī)律又兵,或者從源碼中泄露任柜。隨機(jī)加鹽卒废,每一次鹽都變,就增加了破解的難度宙地。
暴力破解摔认, 什么密碼都不能保證不被暴力破解, 例如窮舉宅粥。所以要使用慢hash算法参袱, 例如b crypt, 就會讓每一次計算都很慢秽梅, 都是秒級的抹蚀, 這樣窮舉的時間就會很長,為了一個密碼破解的時間在當(dāng)前CPU或者GPU的計算能力下可能需要幾十年以上企垦;
BCrypt
BCrypt加密算法环壤,號稱目前最安全的算法之一
哈希(Hash)是將目標(biāo)文本轉(zhuǎn)換成具有相同長度的、不可逆的雜湊字符串(或叫做消息摘要)竹观,而加密(Encrypt)是將目標(biāo)文本轉(zhuǎn)換成具有不同長度的镐捧、可逆的密文。
pip install bcrypt
哈希算法臭增,32位懂酱,往往被設(shè)計成生成具有相同長度的文本,而加密算法生成的文本長度與明文本身的長度有關(guān)誊抛。哈希算法是不可逆的列牺,而加密算法是可逆的。
從耗時看出拗窃, b crypt加密瞎领、驗證非常耗時, 所以如果窮舉随夸, 非常耗時九默。而且碰巧攻破一個密碼, 由于鹽不一樣宾毒, 還得窮舉另一個驼修;
salt=b'$2b$12$jwBD7mg9stvIPydF2bqoPO'
b'$2b$12$jwBD7mg9stvIPydF2bqoPOod PwW YV vdmZb5uwWuwvlf9iHqNlKSQO'
$是分隔符
$2b$,加密算法
12诈铛, 表示2^12key expansion rounds
這是鹽b'jwBD7mg9stvIPydF2bqoPO'乙各, 22個字符, Base 64
這是密文b'odP wWYVvdmZb5uwWuwvlf9iHqNl KS QO'幢竹, 31個字符耳峦, Base 64
import bcrypt
import datetime
password = b'123456'
# 每次拿到鹽都不一樣
print(1, bcrypt.gensalt())
print(2, bcrypt.gensalt())
salt = bcrypt.gensalt()
# 拿到的鹽相同,計算等到的密文相同
print('=========same salt ==========')
x = bcrypt.hashpw(password, salt)
print(3, x)
x = bcrypt.hashpw(password, salt)
print(4, x)
# 每次拿到的鹽不同焕毫,計算生成的密文也不一樣
print('=========different salt ==========')
x = bcrypt.hashpw(password, bcrypt.gensalt())
print(5, x)
x = bcrypt.hashpw(password, bcrypt.gensalt())
print(6, x)
# 校驗
print(bcrypt.checkpw(password, x), len(x))
print(bcrypt.checkpw(password + b' ', x), len(x)) # 錯誤校驗方法蹲坷;
# 計算時長
start = datetime.datetime.now()
y = bcrypt.hashpw(password, bcrypt.gensalt())
delta = (datetime.datetime.now() - start).total_seconds()
print(10, 'duration={}'.format(delta))
# 檢驗時長
start = datetime.datetime.now()
y = bcrypt.checkpw(password, x)
delta = (datetime.datetime.now() - start).total_seconds()
print(y)
print(11, 'duration={}'.format(delta))
start = datetime.datetime.now()
y = bcrypt.checkpw(b'1', x)
delta = (datetime.datetime.now() -start).total_seconds()
print(y)
print(10, 'duration={}'.format(delta))
注冊代碼 V2
全局變量
項目的settings.py文件實際上就是全局變量的配置文件驶乾。
SECRET_KEY 一個強(qiáng)密碼
from django.http import JsonResponse,HttpRequest,HttpResponseBadRequest
import simplejson,jwt,bcrypt
from .models import User
from django.db.models import Q
from django.conf import settings
def gen_token(user_id): # 生成令牌;
key = settings.SECRET_KEY
return JsonResponse({
'token':jwt.encode({'user_id':user_id},key,'HS256').decode()
},status=201)
# register
def reg(request:HttpRequest):
print(request.body)
try:
payload = simplejson.loads(request.body) # 用戶數(shù)據(jù)Json化 提交冠句;
print(type(settings))
email = payload['email'] # 提取內(nèi)容
query = User.objects.filter(email=email) # 看email是否已經(jīng)存在轻掩;
if query.first(): # 查一下: email 如果存在,則return error;
print('============================')
return HttpResponseBadRequest('用戶名已存在')
# 用戶名不存在懦底,繼續(xù)向下唇牧;
name = payload['name'] #
password = payload['password']
user = User()
user.email = email
user.name = name
user.password = bcrypt.hashpw(password.encode(),bcrypt.gensalt()) # 密碼采用bcrypt加密;
try:
user.save() #保存到數(shù)據(jù)庫test,唯一鍵約束
return gen_token(user.id) # 保存數(shù)據(jù)后返回一個令牌數(shù)據(jù)回去聚唐;
# 可以返回user_id status=201(注冊成功 重新登錄) 或者 token(登錄)
except Exception as e:
return JsonResponse({'reason':'asdaf'},status=400)
except Exception as e:
print(e)
return HttpResponseBadRequest('參數(shù)錯誤')
def show(request): # 方法的使用方式各不相同丐重;
users = User.objects.all()
print(users.values())# objects
return JsonResponse({})
# postman---------------------------------------------------------
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo5fQ._qB1j7cV-TIe5nZY8yO_x0e3xsnPQef-_1SRcQM-3_k"
}