1、加密概述
在web后端注册/登录逻辑中,我们经常需要将密码进行加密存储以便更好地保护会员的隐私与安全。存储方式分为明文和密文两种,不用说我们肯定选择密文存储,密文也就是加密后的数据,那么加密又有很多的方式,我们就来讲一讲
加密方式 | 特征描述 |
---|---|
明文转码加密 | BASE64, 7BIT等,这种方式只是个障眼法,不是真正的加密 |
对称算法加密 | DES, RSA等 |
签名算法加密 | 也可以理解为单向哈希加密,比如MD5, SHA1等。加密算法固定,容易被暴力破解。如果密码相同,得到的哈希值是一样的。 |
加盐哈希加密 | 加密时混入一段“随机”字符串(盐值)再进行哈希加密。即使密码相同,如果盐值不同,那么哈希值也是不一样的。现在网站开发中主要是运用这种加密方法 |
2、加密代码
import hashlib
SECRET_KEY = "xyz" # 加密密钥即自定义随机字符串(盐值)
def make_password(password):
# 加密密码
password = SECRET_KEY + password
sha1Obj = hashlib.sha1()
sha1Obj.update(password.encode())
ret = sha1Obj.hexdigest()
return ret
3、token概述
为什么要用token?token有什么用?
JWT认证生成token是目前比较流行的方式。由三段组成 第一段通常是加密算法,第二段是你存储的自定义信息(未加密任何人可以去https://jwt.io/看到数据) 第三段是 第一段和第二段生成的签名参数确保token没有被修改
python后端框架flask、django、tornado等一般都是有封装好的方法直接调用生成token。那么我们讲一下如何用传统的方法进行生成
更多链接
3、token代码
python 目前有多个库实现jwt验证
- python-jose
- pyjwt
- jwcrypto
- authlib
随机选一个就以python-jose为例来生成token
pip install python-jose
from jose import jwt
from datetime import datetime, timedelta
SECRET_KEY = "xyz" # 加密密钥即自定义随机字符串
ALGORITHM = "HS256" # 加密算法HS256
def create_access_token(name, expires_delta=None):
"""
# 生成token
:param name: 保存到token的值
:param expires_delta: 过期时间
:return:
"""
if expires_delta:
# expire = datetime.utcnow() + expires_delta
expire = datetime.now() + expires_delta
else:
# expire = datetime.utcnow() + timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES)
# 设置过期时间:30分钟后
expire = datetime.now() + timedelta(minutes=30)
to_encode = {"exp": expire, "sub": str(name)}
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
def check_jwt_token(token):
"""
# 验证token
:param token:header中的token值
:return:
"""
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload
except (jwt.JWTError, jwt.ExpiredSignatureError, AttributeError):
# 抛出自定义异常, 然后捕获统一响应
raise custom_exc.TokenAuthError(err_desc="ACCESS_TOKEN_FAIL")
def jwt_required(fn):
"""
# 制作token装饰器
:param fn:被装饰的函数
"""
def wrapper(*args, **kwargs):
try:
token = None # 从header中实际获取
jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
# token验证成功后执行被装饰函数
return fn()
except (jwt.JWTError, jwt.ExpiredSignatureError, AttributeError):
return out("ACCESS_TOKEN_FAIL")
return wrapper
def out(keyMsg, req)
"""
# 接口数据格式化
:param keyMsg:接口结果关键字
:param req:接口数据
:return:
"""
# res = {
# "code":{
# "SUCESS":{"msg":"请求成功", "code":1000},
# "FAIL":{"msg":"请求失败", "code":1001},
# "ACCESS_TOKEN_FAIL":{"msg":"TOKEN验证失败", "code":1003}
}
}
res = Config().config
res = res["code"][keyMsg]
res["content"] = req
return res