Я использую версию django 2.1.7 и python 3.6.5, расширяю пользовательскую модель django с помощью AbstractUser и перезаписываю метод аутентификации django. Кажется, что все работает нормально до входа в систему, но когда страница перенаправляет на домашний запрос. Пользователь становится нулевым.
Я попытался выполнить рендеринг вместо перенаправления, похоже, это работает, но затем, когда я открываю одну и ту же страницу в другой вкладке или обновляю страницу, я получаю 403 запрещенную ошибку (проверка CSRF завершилась неудачно. Запрос отменен.)
Пробовал приведенные ниже настройки, но все равно не работает
CSRF_COOKIE_SECURE = False
SESSION_COOKIE_SECURE = False
settings.py
LOGIN_URL = '/'
LOGIN_REDIRECT_URL = 'home'
AUTH_USER_MODEL = 'hygie_portal.CustomUser'
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'hygie_portal',
'django_assets',
]
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',
]
AUTHENTICATION_BACKENDS = (
'hygie_portal.mybackend.MyBackEnd',
)
models.py
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
is_admin = models.IntegerField(blank=True, null=True)
role = models.CharField(max_length=256, blank=True, null=True)
def set_is_admin(self, is_admin):
self.is_admin = is_admin
def set_role(self, role):
self.last_update = datetime.now()
self.role = role
forms.py
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.forms import TextInput,EmailInput,PasswordInput
CustomUser = get_user_model()
class LoginForm(forms.Form):
"""Login form."""
username = forms.CharField(label='Username', max_length=100)
password = forms.CharField( widget=forms.PasswordInput())
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ('username',)
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ('username', 'email')
admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
CustomUser = get_user_model()
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['username',]
admin.site.register(CustomUser, CustomUserAdmin)
urls.py
app_name = "hygie_portal"
urlpatterns = [
path("", views.login_request, name='login'),
path(r'login/', RedirectView.as_view(url='/login/')),
path('home/', views.home, name='home'),
]
view.py
from django.contrib.auth import get_user_model
CustomUser = get_user_model()
@csrf_protect
def login_request(request):
if request.user.is_authenticated:
return render(request, 'users/home_public.html')
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user_info = MyBackEnd.authenticate(encode(username), encode(password), request=request)
if not user_info:
messages.error(request,'Invalid username or password. Please try again.')
return redirect('hygie_portal:login')
is_admin = True if 'manager' in user_info['role'] else False
try:
user_profile = CustomUser.objects.get(username=username)
except:
user_profile = ''
if not user_profile:
if 'name' in user_info:
try:
fname = user_info['name'].split()[0]
except IndexError:
fname = ''
try:
sname = user_info['name'].split()[1]
except IndexError:
sname = ''
else:
fname, sname = '', ''
user_profile = CustomUser(username=username, email=user_info['email'], first_name=fname, last_name=sname, role=user_info['role'])
user_profile.save()
try:
user_profile.set_is_admin(is_admin)
user_profile.set_role(user_info['role'])
user_profile.save()
except Exception as e:
logger.error('Exception updating user****' % e)
login(request, user_profile, backend='hygie_portal.mybackend.MyBackEnd')
#After login request.user.is_authenticated returns true
#return redirect('hygie_portal:home') #when redirected to home request.user.is_authenticated returns False
return render(request, 'users/home_public.html') #works fine, but throws 403 error when page is refreshed or url accessed in different tab
form = LoginForm()
if form.errors:
messages.error(form.errors, 'danger')
flash(form.errors, 'danger')
# default to login page if not authenticated or no form submit.
return render(request, 'public/login.html',{'form': form})
def home(request):
if request.user.is_authenticated:
return render(request, 'users/home_public.html')
else:
return redirect('hygie_portal:login')
mybackend.py
class MyBackEnd(object):
def authenticate(username, password, request=None):
bind_attr = settings.AD_BIND_ATTR
user_dn = settings.AD_DN
login_attr = '(%s=%s)' % (settings.AD_LOGIN_ATTR, username)
data = get_bind_user(username) #returns the user info with role permissions
if len(data) == 0:
return None
if 'mail' not in data:
logger.warning('No email found in AD, adding dummy email')
info['name'] = data['cn'][0] if 'cn' in data else None
info['email'] = data['mail'][0] if 'mail' in data else 'nomail@xx.com'
try:
info['phone'] = data['telephoneNumber'][0]
except KeyError:
info['phone'] = 'Not Available'
try:
info['role'] = data['role']
except KeyError:
info['role'] = False
conn = ldap.initialize(settings.AD_URL)
conn.set_option(ldap.OPT_REFERRALS,0)
conn.set_option(ldap.OPT_PROTOCOL_VERSION, settings.LDAP_PROTOCOL_VERSION)
try:
conn.bind_s(data[bind_attr][0].decode(), password)
conn.search(user_dn, ldap.SCOPE_SUBTREE, login_attr, None)
conn.result()
return info
except (ldap.INVALID_CREDENTIALS, ldap.OPERATIONS_ERROR):
logger.info('Invalid credentials for :%s' % username)
return None
def get_user(self, username):
try:
return CustomUser.objects.get(username=username)
except CustomUser.DoesNotExist:
return None
Я видел в документации django, что login () сохранит идентификатор пользователя для всего сеанса. Я хочу, чтобы сеанс был доступен на разных вкладках после входа пользователя в систему.
Я пытался проверить детали сеанса с помощью request.session, но я не знаю, как использовать его в моем коде.