Open hacker0limbo opened 5 years ago
直接使用cookie也是可以追踪用户的, 但是不安全, 所以比较好的做法为, 在第一次登录以后, 往客户端发送一个 cookie, cookie 里面的 value 设置为session_id, 发送请求到服务器的时候, 服务器有一个 session 使用[session_id: username]来验证发送过来的cookie
cookie
value
session_id
session
[session_id: username]
这样的好处是:
具体流程为:
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)
客户端提交登录登录表单, 如果成功重定向到首页, 否则停留(重定向)在登录页面, 并显示"登录失败"
原理如下
对于 login controller, 需要知道客户端显示登录错误, 还是显示登录成功?
也就是 lgoin:post controller 需要给 redirect 后的 login:get controller 发送一个消息告诉他上次登录失败, 两个 controller 直接无法直接发送消息
由于可以在服务端内部共享消息, 可以将用户的动作存储在 session 里, 具体为:
login:post 发送登录失败就在对应 session 里写入一个标记, redirect 到的 login:get 渲染页面的时候检查是否有登录失败标记, 如果有就在渲染的页面里面取出标记对应的信息, 然后在这个将这个标记从这个 session 里面清楚, 伪代码可以为:
session['操作'] = 'msg' session.get('操作', '') # 获取该操作对应提示信息 session.pop('操作') # 删除该操作以及信息
有时候用户可能没有正确的 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
session 和 cookie 总结
直接使用
cookie
也是可以追踪用户的, 但是不安全, 所以比较好的做法为, 在第一次登录以后, 往客户端发送一个cookie
,cookie
里面的value
设置为session_id
, 发送请求到服务器的时候, 服务器有一个session
使用[session_id: username]
来验证发送过来的cookie
这样的好处是:
具体流程为:
示例代码可以参见: cookie&session
模拟代码
flash message 原理
需求
客户端提交登录登录表单, 如果成功重定向到首页, 否则停留(重定向)在登录页面, 并显示"登录失败"
原理如下
使用 session
对于 login controller, 需要知道客户端显示登录错误, 还是显示登录成功?
也就是 lgoin:post controller 需要给 redirect 后的 login:get controller 发送一个消息告诉他上次登录失败, 两个 controller 直接无法直接发送消息
由于可以在服务端内部共享消息, 可以将用户的动作存储在 session 里, 具体为:
login:post 发送登录失败就在对应 session 里写入一个标记, redirect 到的 login:get 渲染页面的时候检查是否有登录失败标记, 如果有就在渲染的页面里面取出标记对应的信息, 然后在这个将这个标记从这个 session 里面清楚, 伪代码可以为:
使用 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
参考