用戶登陸驗證問題及auth模塊的引入

1、本身實現登陸驗證
2、Django自帶的用戶驗證模塊——auth
3、本身動手解決auth不足的地方
 
 
 
1、本身實現登陸驗證

需求:一共有index和login兩個頁面,若是用戶沒有登陸訪問index頁面,則會自動跳轉到login頁面進行登陸,用戶在login登陸以後,會跳轉到index頁面,頁面出現歡迎用戶字樣
分析:數據庫和session相結合,能夠實現不一樣用戶顯示不一樣歡迎字樣。不過本身寫裝飾器太多麻煩,並且若是用戶多的話session的驗證重複步驟就比較多
 
1.寫入函數
#views.py
 
from functools import wraps    
 
def check_login(f):
    @wraps(f)    #取消裝飾器裝飾完成以後,函數名稱改變的問題
    def inner(request, *args, **kwargs):
        if request.session.get("is_login") == "1":    # 若是session中(is_login)對應的value爲1,就執行f()函數,不然,返回登陸頁面
            return f(request, *args, **kwargs)
        else:
            return redirect("/login/")
    return inner
 
def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")    #從html中拿到用戶輸入的帳號和密碼
 
        user = models.User.objects.filter(username=username, password=password)      # 從數據庫中拿到帳號和密碼和用戶輸入一致的數據
        if user:    #若是有,則證實用戶帳號密碼正確,若是沒有,就返回登陸頁面
            # 登錄成功
            request.session["is_login"] = "1"    #爲此次登陸設置一個session,key爲is_login,value爲'1'
            # request.session["username"] = username   
            request.session["user_id"] = user[0].id    # 爲此次登陸設置一個session,key爲username,value爲數據庫中本帳號密碼保存的id
            # 寫上面的一條代碼,django後臺自動作的事情
            # 1. 生成特殊的字符串
            # 2. 特殊字符串當成key,在數據庫的session表中對應一個session value
            # 3. 在響應中向瀏覽器寫了一個Cookie Cookie的值就是 特殊的字符串
            return redirect("/index/")
    return render(request, "login.html")
 
@check_login    #裝飾器,檢測用戶是否登陸,若是登陸,就執行index函數,若是沒有,就跳轉到登陸頁面
def index(request):
    user_id = request.session.get("user_id")
    # 根據id去數據庫中查找用戶
    user_obj = models.User.objects.filter(id=user_id)    # 設置session的時候,把數據庫中的id設爲了session中的key,目的就是在這裏再次獲得id,從數據庫中拿出其它數據
    if user_obj:
        return render(request, "index.html", {"user": user_obj[0]})
    else:
        return render(request, "index.html", {"user": "匿名用戶"})
 
2.補充index.html頁面
# index.html
 
<!DOCTYPE html>
<html>
<head>
    <title>index</title>
</head>
<body>
<h3>This is a test page!</h3>
hello,{{ user.username }}!    # 替換登陸的名字
</body>
</html>
 
3.建立數據表
# models.py
 
class User(models.Model):
    id = models.AutoField(primary_key=True)
    username = models.CharField(max_length=20, null=False)    
    password = models.CharField(max_length=20, null=False)
 
 
 
2、Django自帶的用戶驗證模塊——auth

在使用這個被前輩們封裝好的模塊以前,咱們仍是先來學習一下模塊的基本使用方法吧!
 
1.建立超級用戶
python manage.py createsuperuser
# 超級用戶數據表(auth_user)是django自動幫忙建立的,可是不能夠直接往裏面寫入數據哦!
# 由於直接寫入的話,密碼是明文顯示的,而通常來講,密碼須要以加密形式保存到數據庫中
# 如:username='username', password='$MqFtX/a3inUsPdJekYDMh8H4ZkohfCl3Lc4Vj5jZuNI='
 
2.authenticate()
from django.contrib import auth    #導入auth模塊
# 驗證用戶名和密碼,若是驗證成功,獲得的是一個用戶對象,若是驗證失敗,獲得的是匿名用戶,取它的任意字段都是空
auth.authenticate(username='theuser',password='thepassword')
若是認證信息有效,會返回一個  User  對象。authenticate()會在User 對象上設置一個屬性來標識後端已經認證了該用戶,且該信息在後續的登陸過程當中是須要的。
 
3.login(HttpRequest, user)
auth.login(request, user)
# 將驗證的用戶注入request.user屬性
# 該函數接受一個HttpRequest對象,以及一個認證了的User對象
# 此函數使用django的session框架給某個已認證的用戶附加上session id等信息。
from django.contrib.auth import authenticate, login
   
def my_view(request):
  username = request.POST['username']
  password = request.POST['password']
  user = authenticate(username=username, password=password)
  if user is not None:
    login(request, user)
    # Redirect to a success page.
    ...
  else:
    # Return an 'invalid login' error message.
    ...
 
4.logout(request) 註銷用戶
# 該函數接受一個HttpRequest對象,無返回值。
# 當調用該函數時,當前請求的session信息會所有清除。
# 該用戶即便沒有登陸,使用該函數也不會報錯。
from django.contrib.auth import logout
   
def logout_view(request):
  logout(request)
  # Redirect to a success page.
 
5.user對象的 is_authenticated()
要求:
1  用戶登錄後才能訪問某些頁面,
2  若是用戶沒有登陸就訪問該頁面的話直接跳到登陸頁面
3  用戶在跳轉的登錄界面中完成登錄後,自動訪問跳轉到以前訪問的地址
方法1:
def my_view(request):
  if not request.user.is_authenticated():
    return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
方法2:
from django.contrib.auth.decorators import login_required
      
@login_required    # django已經爲咱們設計好了一個用於此種狀況的裝飾器:login_requierd()
def my_view(request):
  ...
 
# 若用戶沒有登陸,則會跳轉到django默認的登陸URL '/accounts/login/ ' 
# 默認url能夠在settings.py文件中經過LOGIN_URL進行修改( 在settings.py中加入 LOGIN_URL = '/login/'
# 登錄成功後,會重定向到該路徑
注意:
1. 若是是真正的 User 對象,返回值恆爲 True 。 用於檢查用戶是否已經經過了認證。經過認證並不意味着用戶擁有任何權限,這個方法甚至也不檢查該用戶是否處於激活狀態,只是代表用戶成功的經過了認證。
2. 這個方法很重要, 在後臺用request.user.is_authenticated()判斷用戶是否已經登陸,若是true則能夠向前臺展現request.user.name
 
6.使用create_user輔助函數建立用戶
def register(request):
    from django.contrib.auth.models import User
    user = User.objects.create_user(username='abcd', password='999999999')    # 這裏把它寫死了,實際中要從頁面中post過來,獲得用戶輸入的帳號和密碼
    # user = User.objects.create_user(username='',password='',email='')    # email能夠不寫,password至少8個字符,password用哈希算法保存到數據庫
    # 這裏建立用戶一共有三種:1. create() 密碼明文保存; 2. create_superuser() 建立超級用戶 3. create_user() 建立普通用戶
    return HttpResponse('successful!')
 
7.使用check_password(passwd)檢查密碼
def register(request):
    from django.contrib.auth.models import User
    user_obj = User.objects.create_user(username='abcd', password='999999999')
    user_obj.check_password('888888888')    # --->返回false
    user_obj.check_password('999999999')    # --->返回true,爲了演示,這裏一樣也把數值給寫死了
 
8.使用 set_password() 來修改密碼
user = User.objects.get(username='')    # 獲得要修改密碼的對象
user.set_password(password='')    # 從新設置密碼
user.save()    # 保存
 
 
 
3、auth_user字段不夠的解決方案

 
1.一對一表
from django.contrib.auth.models import User
 
class UserDetail(models.Model):
    phone = models.CharField(max_length=11)
    user = models.OneToOneField(to=User)    #這裏關聯的User就是上面導入的User
 
2.類的繼承(繼承auth_user表)
from django.contrib.auth.models import User, AbstractUser
 
class UserInfo(AbstractUser):
    phone = models.CharField(max_length=11)
# 若是使用繼承的方式,須要在settings.py中配置 默認用戶認證時使用的是哪張表
# AUTH_USER_MODEL = 'app01.UserInfo'
# 另外使用這種方法以前,要把auth本身建立的user表刪除才能夠
# 做用:替代auth_user並擴展功能
 
 
 
 
4、未處理的兩點內容

is_staff : 用戶是否擁有網站的管理權限.
is_active : 是否容許用戶登陸, 設置爲``False``,能夠不用刪除用戶來禁止 用戶登陸
 
簡單示例
def sign_up(request):
    state = None
    if request.method == 'POST':
        password = request.POST.get('password', '')
        repeat_password = request.POST.get('repeat_password', '')
        email=request.POST.get('email', '')
        username = request.POST.get('username', '')
        if User.objects.filter(username=username):
                state = 'user_exist'
        else:
                new_user = User.objects.create_user(username=username, password=password,email=email)
                new_user.save()
                return redirect('/book/')
    content = {
        'state': state,
        'user': None,
    }
    return render(request, 'sign_up.html', content) 
 
註冊示例代碼
@login_required
def set_password(request):
    user = request.user
    state = None
    if request.method == 'POST':
        old_password = request.POST.get('old_password', '')
        new_password = request.POST.get('new_password', '')
        repeat_password = request.POST.get('repeat_password', '')
        if user.check_password(old_password):
            if not new_password:
                state = 'empty'
            elif new_password != repeat_password:
                state = 'repeat_error'
            else:
                user.set_password(new_password)
                user.save()
                return redirect("/log_in/")
        else:
            state = 'password_error'
    content = {
        'user': user,
        'state': state,
    }
    return render(request, 'set_password.html', content)
相關文章
相關標籤/搜索