14.Web框架

1.uwsgi,uWSGI,WSGI的关系

http协议
uwsgi协议
WSGI协议
客户端
Nginx服务器
uWSGI服务gunicorn,uwsgi
WSGI应用django,flask

uwsgi协议:一种二进制线路协议,不是通信协议uWSGI服务器与其他网络服务器的数据通信

uWSGI服务器:是一种web服务器,是实现了uwsgi和WSGI两种协议的Web服务器

WSGI协议:是一种Web服务器网关接口,定义了Web服务器如何与Python应用程序进行交互

2.csrf

2.1 CSRF定义

CSRF(Cross-site request forgery)攻击,中文名是跨站请求伪造

比如现在有两个网站,A网站是真实受信任的网站,而B网站是危险网站。

  • 当你登陆A网站后,浏览器会将A网站服务器给你生成的 sessionid 存入 cookie,有了这个 cookie,就拥有了你的帐号权限,以后请求访问,就不用再次登陆

  • 在cookie的过期时间之内,你去访问了恶意网站B,它给你返回一些恶意请求代码.要求你去访问网站A,这样你的浏览器就会在不知情的情况下去访问可信网站A

  • 然后网站A误以为是用户本身的操作,导致来自恶意网站B的攻击代码会被执:发邮件,发消息,修改你的密码,购物,转账,偷窥你的个人信息,导致私人信息泄漏和账户财产安全收到威胁

2.2 CSRF Token

  • 当用户请求一个更新用户名的页面时,由服务端生成一个随机数 Token,然后放入HTML表单中,并且会把这个 Token 放在 cookie 里发给浏览器
  • 当用户提交表单请求时,表单数据会带上这个 Token 发送给服务端,并且带上携带 token 的 cookie
  • 服务端收到表单请求后,会从表单数据里取出 Token,与 cookie 里的 token 进行对比,如果是一样的,就是合法的用户请求,将新的用户名存入数据库,如果不一样,那就是非法的请求,应当拒绝。

2.3 JWT

背景:如果浏览器禁用 cookie,或者多个服务器需要使用同一个CSRF Token值如何解决?

定义:jwt 全称JSON Web Token,JWT 的诞生并不是解决 CSRF 跨域攻击,而是解决跨域认证的难题

  • 用户以 Web表单 的形式,将自己的用户名和密码 POST 到后端的接口。
  • 后端核对用户名和密码成功后,会计算生成JWT Payload 字符串(具体计算方法,后续会讲,然后返回 response 给浏览器。
  • 浏览器收到 JWT 后,将其保存在 cookie 里或者 localStorage 或者 sessionStorage里(具体如何选,后面会说)
  • 后续在该域上发出的请求,都会将 JWT放入HTTP Header 中的 Authorization 字段。
  • 后端收到新请求后,会使用密钥验证 JWT 签名。
  • 验证通过后后端使用 JWT 中包含的用户信息进行其他相关操作,返回相应结果。

组成:头部.载荷.签名

  • 第一部分:头部(Header),Base64URL编码
  • 第二部分:载荷(Payload),Base64URL编码
  • 第三部分:签名(Signature)
JWT存储位置 JWT传输位置 攻击风险
cookie Header XSS
cookie HttpOnly cookie CSRF

1.Base64URL不同于 Base64 ,Base64 有三个字符+ / =,=被省略,+替换成,/替换成_

2.CSRF Token 和 JWT 虽然都可以做到防御 CSRF 攻击,但其实无论是哪个都无法同时做到防御 CSRF 和 XSS 攻击,在阻止了 CSRF 攻击后, 需要再通过其他手段来减少 XSS 攻击的可能性

3.payload 尽量不要存放敏感s

编码:

import jwt
import datetime
import uuid

salt = 'minggezuishuai'

# 构造header , 这里不写默认的也是
headers = {
    'typ': 'JWT',
    'alg': 'HS256'
}

# 构造payload
payload = {
    'user_id': str(uuid.uuid4()),  # 自定义用户ID
    'username': "wangbm",  # 自定义用户名
    'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=5)  # 超时时间,取现在时间,五分钟后token失效
}
token = jwt.encode(payload=payload, key=salt, algorithm="HS256", headers=headers).decode('utf-8')

测试

$ pyjwt --key="xiaopawnye" encode user_id=888f20d9-07ed-41bd-b329-17c6f058a14e username=wangbm exp=+120
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiODg4ZjIwZDktMDdlZC00MWJkLWIzMjktMTdjNmYwNThhMTRlIiwidXNlcm5hbWUiOiJ3YW5nYm0iLCJleHAiOjE1OTQ0MzQ4NTl9.A792th12kY1YnBWyVgbr5l6OQ5emRiETIjsnmIl4Ji8

解码

>>> import jwt
>>> token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiODg4ZjIwZDktMDdlZC00MWJkLWIzMjktMTdjNmYwNThhMTRlIiwidXNlcm5hbWUiOiJ3YW5nYm0iLCJleHAiOjE1OTQ0MzQzMjZ9.kkEMhSx732lO6HWWNPNVQDHR9WuCEVxKgNol-LTbCP8"
>>> jwt.decode(token, 'xiaopawnye', algorithms=['HS256'])
{'user_id': '888f20d9-07ed-41bd-b329-17c6f058a14e', 'username': 'wangbm', 'exp': 1594434326}

参考

1.手绘 10 张图,把 CSRF 跨域攻击、JWT 跨域认证说得明明白白的

3.XSS

XSS(Cross Site Scripting)跨站脚本攻击,XSS的重点不在于跨站点,而是在于脚本的执行

常见的 XSS 攻击有三种:反射型,DOM-based 型,存储型

常见的防护方法:任何时候用户的输入都是不可信的,理论上都要进行验证

4.SQL注入

定义:通过构造特殊的输入参数传入web应用

你可能感兴趣的:(2.Web框架-django,前端,python,django,web安全)