[英]Flask JWT Extended missing csrf access token
我的 flask 应用程序使用 JWT 作为身份验证手段。 这些令牌存储在 cookies 中,flask-jwt-extended 配置为使用它们。 对于常规的 GET 请求,身份验证工作正常, @jwt_required
装饰器能够从 cookies 读取令牌并对用户进行身份验证。 但是,当使用fetch()
发出 AJAX POST 请求时,扩展程序无法读取它们并返回Missing CSRF token
错误。 奇怪的是,当在 POST 路由中访问请求 object 时,所有必需的 cookies 以及所有其他路由中都存在,这意味着fetch()
正确设置了所有必需的 cookies:
ImmutableMultiDict([
('csrftoken', 'valid_csrf_token'),
('session','valid_session_cookie'),
('access_token_cookie', 'valid_access_token'),
('csrf_access_token', 'valid_csrf_access_token')
])
Flask POST 路线:
@main.route("/sendmail", methods=["POST"])
@jwt_required()
async def send_mail():
data = json.loads(request.data)
mail_template = render_template("mail-view.html", data=data)
pdf_report = pdfkit.from_string(mail_template, False)
message = Message(
subject="Flask-Mailing module",
recipients=["recepient-mail@domain.com"],
body="Message body",
subtype="html",
)
message.attach("report.pdf", pdf_report)
await mail.send_message(message)
return jsonify({"message": "success"}), 200
获取请求:
fetch(window.location.origin + "/sendmail", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "same-origin",
body: JSON.stringify(mail),
})
我的应用程序配置 object:
class DevConfig:
SECRET_KEY = os.environ.get("SECRET_KEY")
JWT_SECRET_KEY = os.environ.get("JWT_SECRET_KEY")
JWT_COOKIE_SECURE = False
SESSION_COOKIE_SECURE = False
JWT_TOKEN_LOCATION = ["cookies"]
JWT_ACCESS_TOKEN_EXPIRES = datetime.timedelta(hours=1)
MAIL_SERVER = "smtp.googlemail.com"
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USE_SSL = False
MAIL_USERNAME = os.environ.get("MAIL_USERNAME")
MAIL_PASSWORD = os.environ.get("MAIL_PASSWORD")
MAIL_FROM = os.environ.get("MAIL_USERNAME")
使用 flask-jwt-extended 默认设置,CSRF-Token 只需要为 state 更改请求方法(除“GET”之外的所有内容)发送。 这就是为什么即使没有 CSRF 令牌也可以授权“GET”方法的原因。 其次,CSRF-Token 的整个想法是不通过 web 浏览器自动发送它,因此它不被 cookie 接受:
默认情况下,我们通过在有人登录时设置两个 cookies 来完成此操作。第一个 cookie 包含 JWT,并编码为 JWT 是双重提交令牌。 此 cookie 设置为仅限 http,因此无法通过 javascript 访问(这是防止 XSS 攻击能够窃取 JWT 的原因)。 我们设置的第二个 cookie 仅包含相同的双重提交令牌,但这次是在 javascript 可读的 cookie 中。 每当发出请求时,都需要包含一个 X-CSRF-TOKEN header,以及双重提交令牌的值。 如果此 header 中的值与存储在 JWT 中的值不匹配,则请求被踢出无效。
https://flask-jwt-extended.readthedocs.io/en/stable/token_locations/
因此,每当您发送请求时,都应将 CSRF-Token 添加到标头中:
fetch(window.location.origin + "/sendmail", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": getCookie("csrf_access_token"),
},
credentials: "same-origin",
body: JSON.stringify(mail),
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.