Description
session 和 cookie 总结
直接使用cookie
也是可以追踪用户的, 但是不安全, 所以比较好的做法为, 在第一次登录以后, 往客户端发送一个 cookie
, cookie
里面的 value
设置为session_id
, 发送请求到服务器的时候, 服务器有一个 session
使用[session_id: username]
来验证发送过来的cookie
这样的好处是:
- 服务端可以使用 session 来跟踪用户
- 客户端用户登录一次以后由于被设置了 cookie, 下次可以免去登录
具体流程为:
1, 第一访问登录页面, 提交登录表单信息
2, 服务端得到用户提交的登录数据, 设置:
session, session[session_id] = user.username
3, 服务端返回 response 带上 cookie 信息:
headers['Set-Cookie'] = f'user={session_id}'
4, 一个 current_user 函数, 可以用户从用户的 cookie 里得到 session_id, 与服务端匹配, 验证用户:
session_id = request.cookies.get('user', '')
username = session.get(session_id, '游客')
5, 如果对应的 session_id 匹配成功, 说明用户处于登录状态, 可以被追踪, 否则用户没有登录
6, 用户如果关闭浏览器, cookie 不受影响一直保存在浏览器里(除非过期), 下次打开页面可以直接免登录
7, 只要服务器不关闭, 那么 session 里面的用户信息是永久保存的, 只要客户端设置了 cookie, 验证成功那么该用户就可以被追踪, 即处于登录成功的状态
示例代码可以参见: cookie&session
模拟代码
from bottle import route, run, response, request, redirect
login_user = {} # 就是 session
@route('/login')
def login():
key = hash("test password")
login_user[key] = "test password"
response.set_cookie('session_id', str(key)) # 设置Cookie值, 下次可以免登录
return 'login successfuly!'
@route('/logout')
def logout():
key = request.get_cookie('session_id')
login_user.pop(int(key), None) # 删除 session 里面的用户, 这样无法在服务端验证
return 'logout successfuly!'
@route('/logintest')
def logintest():
key = request.get_cookie('session_id') # 获取Cookie值
if key is not None and int(key) in login_user: # 看看 session 字典里存的有没有用户
return 'login test successfuly!'
else :
return redirect('/beforelogin')
@route('/beforelogin')
def beforelogin():
return 'please login!'
run(host='localhost', port=8080, debug=True)
flash message 原理
需求
客户端提交登录登录表单, 如果成功重定向到首页, 否则停留(重定向)在登录页面, 并显示"登录失败"
原理如下
使用 session
对于 login controller, 需要知道客户端显示登录错误, 还是显示登录成功?
也就是 lgoin:post controller 需要给 redirect 后的 login:get controller 发送一个消息告诉他上次登录失败, 两个 controller 直接无法直接发送消息
由于可以在服务端内部共享消息, 可以将用户的动作存储在 session 里, 具体为:
login:post 发送登录失败就在对应 session 里写入一个标记, redirect 到的 login:get 渲染页面的时候检查是否有登录失败标记, 如果有就在渲染的页面里面取出标记对应的信息, 然后在这个将这个标记从这个 session 里面清楚, 伪代码可以为:
session['操作'] = 'msg'
session.get('操作', '') # 获取该操作对应提示信息
session.pop('操作') # 删除该操作以及信息
使用 cookie
有时候用户可能没有正确的 redirect 到 login:get, 那么这个 flash message 还是存在 session 里面, 也就是说用户下次访问 login:get 会提示登录错误, 这样是不合理的
可以使用 cookie, 做法为:
login:post 检测发现错误了就给客户端加一个 cookie 并且发送 redirect 到 login:get, 也就是说这个 cookie 只有 redirect 成功以后才会被客户端带上, 那么重定向以后只要检查是否带有这个 cookie, 有就渲染出对应的错误消息. 即使 redirect 没有成功, 那么附带的 cookie 也无法正确被发送过去, 因而也不会显示错误信息
当然匹配了 cookie 以后需要手动设置 cookie 过期时间清除 cookie, 防止下次访问该页面出现同样的 flash message