一、短信验证码模块
第一版代码如下
# 将短信验证码写入缓存
conn = get_redis_connection('verify_codes')
conn.setex('sms_code_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
conn.setex('sms_code_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
优化版代码如下
conn = get_redis_connection('verify_codes')
pl = conn.pipeline()
pl.setex('sms_code_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
pl.setex('sms_code_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
pl.execute()
conn.setex两次操作会对数据库进行两次连接,redis提供了管道,将两次操作放入管道中,然后可以只对数据库进行一次连接就可以完成多次操作。
二、Celery ValueError: not enough values to unpack (expected 3, got 0)的解决
worker报错信息如下
[2018-01-12 19:08:15,545: INFO/MainProcess] Received task: tasks.add[5d387722-5389-441b-9b01-a619b93b4702]
[2018-01-12 19:08:15,550: ERROR/MainProcess] Task handler raised error: ValueError('not enough values to unpack (expected 3, got 0)',)
Traceback (most recent call last):
File "d:\programmingsoftware\python35\lib\site-packages\billiard\pool.py", line 358, in workloop
result = (True, prepare_result(fun(*args, **kwargs)))
File "d:\programmingsoftware\python35\lib\site-packages\celery\app\trace.py", line 525, in _fast_trace_task
tasks, accept, hostname = _loc
ValueError: not enough values to unpack (expected 3, got 0)
解决方案:
先安装一个`eventlet
pip install eventlet
然后启动worker的时候加一个参数,如下:
celery -A <mymodule> worker -l info -P eventlet
然后就可以正常的调用了。
三、session与JWT的取舍
基于session认证所显露的问题
Session: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。
扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。
CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
**基于token的鉴权机制
基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。
流程上是这样的:
用户使用用户名密码来请求服务器
服务器进行验证用户的信息
服务器通过验证发送给用户一个token
客户端存储token,并在每次请求时附送上这个token值
服务端验证token值,并返回数据
这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了Access-Control-Allow-Origin:
四、MYSQL: Cannot delete or update a parent row: a foreign key constraint fails
这可能是MySQL在InnoDB中设置了foreign key关联,造成无法更新或删除数据。可以通过设置FOREIGN_KEY_CHECKS变量来避免这种情况。
SET FOREIGN_KEY_CHECKS = 0;
删除完成后设置
SET FOREIGN_KEY_CHECKS = 1;
但是对于更新字段等操作,必须也将子表的字段同步更新
想要删除父表的数据,需要先禁用外键约束检查:
SET FOREIGN_KEY_CHECKS = 0;
再执行更新语句即可
update dba.dept
set deptno=1110 where deptno=10;
为了确保子表和父表数值一致,也要更新子表相应字段值:
update dba.employee2 set deptno=1110 where deptno=10;