【Django】Day3-視圖-登錄功能

Django視圖

一.登錄系統

1.寫一個表格

對於一個登錄系統來說,首頁是一個登錄頁面

<html>
<head>
<title>Django Page</title>
</head>
<body>
<h1>發佈會管理</h1>
<form>
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password"><br>
<button id="btn" type="submit">登錄</button>
</form>
</body>
</html>
  • 增加get方法
<html>
<head>
<title>Django Page</title>
</head>
<body>
<h1>發佈會管理</h1>
<form method="get">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password"><br>
<button id="btn" type="submit">登錄</button>
</form>
</body>
</html>

但是get方法對於信息傳遞是沒有加密的,所以應該使用post方法

  • 增加post方法
    把表格請求的方法換成post
“CSRF verification failed. Request aborted.”

但是之後請求的時候會出現報錯,這個是CSRF攻擊,通過僞裝成受信任用戶的請求來利用受信任的網站,如果攻擊者針對站點僞造鏈接,當該站點的用戶點擊該鏈接,且該站點使用的是持久化的cookies策略,攻擊者就會獲取用戶認證信息,進行攻擊,當然,這裏也可以不用管。

  • Django對CSRF的保護
    Django 針對CSRF 的保護措施是在生成的每個表單中放置一個自動生成的令牌,通過這個令牌判斷POST請求是否來自同一個網站。

所以這裏使用了Django的模板標籤(template tag)添加CSRF令牌,在form表單裏面添加{% csrf_token %}

<html>
<head>
<title>Django Page</title>
</head>
<body>
<h1>發佈會管理</h1>
<form action="/login_action/">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password"><br>
<button id="btn" type="submit">登錄</button>
    {% csrf_token %}
</form>
</body>
</html>

這樣在頁面想Django服務器發送Post請求的時候,客戶端會加上一個srfmiddlewaretoken字段,給當前會話ID加上密鑰

2.處理登錄請求

  • 指定提交路徑
    對於form表單提交的數據,我們需要指定提交路徑,修改form的路徑
<form method="post" action="/login_action/">
  • 新增login_action路由
    打開urls.py文件
from blog import views
urlpatterns = [
……
path(r'login_action/', views.login_action),
]
  • 新增視圖函數
    在view文件中增加login_action函數
def login_action(request):
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        if username == 'test' and password == 'test123':
            return HttpResponse('login success!')
        else:
            return render(request,'index.html', {'error': 'username or password error!'})
    else:
        return render(request, 'index.html', {'error': 'username or password error!'})

這裏通過HttpResponse類返回一個登錄成功的信息;然後通過render方法給login頁面返回一個錯誤信息

  • 在index頁面增加錯誤提示
<form method="post" action="/login_action/">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password"><br>
{{ error }}<br>
<button id="btn" type="submit">登錄</button>
{% csrf_token %}
</form>

這裏使用了Django的模板語言 {{ error }},對應着之前render返回的字典中error的value

3.登錄成功頁

  • 修改login sucess
    這裏要修改成一個新的函數來處理登錄成功的信息,修改登錄成功的操作
def login_action(request):
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        if username == 'test' and password == 'test123':
            return HttpResponseRedirect('/event_manage/')
        else:
            return render(request,'index.html', {'error': 'username or password error!'})
    else:
        return render(request, 'index.html', {'error': 'username or password error!'})

這裏使用的是HttpResponseRedirect類,對頁面進行重定向,可以將之前登錄成功的結果重定向到/event_manage/路徑,然後可以創建event_manage 函數,用於返回發佈會管理event_manage.html 面頁。

  • 在view中新增函數
def event_manage(request):
    return render(request,"event_manage.html")
  • 在urls中新增event_manage路由
path(r'event_manage/', views.login_action),

4.代碼更新

這裏項目的源碼更新到了github

二.Cookie 和Session

1.Cookie 和Session基本概念

這裏可以看http協議基礎

2.使用Cookie增加一個用戶名

本節使用Cookie和Session來實現一個功能——
假如用戶通過“zhangsan”登錄,然後,在登錄成功頁顯示“嘿,zhangsan 你好!

  • 獲取暱稱
    這裏是修改login_action,傳遞數據
def login_action(request):
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        if username == 'test' and password == 'test123':
            response = HttpResponseRedirect('/event_manage/')
            # 添加瀏覽器cookie(key value 過期時間)
            response.set_cookie('user', username, 3600)
            return response
        else:
            return render(request,'index.html', {'error': 'username or password error!'})
  • 得到暱稱
    修改event_manage來獲取數據
def event_manage(request):
    username = request.COOKIES.get('user', '')  # 讀取瀏覽器cookie(key)停留時間
    return render(request, "event_manage.html", {"user": username})

  • 展示暱稱
    這裏需要修改獲取的數據的模板event_manage.html
<html>
<head>
<title>Event Manage Page</title>
</head>
<body>
<h1>Login Success!</h1>
<div style="float:right;">
<a>嘿!{{ user }} 歡迎</a><hr/>
</div>
</body>
</html>

然後登錄成功的時候就可以展示登錄成功的用戶暱稱

3.修改成Session展示

使用Cookie來存儲數據顯而易見是不夠安全的,所以我們需要使用Session,把數據存在服務端,以防攻擊者修改數據

login_action修改

修改

response.set_cookie('user', username, 3600)

request.session['user'] = username # 將session 信息記錄到瀏覽器
event_manage修改

修改

username = request.COOKIES.get('user', '')

username = request.session.get('user', '') # 讀取瀏覽器session

但是還沒完,需要補充數據表

創建django_session表

對於session來說,服務端來存儲用戶的sessionId等數據,Django是一個服務端,所以我們需要一個django_session表來存儲數據

  • 生成數據表,通過“migrate”命令進行數據遷移
python manage.py migrate

這裏在setting文件中有一個默認配置DATABASES。

然後重新登錄即可

通過Chrome瀏覽器的抓包工具可以看到,在登錄的時候接口傳遞的由cookie變成了session

三.Django認證系統

之前只是對登錄的功能實現了驗證,但是用戶名密碼是在代碼中寫死的,這裏我們需要增加用戶數據

1.配置用戶

首先先新建一個超級管理員帳戶

python manage.py createsuperuser
Username (leave blank to use 'fnngj'): admin #輸入用戶名
Email address: admin #輸入郵箱
Password: #輸入密碼
Password (again): #重複輸入密碼
Superuser created successfully.

然後就可以登錄到admin頁面

然後使用超級用戶登錄到對應的admin頁面,增加用戶組,增加用戶,並設置用戶狀態,最後這個用戶可以登錄併到該頁面

2.引用Django的認證登錄

修改登錄邏輯

from django.contrib import auth

def login_action(request):
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        user = auth.authenticate(username=username,password=password)
        if user is not None:
            # 新增登錄驗證邏輯
            auth.login(request, user)
            request.session['user'] = username
            response = HttpResponseRedirect('/event_manage/')
            return response
        else:
            return render(request,'index.html', {'error': 'username or password error!'})

使用authenticate方法,用戶名存在的話返回一個User對象,不存在會返回None;如果返回的不是就會返回None

3.加上登錄限制

在之前的設計中,可以直接通過路徑跳轉到登錄成功的頁面,我們需要對路徑進行限制

下面是對登錄頁限制

from django.contrib.auth.decorators import login_required

@login_required
def event_manage(request):
username = request.session.get('user', '')
return render(request,"event_manage.html",{"user":username})

增加之後,之間通過瀏覽器請求http://127.0.0.1:8000/event_manage/頁面將會返回一個失敗提示。
可以看到這裏配置的accounts/login是一個默認路徑跳轉

http://localhost:8000/accounts/login/?next=/event_manage/

然後把這個跳轉等價

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/',views.archive),
    path('index/',views.index),
    path('accounts/login/',views.index),
    path('login_action/', views.login_action),
    path('event_manage/', views.event_manage),
]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章