尝试向 Django 视图发出发布请求时出现错误:禁止(未设置 CSRF cookie。)

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

我正在尝试创建一个(chrome 扩展 + Django)密码管理器,它将从表单中读取输入框,然后单击“提交”,它将向 Django 视图发出 POST 请求,其中的数据将存储到 postgresql 数据库中。 (请记住,这只是一个个人项目。)

但在每个请求中,我都会收到错误:Forbidden(未设置 CSRF cookie。)。即使我在检查的“应用程序”选项卡下看到 csrftoken cookie。我将 csrf 令牌与请求一起传递,所以我无法弄清楚错误是什么。

我尝试使用 Cookies.get('csrftoken') 从 cookie 中获取 csrf 令牌,并在从 Django 获取后设置 csrf 令牌 cookie。

这就是我在 Django 中的视图:

@ensure_csrf_cookie
def add(request):
    if request.method == "POST":
        website = request.POST['website']
        username = request.POST['username']
        password = request.POST['password']
        user = request.user
        encryptedPass = cryptography.crypto(password)
        credentials = Credentials.objects.create(email=username, password=encryptedPass)
        if Website.objects.filter(user = user.id).filter(name=website).exists():
            website_obj = Website.objects.filter(user = user.id).filter(name=website)
            # print(website_obj[0].credentials)
            website_obj[0].credentials.add(credentials)
        else:
            website_obj = Website.objects.create(user=user, name=website)
            website_obj.credentials.add(credentials) 
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest': 
            return JsonResponse({'message':'Credentials Add'})      
        return redirect('add')
    return render(request,'add.html')

这是我将 csrf 令牌传递给 chrome 扩展的视图:

@ensure_csrf_cookie
def get_csrf_token(request):
    return JsonResponse({'csrfToken': django.middleware.csrf.get_token(request)})

我已经尝试了我的settings.py中的所有内容:

ALLOWED_HOSTS = []
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'corsheaders',
    'password_manager_app'
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_ALL_ORIGINS = True

CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SAMESITE = 'None'
CSRF_COOKIE_SECURE = False
CSRF_COOKIE_HTTPONLY = False
CSRF_TRUSTED_ORIGINS = ["*"]
CSRF_ALLOWED_ORIGINS = ["*"]
CSRF_COOKIE_DOMAIN = "*"

我正在 content-script.js 中使用 axios 发出发布请求:

export async function getCsrfToken(){
  const axios = require('axios')
  let token;
  const response = await axios.get('http://localhost:8000/get-csrf-token',{withCredentials:true}).then((response)=>{
    console.log(response.data.csrfToken)
    token = response.data.csrfToken
  })
  return token
}

export async function axiosaddCredentialsToDatabase(email,password,url){
  const token = await getCsrfToken()
  const axios = require('axios')
  axios.post('http://localhost:8000/add',{email,password,url},{
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'X-CSRFToken': token,
      'X-Requested-With': 'XMLHttpRequest',
    },
    withCredentials:true
  }).then((response)=>{
    console.log(response)
  })
}

如有任何意见,我将不胜感激。预先感谢:)

javascript django google-chrome-extension cors csrf
1个回答
0
投票

那是因为不知何故令牌没有被验证。

此外,不应只是为了检索此令牌而发送请求,Famework 中间件会将其设置为 cookie,因此您只需要检索它。否则,服务器将因令牌请求而过载(在现实世界环境中)。

这是一个最小的例子:

const getCookie = (name) => {
  let cookieValue = null;
  if (document.cookie && document.cookie !== "") {
    const cookies = document.cookie.split(";");
    for (let i = 0; i < cookies.length; i++) {
      const cookie = cookies[i].trim();
      if (cookie.substring(0, name.length + 1) === name + "=") {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
      }
    }
  }
  return cookieValue;
};

const csrftoken = getCookie("csrftoken");
const data = {
  email: "[email protected]",
  password: "supersecret",
  url: "https://example.com"
};
const headers = {
  "Content-Type": "application/json",
  "X-CSRFToken": csrftoken,
};

const sendRequest = async () => {
  try {
    const response = await axios.post("/add/", data, { headers });
    console.log(response.data);
  } catch (error) {
    console.log(error);
  }
};

sendRequest();
© www.soinside.com 2019 - 2024. All rights reserved.