Python中的CSRF攻击与JSON Web Token验证
CSRF攻击(Cross-Site Request Forgery,跨站请求伪造)指的是攻击者在用户不知情的情况下,通过第三方站点向目标站点发送恶意请求,例如转账、更改密码等操作。为了避免这种攻击,通常会在表单中添加一个随机生成的token,而在提交表单时,只有当该token与服务器记录的token一致时,才会被服务器接受。
Python中可以使用Django框架提供的装饰器来自动添加token,使用方法如下:
from django.views.decorators.csrf import csrf_protect, csrf_exempt @csrf_protect # 添加CSRF token保护 def my_view(request): ... @csrf_exempt # 不添加CSRF token保护 def my_other_view(request): ...
其中,csrf_protect()
装饰器会自动在表单中添加token,而 csrf_exempt()
则会禁用该保护措施。
而在使用Ajax发送请求时,需要在请求头中添加 X-CSRFToken
字段,其值为当前页面的token。可以使用以下代码来获取token和发送POST请求:
// 获取token的值 var csrftoken = getCookie('csrftoken'); // 发送POST请求 $.ajax({ type: 'POST', url: '/my_url/', data: { name: 'pidancode.com', content: 'Hello, 皮蛋编程!' }, beforeSend: function(xhr, settings) { xhr.setRequestHeader("X-CSRFToken", csrftoken); }, success: function(result) { console.log(result); } }); // 获取cookie中的值 function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = $.trim(cookies[i]); // 在cookie中查找token if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; }
JSON Web Token(JWT)是一种用于身份验证的开放标准(RFC 7519),其使用JSON格式对信息进行编码,并约定由三部分组成:头部、载荷和签名。JWT的格式如下:
header.payload.signature
其中,头部用于指定加密算法等信息,载荷用于存储实际的信息,例如用户ID、权限等,而签名用于验证数据的完整性和真实性。
使用JWT验证步骤如下:
- 用户在登录时使用用户名和密码向服务器发送请求;
- 服务器验证用户名和密码是否匹配,如果匹配则生成一个JWT并返回给客户端;
- 客户端在以后每次向服务器发送请求时,在请求头中添加JWT;
- 服务器对JWT进行验证,验证成功则允许访问,否则拒绝访问。
Python中可以使用PyJWT包来生成、解析JWT,在安装PyJWT包后,可以使用以下代码生成一个JWT:
import jwt import datetime key = "my_secret_key" # 密钥,可以任意指定 payload = { 'user_id': 123, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30) # 有效期为30分钟 } token = jwt.encode(payload, key, algorithm='HS256')
在此代码中,jwt.encode()
函数用于生成JWT,其中 payload
参数为需要存储的信息,key
为密钥,用于签名,algorithm
为加密算法,常用的有HS256、RS256等。
在客户端收到JWT后,可以将其存储在cookie或localStorage中,以便以后使用。使用以下代码将JWT解析:
import jwt key = "my_secret_key" # 密钥必须与生成token时一致 token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsImV4cCI6MTYyMDA1MDY5NX0.APEeMR21jK5EnaSG5Z5TIAGnbctNnNWszL61zvbdgEU" payload = jwt.decode(token, key, algorithms=['HS256']) print(payload) # {'user_id': 123, 'exp': 1620050695}
在此代码中,jwt.decode()
函数用于解析JWT,其中 token
参数为待解析的JWT,key
为密钥,用于验证签名,algorithms
为加密算法。
因为JWT使用了Base64编码,所以 JWT不能存储敏感信息,不应该存储密码等机密信息。在使用JWT时,应该注意安全性问题。
相关文章