CSRF跨域請求保護(hù)
A站為正常網(wǎng)站,B站為病毒網(wǎng)站,當(dāng)我先訪問A站可柿,本地瀏覽器會記錄cookies
在本地,之后訪問B站丙者,B站會竊取我的cookies
复斥,然后通過我的cookies
就可以冒名訪問A站中我的賬戶。這就是CSRF
跨站請求偽造攻擊械媒。
在Django
的form
表單提交時目锭,如果是POST
方法提交,會引發(fā)CSRF
跨域請求保護(hù)纷捞,解決方法為:在form
表單中添加{% csrf_token %}
,打開網(wǎng)站就會在頁面生成token
(令牌)來進(jìn)行認(rèn)證痢虹,當(dāng)別人登錄會,頁面會生成完全不一樣的token
主儡,登錄時抓包會發(fā)現(xiàn)提交的form
表單中會有csrfmiddlewaretoken
這么一項奖唯。
HTML 的登錄表單
<!-- html中的登錄表單-->
<form class="form-signin" role="form" method="post" action="{% url 'login' %}">
{% csrf_token %}
<h2 class="form-signin-heading">Please sign in</h2>
<input name="username" type="email" class="form-control" placeholder="Email address" required="" autofocus="">
<input name="password" type="password" class="form-control" placeholder="Password" required="">
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<span style="color: red" >{{ login_err }}</span>
</form>
登錄功能的實現(xiàn)
當(dāng)點擊登錄時,會將表單提交到urls.py
中的別名為login
的url
來處理糜值,如:
...
urlpatterns = [
...
url(r'^login/', views.login_site, name='login'),
url(r'^logout/', views.logout_site, name='logout'),
]
處理邏輯為:如果方式為Post
丰捷,獲取到提交的username
和password
坯墨,然后通過django
的authenticate
方法來驗證。
# 導(dǎo)入的login 和 logout 用來實現(xiàn)保持session
from django.contrib.auth import authenticate, login, logout
def login_site(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password) # 使用 Django 的 authenticate 方法來驗證
if user:
login(request, user) # <==
return HttpResponseRedirect('/')
else:
return render(request, 'login.html', {
'login_err': 'Please recheck your username or password !'
})
return render(request, 'login.html')
登出功能
def logout_site(request):
logout(request) # <==
return HttpResponseRedirect('/')
HTML 頁面驗證是否登錄
頁面中需要根據(jù)是否登錄來顯示登錄狀態(tài)瓢阴,登錄顯示登錄的用戶名畅蹂,未登錄顯示login
...
<ul class="nav navbar-nav navbar-right">
<!-- 驗證是否已經(jīng)登錄-->
<!-- 如果沒有登錄,則展示登錄鏈接-->
{% if not request.user.is_authenticated %}
<li>
<a href="{% url 'login' %}">Login</a>
</li>
{% else %}
<!-- 如果已經(jīng)登錄荣恐,則展示用戶名和下拉菜單-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">{{ request.user.name }}<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="#">個人信息</a></li>
<li class="divider"></li>
<li><a href="{% url 'logout' %}">Logout</a></li>
</ul>
</li>
{% endif %}
</ul>
...
強(qiáng)制登錄
網(wǎng)站很多頁面我們需要用戶登錄才能展示,或者說打開網(wǎng)站時累贤,必須先登錄叠穆。可以進(jìn)行如下兩步設(shè)置:
第一步:在settings.py
文件中寫明當(dāng)用戶未登錄就訪問網(wǎng)站時的跳轉(zhuǎn)路徑臼膏。
# settings.py 文件中
LOGIN_URL = '/login/'
第二步:在需要登錄才能打開的頁面中使用login_required
裝飾器
from django.contrib.auth.decorators import login_required
@login_required
def dashboard(request):
return render(request, 'dashboard.html')
...
...