I'm using python and urllib module to POST my credentials to a generic django view for loging in, that's all. I tried some stuff based on the standard basic authentification pattern, modifying the authenticate header.... but all the same, It keeps throwing me a 403 forbidden code. I searched for an answer that address this matter, but as to me.... I couldn't find any.
CODE
from django.contrib.auth import views
urlpatterns = [
path('accounts/login/', views.LoginView.as_view(template_name='accounts/login.html'), name='login'),
]
settings.py
"""
Django settings for tests project.
Generated by 'django-admin startproject' using Django 2.2.17.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'ukqp@#s^bo)wcl)qr#fc1%+-1rm(f1-6(8trin3rl)6=dbwt@9'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
LOGIN_REDIRECT_URL = '/catalog/'
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'catalog.apps.CatalogConfig',
'accounts.apps.AccountsConfig',
]
MIDDLEWARE = [
'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',
]
ROOT_URLCONF = 'tests.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'catalog.context_processors.muelte',
],
},
},
]
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
WSGI_APPLICATION = 'tests.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/
' My Attempt
import urllib.parse, urllib.request
base = 'http://localhost:8000/'
login_path = 'accounts/login/'
blurl = urllib.parse.urljoin(base, login_path)
headers = {
'username': 'l0new0lf',
'password': 'ColdSOul',
}
rq = urllib.request.Request(blurl, method='post', headers=headers)
print(urllib.request.urlopen(rq))
Traceback:
Traceback (most recent call last):
File "/home/l0new0lf/Desktop/algo.py", line 11, in <module>
print(urllib.request.urlopen(rq))
File "/usr/lib/python3.8/urllib/request.py", line 222, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python3.8/urllib/request.py", line 531, in open
response = meth(req, response)
File "/usr/lib/python3.8/urllib/request.py", line 640, in http_response
response = self.parent.error(
File "/usr/lib/python3.8/urllib/request.py", line 569, in error
return self._call_chain(*args)
File "/usr/lib/python3.8/urllib/request.py", line 502, in _call_chain
result = func(*args)
File "/usr/lib/python3.8/urllib/request.py", line 649, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden
####EDIT 1####
I noted i was missing csrf token, added it to POST headers, but still the same error. Though this approach doesnt work, because AFAIK each csrf token is generated for each request independently.
import urllib.parse, urllib.request
from bs4 import BeautifulSoup
base = 'http://localhost:8000/'
login_path = 'accounts/login/'
blurl = urllib.parse.urljoin(base, login_path)
headers = {
'username': 'l0new0lf',
'password': 'ColdSOul',
}
get_rq = urllib.request.urlopen(blurl)
soup = BeautifulSoup(get_rq.read(), features='lxml')
form = soup.select_one('form')
csrf = form.select_one('form input[name^="csrf"]')
headers.update(((csrf['name'], csrf['value']),))
rq = urllib.request.Request(blurl, method='post', headers=headers)
print(urllib.request.urlopen(rq))
PD: I don't come across this problem only when authenticating, but also in POSTing any data to any view. Also, i do accept answers based on requests module too, if more convenient.
Many thanks in advance.