CSRF 会话令牌丢失错误。使用 axios 的 Expressjs 应用程序。不使用表格

问题描述 投票:0回答:1

我一直对这个错误消息感到抓狂。请耐心等待,因为我只是没那么聪明。 我有一个用 python 制作的 Flask 应用程序,并在应用程序中启用了 CSRFProtect。

Python 中的 Web 服务

'''Using flask to create the python ws'''
from flask import Flask, request, session
from flask_cors import CORS
from flask_wtf.csrf import CSRFProtect
from dotenv import dotenv_values
from Validator import geia_std_xsd_validation

# returns a dict of the values contained within the .env file
config = dotenv_values('.env')


ALLOWED_EXTENSIONS = {'xml'}

APP = Flask(__name__)
SECRET_KEY = 'test12'
csrf = CSRFProtect()
origin_array = config['WHITELIST_ARRAY']
cors = CORS(APP, origins=origin_array, expose_headers=['Content-Type', 'X-CSRFToken'], supports_credentials=True)
csrf.init_app(APP)
APP.config['SECRET_KEY'] = SECRET_KEY


APP.vars = {}

def allowed_file(filename):
    """
    Checks to make sure the uploaded file is in the list of allowed extensions.
    """
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

# Do we need this?
@APP.route('/', methods = ['GET'])
def server_up():
    '''This method handles the calls to our ws'''
    if request.method == 'GET':
        return {
            "message": APP.config.get('WTF_CSRF_FIELD_NAME'),
            'sesh': session
        }

@APP.before_request
def test():
    session['csrf_token'] = 'test12'
    print('before')

@APP.route('/xsd_validator', methods = ['POST'])
# @csrf.exempt # we'll figure this out later...
def xsd_validation():
    '''This method handles the calls to our ws'''
    if request.method == 'POST':
        print('HITTING')
        # If there isn't a file in the request.
        if len(request.files) <= 0:
            print('No files in response')
            return 'No file sent'

        # # Set the file from the request.
        file = request.files['testFile']

        # # Make sure we have a filename so we can check extension.
        if file.filename == '':
            print('Blank filename')
            return 'Invalid filename'

        # # If there is a file and we allow that file type then validate it against the schema.
        if file and allowed_file(file.filename):
            print('Got into the file statement')
            file_text = file.read()
            errors = geia_std_xsd_validation(file_text)
            return errors

    return 'Nothing Happened'


if __name__ == "__main__":
 // APP.run(//the sauce)

我有另一个用expressjs制作的Web服务,它将使用一个文件来访问此Web服务,以使用此功能进行xml验证

const testTHATSHIZZLE = async (req, res) => {
  const csrf = 'test12'
  const file = req.files.testFile
  const name = file.name

  // not recognizing blob D:
  const submittedFile = new FormData()
  const arrayBuffer = Uint8Array.from(file.data).buffer
  const nodeBuffer = Buffer.from(arrayBuffer)
  // const fileBlob = new Blob([file.data])
  submittedFile.append('testFile', nodeBuffer, name)
  await axios.post('https://localhost:6030/xsd_validator', submittedFile, {
    csrf_token: csrf,
    withCredentials: true,
    headers: {
      'X-CSRFToken': csrf,
      'Content-Type': 'multipart/form-data'
    }
  }).then(response => {
    res.send(response.data)
  }).catch(error => {
    console.log(error)
    res.send(error)
  })
}

仅对于基线而言,当 csrf.exempt 在我需要的路线上方取消注释时,这完全有效。 但是当为路由启用 csrf 时,我得到了

bad request 400 error CSRF session token missing. 
我正在到处寻找,但我就是无法弄清楚这一点。当我将 Flask 应用程序放入调试器并尝试查看有哪些会话变量时,它是一个空的 ImmutableDict。正如您所看到的,我在标题下设置 csrf 测试器令牌,并将 withCredentials 添加到 axios 调用中。 Flask 应用程序已启用 cors 并支持凭据。

我对 axios 和我的 Flask 应用程序如何交互感到非常困惑。我可以在 GET 路由的 before_request 方法中设置会话变量,但在我点击 POST 路由之前它会失败。并不是说我认为我应该这样做。我只是想测试一下。

session中没有其他变量吗?

我不知道我是否调用了这个错误,但我希望有人了解更多关于从不使用 Flask 表单的外部 Web 服务中使用 csrf 保护的 Flask 应用程序。

我已经尝试浏览 gitlab repo forflask-wtf 并查看 csrf.py,但这只是告诉我这应该已经可以工作了。我不知道为什么当我进行 axios 调用时,会话没有建立。

csrf flask-wtforms
1个回答
0
投票

每次需要通过 axios (xmlhttprequest) 发送表单时,客户端应向服务器请求新的 crsf 令牌

你的配置:

# your settings.py
SESSION_PROTECTION = "strong"

# help prevent XSS. 
SESSION_COOKIE_HTTPONLY = True

# you will want to set this to False during development.
# this is due to the lack of SSL during development.
SESSION_COOKIE_SECURE = True

您还需要启用 CSRF 保护。这是使用 Flask-wtf 包完成的。

from flask_wtf import CSRFProtect

crsf = CSRFProtect(app) 
# or crsf = CSRFProtect()
# csrf.init_app(app)
# if you're using factory config.

获取 csrf 令牌的示例端点。

from flask_wtf.csrf import generate_csrf

@app.route("/csrf")
def get_csrf():
    response = jsonify(detail="success")
    response.headers.set("X-CSRFToken", generate_csrf())
    return response

现在在您的客户端应用程序上,例如 React、Vue 等。例如,使用 axios,您可以将其添加到您的 index.js 中,以确保对该域发出的每个请求都包含该特定域可用的所有 cookie。

axios.defaults.withCredentials = true

或对于每个请求:

withCredentials: true,

或通过代码块:

const instance = axios.create({
  withCredentials: true
})

最后是客户:

const testTHATSHIZZLE = async (req, res) => {

  const instance = axios.create({
      withCredentials: true
  })

  const file = req.files.testFile
  const name = file.name

  // not recognizing blob D:
  const submittedFile = new FormData()
  const arrayBuffer = Uint8Array.from(file.data).buffer
  const nodeBuffer = Buffer.from(arrayBuffer)
  // const fileBlob = new Blob([file.data])
  submittedFile.append('testFile', nodeBuffer, name)
  // we get new crsf token (instance refer to axios withCredentials: true)
  const response  = await instance.get('https://localhost:6030/csrf', { withCredentials: true })
  // we do request
  await instance.post('https://localhost:6030/xsd_validator', submittedFile, {
    withCredentials: true,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  }).then(response => {
    res.send(response.data)
  }).catch(error => {
    console.log(error)
    res.send(error)
  })
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.