Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

session 和 cookie 整理 #3

Open
hacker0limbo opened this issue Aug 25, 2019 · 0 comments
Open

session 和 cookie 整理 #3

hacker0limbo opened this issue Aug 25, 2019 · 0 comments
Labels
网络 浏览器, 计算机网络等

Comments

@hacker0limbo
Copy link
Owner

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

参考

@hacker0limbo hacker0limbo added the 网络 浏览器, 计算机网络等 label Aug 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
网络 浏览器, 计算机网络等
Projects
None yet
Development

No branches or pull requests

1 participant