登录和session的概念

session机制

原理


点击这里,边看视频讲解,边学习以下内容

我们来思考一个问题。

一个网站,比如一个购物网站,服务成千上万的客户。

这么多客户同时访问网站,挑选商品,购物结算,都是通过HTTP请求访问网站的。

这个网站服务程序 怎么每个HTTP请求(比如付费 HTTP 请求)对应的是哪个客户的呢?

网站是怎么做到这点的呢?

一种常见的方式就是:通过 Session机制

session 翻译成中文就是 会话 的意思

session 机制大体原理如下图所示 :

image


image

用户使用客户端登录,服务端进行验证(比如验证用户名、密码)。

验证通过后,服务端系统就会为这次登录创建一个session。

session就是一个数据结构,保存该客户这次登录操作相关信息。通常保存在数据库中。

同时创建一个唯一的sessionid(就是一个字符串),标志这个session。

然后,服务端通过HTTP响应,把sessionid告诉客户端。

客户端在后续的HTTP请求消息头中,都要包含这个sessionid。这样服务端就会知道,这个请求对应哪个session,从而知道对应哪个客户。


从上图可以看出, 服务端是通过 HTTP的响应头 Set-Cookie 把产生的 sessionid 告诉客户端的。

客户端的后续请求,是通过 HTTP的请求头 Cookie 告诉服务端它所持有的sessionid的。

cookie 英文就是小甜饼的意思,这里表示一小段数据。

HTTP 协议规定了, 网站服务端放HTTP响应中 消息头 Set-Cookie 里面的数据, 叫做 cookie 数据, 浏览器客户端 必须保存下来。

而且后续访问该网站,必须在 HTTP的请求头 Cookie 中携带保存的所有cookie数据。

白月SMS系统使用的就是典型 session 区分用户的机制。

大家先看视频中关于白月SMS系统的session讲解。



点击这里,边看视频讲解,边学习以下内容

我们在Python代码中如果接收到服务端HTTP响应,其中Set-Cookie的数据怎么保存呢? 后续怎样放到请求消息头中 Cookie中呢?

前面 学过 HTTP响应中 如何 获取响应头, 构建请求怎样设置请求头,完全可以自己处理。

而且,requests库给我们提供一个 Session 类 。

通过这个类,无需我们操心, requests库自动帮我们保存服务端返回的 cookie数据, HTTP请求自动 在消息头中放入 cookie 数据。

如下所示:

import requests

# 打印HTTP响应消息的函数
def printResponse(response):
    print('\n\n-------- HTTP response * begin -------')
    print(response.status_code)

    for k, v in response.headers.items():
        print(f'{k}: {v}')

    print('')

    print(response.content.decode('utf8'))
    print('-------- HTTP response * end -------\n\n')


# 创建 Session 对象
s = requests.Session()

# 通过 Session 对象 发送请求
response = s.post("http://127.0.0.1/api/mgr/signin",
       data={
           'username': 'byhy',
           'password': '88888888'
       })

printResponse(response)

# 通过 Session 对象 发送请求
response = s.get("http://127.0.0.1/api/mgr/customers",
      params={
          'action'    :  'list_customer',
          'pagesize'  :  10,
          'pagenum'   :  1,
          'keywords'  :  '',
      })

printResponse(response)

打印完整的HTTP消息

如果你想打印出完整的请求响应消息,参考如下代码

import requests

# 打印请求消息, 参数为 PreparedRequest 对象
def pretty_print_request(req):
    if req.body == None:
        msgBody = ''
    else:
        msgBody = req.body
    print(
        '{}\n{}\n{}\n\n{}'.format(
        '\n\n----------- 发送请求 -----------',
        req.method + ' ' + req.url,
        '\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()),
        msgBody,
    ))

# 打印响应消息
def pretty_print_response(res):
    print(
        '{}\nHTTP/1.1 {}\n{}\n\n{}'.format(
        '\n\n----------- 得到响应 -----------',
        res.status_code,
        '\n'.join('{}: {}'.format(k, v) for k, v in res.headers.items()),
        res.text,
    ))


req = requests.Request(
    'post',
    'http://www.baidu.com',
    headers={
        'head1':'value1',
        'head2':'value2',
    },
    data={
        'item1':'body-value1',
        'item2':'body-value2',
    })

session = requests.Session()

#  如果这样写 prepared = req.prepare() 
#  后续发送会 请求消息头中,会丢掉session中的cookie数据
#  必须像下面这样写,才能让请求包含cookie数据
prepared = session.prepare_request(req)

pretty_print_request(prepared)
r = session.send(prepared)
pretty_print_response(r)

课后练习

题目1

点击这里查看白月SMS系统的接口文档

请用 Python 和 Requests库,为接口文档 里面每个API 接口, 开发一个函数 发送对应的HTTP请求,接收并且打印出响应消息体中的内容。

并且在测试过程中,使用 fiddler 抓包查看发送接收的HTTP消息。

题目2

VIP学员请联系老师获取补充练习

上一页
下一页