为什么说session依赖cookie,以及cookie的常用知识
session的用法
session在Flask中通常用做设置某些页面的权限,比如某些页面必须要登录才可以看到,登录的信息或标志就放到session中.它的使用过程如下:
- 在整个flask工程的启动文件中添加app.config['SECRET_KEY'] = 'you never guess',SECRET_KEY是用来加密session的,本质上是一个加密盐.
- 再在使用的py文件中添加from functools import wraps ,封装装饰器
- 在使用的py文件中添加from flask import session
- 然后写处理函数
- 再在逻辑代码中写已经登录的标志或者是存储其他关于请求的信息
- 最后在设置限制的视图函数前添加限制函数的修饰器
一个简单的例子
# encoding: utf-8
from flask import Flask
from flask import request, session, redirect
from functools import wraps
app = Flask(__name__)
app.config['SECRET_KEY'] = 'you never guess' # 使用 session 必须要配置这个,加密签名.
# 登录、注册认证函数
def authorize(fn):
@wraps(fn)
def wrapper(*args, **kwargs): # 这里就像过滤器,有了那个修饰器标志的视图函数都必须经过这个函数才可以返回请求
user = session.get('logged_in', None) # 取得登录标志
if user:
return fn(*args, **kwargs) # 登录了就返回请求
else:
return 'need login!' # 否则就转到注册的页面
return wrapper
@app.route('/')
@app.route('/home')
def index():
session["global_name"] = "global_path"
return session["global_name"] + 'home.html'
@app.route('/find')
def find():
print(vars(session))
return session.get("global_name", "None") + 'find.html'
@app.route('/doc')
@authorize # 这个修饰器表示,这个视图页面必须登录才可以访问
def blog():
print(session['username'])
return 'blog.html'
# 登录用户
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return "login.html"
if request.method == 'POST':
username = request.values.get('username')
password = request.values.get('password')
if username and password:
session['logged_in'] = True # 登录成功
session['username'] = username
session['password'] = password
return username + password
else:
return "need username and password"
# 注销用户
@app.route('/signout', methods=['GET', 'POST'])
@authorize
def logout():
session['logged_in'] = False # 变成false 就意味着需要重新登录了
return redirect('/home')
if __name__ == '__main__':
app.run()
几句curl
# 登录接口与返回,可以看出response中set-cookie了
curl -X POST "http://127.0.0.1:5000/login" -d "username=test&password=123"
HTTP/1.0 200 OK
Set-Cookie: session=eyJsb2dnZWRfaW4iOnRydWUsInBhc3N3b3JkIjoiMTIzIiwidXNlcm5hbWUiOiJsZ2oifQ.DoNGjg.4c2Adke_tzqo5MW_BHs95FvY6i4; HttpOnly; Path=/
# 不带cookie访问需要登录的接口
curl "http://127.0.0.1:5000/doc"
need signin!
# 带上cookie后访问通过
curl --cookie "session=eyJsb2dnZWRfaW4iOnRydWUsInBhc3N3b3JkIjoiMTIzIiwidXNlcm5hbWUiOiJsZ2oifQ.DoNGjg.4c2Adke_tzqo5MW_BHs95FvY6i4" "http://127.0.0.1:5000/doc"
user/blog.html
# 登出接口也是同上的.
curl "http://127.0.0.1:5000/logout"
need signin!
curl --cookie "session=eyJsb2dnZWRfaW4iOnRydWUsInBhc3N3b3JkIjoiMTIzIiwidXNlcm5hbWUiOiJsZ2oifQ.DoNGjg.4c2Adke_tzqo5MW_BHs95FvY6i4" "http://127.0.0.1:5000/signout"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: <a href="/home">/home</a>. If not click the link.
# 使用session存储一些其他信息也是依赖于cookie存在的
curl -v "http://127.0.0.1:5000"
global_pathhome.html
HTTP/1.0 200 OK
Set-Cookie: session=eyJnbG9iYWxfbmFtZSI6eyIgYiI6IloyeHZZbUZzWDNCaGRHZz0ifX0.DoNPag.ooEMHsinZlKRQpLF_-S3axsH3jc; HttpOnly; Path=/
# 想要得到设置global_name,不带cookie是得不到的
curl "http://127.0.0.1:5000/find"
Nonefind.html
# 带cookie
curl --cookie "session=eyJnbG9iYWxfbmFtZSI6eyIgYiI6IloyeHZZbUZzWDNCaGRHZz0ifX0.DoNPag.ooEMHsinZlKRQpLF_-S3axsH3jc" "http://127.0.0.1:5000/find"
global_pathfind.html
# 设置cookie
curl -v "http://127.0.0.1:5000/set_cookie"
< HTTP/1.0 200 OK
< Set-Cookie: name=test; Expires=Wed, 19-Sep-2018 03:42:31 GMT; Max-Age=200; Path=/
< Set-Cookie: age=18; Path=/
set_cookie* Closing connection 0
# 获取cookie
curl --cookie "name=test;age=18" "http://127.0.0.1:5000/get_cookie"
name is test,name is 18
总结:
平时使用浏览器访问接口,很难注意到cookie和session的区别与联系,使用curl就把区别暴露了出来.
上面的curl交互可以看出 session是会以set-cookie的方式设置到浏览器中,之后的访问都会将cookie带上请求其他接口,若使用curl而不带上cookie就会导致错误,这也是为什么说session是依赖cookie存在的.
cookie存在的目的:
因为http协议属于无状态协议,它不跟踪从一个客户端到另一个客户端的请求信息.也就是说即使第一次和服务器连接后并且登录成功,第二次请求服务器依然不知道请求的是哪个用户.
所以使用cookie来解决这个问题:第一次登录成功后,服务器返回cookie给浏览器,然后浏览器保存在本地,当用户发送第二次请求时,就会自动的把上次请求存储的cookie数据携带给服务器,服务器再根据cookie数据判断是哪个用户.session和cookie的作用类似:
也是用来存储用户相关的信息,存储在服务器端.把用户的信息经过加密后存储在session中,然后产生一个唯一的session_id.cookie和session的结合使用
一般有两种存储方式:
(1) 存储在服务器端:通过cookie存储一个session_id,然后具体的数据则是保存在session中.如果用户已经登录,则服务器会在cookie中保存一个session_id,下次再请求时,会把该session_id携带上来,服务器根据session_id在session库中获取用户的session数据,就知道用户到底是谁了.以及之前保存的一些状态信息,这种专业术语叫做server side session. (2) 存储在客户端:将session数据加密,然后存储在cookie中.这种专业术语叫做 client side session.flask框架采用的就是这种方式,但是可以替换成其他形式.
flask的session机制
把用户信息经过加密后放入到session中,然后把session存放到cookie中.下次请求时,从浏览器发送过来的cookie中读取到session,然后再从session中读取数据并解密,获取最终的用户数据.这样可以节省服务器开销.
cookie的删除
1) 可以通过在浏览器中设置来清除cookie.
(2) 使用Response的set_cookie进行清除
@app.route('/del_cookie')
def del_cookie():
response=make_response('delete cookie')
response.set_cookie('Name','',expires=0)
return response
(3)使用Response的 delete_cookie方法.
@app.route('/del_cookie2')
def del_cookie2():
response=make_response('delete cookie2')
response.delete_cookie('Name')
return response
cookie的其他属性
观察"Set-Cookie: name=test; Expires=Wed, 19-Sep-2018 03:42:31 GMT; Max-Age=200; Path=/" 可以看出其实cookie有很多属性,如下:
在chrome控制台中的resources选项卡中可以看到cookie的信息。
一个域名下面可能存在着很多个cookie对象。
name 字段为一个cookie的名称。
value 字段为一个cookie的值。
domain 字段为可以访问此cookie的域名。
非顶级域名,如二级域名或者三级域名,设置的cookie的domain只能为顶级域名或者二级域名或者三级域名本身,不能设置其他二级域名的cookie,否则cookie无法生成。
顶级域名只能设置domain为顶级域名,不能设置为二级域名或者三级域名,否则cookie无法生成。
二级域名能读取设置了domain为顶级域名或者自身的cookie,不能读取其他二级域名domain的cookie。所以要想cookie在多个二级域名中共享,需要设置domain为顶级域名,这样就可以在所有二级域名里面或者到这个cookie的值了。
顶级域名只能获取到domain设置为顶级域名的cookie,其他domain设置为二级域名的无法获取。
path 字段为可以访问此cookie的页面路径。 比如domain是abc.com,path是/test,那么只有/test路径下的页面可以读取此cookie。
expires/Max-Age 字段为此cookie超时时间。若设置其值为一个时间,那么当到达此时间后,此cookie失效。不设置的话默认值是Session,意思是cookie会和session一起失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此cookie失效。
Size 字段 此cookie大小。
http 字段 cookie的httponly属性。若此属性为true,则只有在http请求头中会带有此cookie的信息,而不能通过document.cookie来访问此cookie。
secure 字段 设置是否只能通过https来传递此条cookie
下面是flask中cookie对应属性的配置项
SECRET_KEY 密钥
SESSION_COOKIE_NAME 会话 cookie 的名称
SESSION_COOKIE_DOMAIN 会话 cookie 的域。如果没有设置的话, cookie 将会对 SERVER_NAME 所有的子域都有效。
SESSION_COOKIE_PATH 会话 cookie 的路径。如果没有设置或者没有为 '/' 设置,cookie 将会对所有的 APPLICATION_ROOT 有效。
SESSION_COOKIE_HTTPONLY 控制 cookie 是否应被设置 httponly 的标志, 默认为 True 。
SESSION_COOKIE_SECURE 控制 cookie 是否应被设置安全标志,默认为 False。
扩展
既然session依赖cookie,要是浏览器禁用了cookie改怎么达到状态保持的效果呢?
这个时候,就需要用到URL重写了,既让服务器收到的每个请求参数中都带有sessioinId,也就是从原本的隐式(headers传参)变为url或body传参。当我们清空浏览器的时候,session会消失吗?
这个问题包含着一些陷阱。因为很多时候当我们清空浏览器以后,确实需要重新登录系统才可以操作,所以很多人自然而然认为清空浏览器缓存(包含cookie)以后session就会消失。
其实这种结论是错误的。要知道,session是存在于服务器的,你清除浏览器缓存,只是清除了cookie,跟session一点关系都没有。那么为什么我们却不能访问网站,而需要重新登录了呢?因为清空了浏览器缓存,这时候cookie数组中必定不会有JSESSIONID这个cookie,所以必须得新建一个session,用新的sessionId来给JSESSIONID这个cookie赋值。由于是新建的session,session中必定没有userId这样的属性值,所以判断结果自然为空,所以需要重新登录。这次赋值以后,下一次再请求该网站的时候,由于cookie数组中已经有了JSESSIONID这个cookie,并且能通过该JSESSIONID的值找到相应的session,所以就不需要再重新登录了。
参考
- http://www.pythondoc.com/flask/config.html
- https://blog.csdn.net/qq_37526590/article/details/80219227
- https://www.cnblogs.com/keyi/p/6823853.html
为什么说session依赖cookie,以及cookie的常用知识的更多相关文章
- session依赖cookie,如果浏览器禁用了cookie呢?
我们都知道session依赖cookie,因为服务器需要在每次请求中获取sessionId,然后找到客户端的session对象,如果浏览器禁用了cookie呢? 这个时候,就需要用到URL重写了,这种 ...
- Django(十三)状态保持 —— cookie与session+ajax异步请求+session记住登录状态+cookie记住登录名密码
一.状态保持的概述 http协议是无状态的.下一次去访问一个页面时并不知道上一次对这个页面做了什么.因此引入了cookie.session两种方式来配合解决此问题. Duplicate entry:重 ...
- 【转】Session ID/session token 及和cookie区别
Session + Cookie 知识收集! cookie机制采用的是在客户端保持状态的方案.它是在用户端的会话状态的存贮机制,他需要用户打开客户端的cookie支持.cookie的作用就是为了解决 ...
- Session id实现通过Cookie来传输方法及代码参考
1. Web中的Session指的就是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间.因此从上述的定义中我们可以看到,Session实际上是一个特定的 ...
- Session的引入以及Cookie的不足
一.为什么引入session > Cookie实际上就是一个头. > 服务器会创建Cookie,并且将Cookie以一个响应头的形式发送给浏览器 > 浏览器收到Cook ...
- php使用CURL不依赖COOKIEJAR获取COOKIE的方法
本文实例讲述了php使用CURL不依赖COOKIEJAR获取COOKIE的方法.分享给大家供大家参考.具体分析如下: PHP中CURL类是一个非常牛逼的工具类,具体怎么牛逼就不啰嗦了. 对于COOKI ...
- session详解&和cookie的区别
session简介 1. 定义 session用来保存会话数据, 将数据保存到服务器中. 2. 作用 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),一个浏览器独占一 ...
- Java Web Application使Session永不失效(利用cookie隐藏登录)
在做 Web Application 时,因为 Web Project 有 session 自动失效的问题,所以如何让用户登录一次系统就能长时间运行三个月,就是个问题. 后来,看到 session 失 ...
- 07: jquery.cookie操作cookie
1.1 jquery.cookie常用方法 定义:让网站服务器把少量数据储存到客户端的硬盘或内存,从客户端的硬盘读取数据的一种技术 1. 添加一个"会话cookie" $.cook ...
随机推荐
- PAT——1018. 锤子剪刀布
大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示: 现给出两人的交锋记录,请统计双方的胜.平.负次数,并且给出双方分别出什么手势的胜算最大. 输入格式: 输入第1行给出正整数N( ...
- 【题解】洛谷P1941 [NOIP2014TG] 飞扬的小鸟(背包DP)
次元传送门:洛谷P1941 思路 从题意可知 在每个单位时间内 可以无限地向上飞 但是只能向下掉一次 所以我们可以考虑运用背包解决这道题 上升时 用完全背包 下降时 用01背包 设f[x][y]为在坐 ...
- jquery获取所有选中的checkbox
获取所有name为spCodeId的checkbox var spCodesTemp = ""; $("input:checkbox[name=spCodeI ...
- 《Linux 学习》01---redis安装, 并使用Redis Desktop Manager 连接
一.环境简介: linux 系统:centos 7.X 二.安装大纲: 1.下载安装包 2.安装 3.统一管理redis 配置文件 4.编辑redis配置文件,设置常用的功能 5.(1)命令启动,连接 ...
- linux系统基础之---系统基本安全(基于centos7.4 1708)
- Java 8 – Map排序
前提 Map是Java中最常用的集合类之一,这里整理了关于HashMap的排序 (关于List的排序,请查看Collections.sort()的doc或源码). 将无序的HashMap借助Strea ...
- Java代码注释
单行注释: 选中代码,按下ctrl+/ 一条代码单行注释:选中一条代码按下ctrl+/,则为一条代码单行注释: 多条代码单行注释:选中多条代码按下ctrl+/,则为多条代码单行注释: 取消注释:对已经 ...
- JavaScript脚本加载相关知识
<script>标签的位置 HTML4规范允许<script>可以放在<head>或<body>中. 但是,放在<head>中会导致性能问题 ...
- Linux phpmailer发送邮件失败的解决方法
(本地windows phpmailer发送ok 放到linux发送失败) 原因:linux 通过465端口进行更安全的SMTPS协议发送邮件 windows 是基于smtp 25端口的 因此 可 ...
- 「PHP」策略模式
引言 所属:行为型模式,常用设计模式之一 学习资料: <大话设计模式>程杰 模式概述 分享一篇关于策略模式讲的很好的文章,大家可以参考一下:https://www.cn ...