使用Flask/WTForms和React进行CSRF保护 [英] CSRF Protection with Flask/WTForms and React

查看:85
本文介绍了使用Flask/WTForms和React进行CSRF保护的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于通过React(作为受控组件)提交到Flask后端(理想情况下是使用WTForms)提交的表单,是否有人成功实现了CSRF保护?我已经看到了很多部分答案,其中一个是关于Django的答案,但是找不到任何适合Flask的东西.我的大问题似乎是我不知道如何将csrf令牌发送到我的react前端,在提交表单之前将其存储为标头,然后使用正确的令牌提交表单.任何方向都会很有帮助.

Has anyone successfully implemented CSRF protection for a form submitted with React (as a controlled component) to a Flask back-end (ideally with WTForms)? I've seen a lot of partial answers, and one with Django, but couldn't find anything definitive for Flask. My big issue seems to be that I don't know how to send the csrf token to my react front end, store it as a header before submitting my form, then submit my form with the correct token. Any direction would be really helpful.

推荐答案

所以,基本上,我所做的是我在Flask中设置了一条可以接收GET和POST请求的路由.当组件挂载时,React发送一个GET请求,并且Flask以csrf令牌作为头响应(手动完成).然后React将这个值存储在状态中.提交表单后,来自state的csrf令牌将作为字段发送,类似于在纯Flask应用程序中将其发送为隐藏字段的方式.尽管从技术上讲这是可行的,但我很好奇它是否仍然容易受到CSRF的攻击.我认为第二个最佳选择是在所有端点上设置CSRF保护,因此,如果这不安全,可以尝试一下.

So, essentially what I did is I set up a route in Flask that can receive both GET and POST requests. React sends a GET request when the component mounts, and Flask responds with the csrf token as a header (done manually). Then React stores this value in state. When the form is submitted, the csrf token from state is sent as a field, similar to the way it is sent in a pure Flask app, where it would be a hidden field. While this technically works, I am curious if this is still vulnerable to CSRF. I think the next best option is to set up CSRF protection on all endpoints, so can try that if this isn't secure.

烧瓶路线:

@app.route('/api/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    print(request.method)
    if request.method == 'GET':
        return ('', {'csrf_token': form.csrf_token._value()})
    elif form.validate_on_submit():
        return { 'message': 'Login successful' }, 200
    else:
        return { 'errors': form.errors }

在componentDidMount中获取请求:

GET request in componentDidMount:

componentDidMount() {
  axios.get('/api/login',{data: null, headers: {'Content-Type': 'application/json'}})
  .then(res => {
    console.log(res)
    this.setState({
      csrf: res.headers.csrf_token
    });
  }) 
}

提交表单后的POST请求:

POST request when form is submitted:

onSubmitLogin = e => {
  e.preventDefault();
  const userData = {
    username: this.state.username,
    password: this.state.password,
    csrf_token: this.state.csrf
  };
  axios({
    method: 'post',
    url: '/api/login',
    data: userData,
    headers: {
      'content-type': 'application/json'
    }
  })
  .then(res => {
    console.log(res);
  });
}

这篇关于使用Flask/WTForms和React进行CSRF保护的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆