auth模块
内容概要
- csrf跨站请求伪造
- csrf相关校验策略
- CBV添加装饰器的多种方式
- auth认证模块
csrf跨站请求伪造
钓鱼网站:模仿一个正规的网站 让哟ing胡在该网站上做操作 但是操作的结果会影响到用户正常的网站账户 但是其中有一些猫腻
模拟钓鱼网站案例:转账案例
原网站
def tans_func(request):
if request.method == 'POST':
user1 = request.POST.get('user1')
user2 = request.POST.get('user2')
money = request.POST.get('money')
print('[%s]向[%s]转账[%s]' % (user1, user2, money))
return render(request, 'tans.html')
<form action="" method="post">
<p>转账人
<input type="text" name="user1">
</p>
<p>收款人
<input type="text" name="user2">
</p>
<p>转帐金额
<input type="text" name="money">
</p>
<input type="submit">
钓鱼网站
def tans_func(request):
return render(request, 'tans.html')
<form action="http://127.0.0.1:8000/tans/" method="post">
<p>转账人
<input type="text" name="user1">
</p>
<p>收款人
<input type="text">
<input type="text" name="user2" value="wewe" style="display: none">
</p>
<p>转账金额
<input type="text" name="money">
</p>
<input type="submit">
</form>
csrf校验伪造
在提交数据的位置添加唯一标识
就是我们以前会注释的那个csrf
那个中间件现在加了{%csef_token%}
就可以不用注释
作用就是判断你是不是我自己的页面发送过来的请求,如果是就处理,不是就不处理
1.form表单csrf策略
在form表单内部添加 {% csef_token %}
2.ajax请求
方式1:自己动手取值 较为繁琐
data:{'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val(),},
就是拿到它的值
方式2:利用模板语法自动获取(一定要用引号引起来)
data:{'csrfmiddlewaretoken':'{{ csrf_token }}',},
方式3:直接引入一个js脚本即可(官方提供的)
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
把这的写到js
文件里面然后导入一下就可以了
csrf相关装饰器
整个django项目都校验csrf
到那时某些视图函数\类不想校验
整个django项目都不想校验csrf
但是某些视图函数\类需要校验
FBV添加装饰器的方式(与正常函数添加装饰器一样)
from django.views.decorators.csrf import csrf_exempt, csrf_protect
@csrf_protect # 需要csrf 校验
def tans_func(request):
if request.method == 'POST':
user1 = request.POST.get('user1')
user2 = request.POST.get('user2')
money = request.POST.get('money')
print('[%s]向[%s]转账[%s]' % (user1, user2, money))
return render(request, 'tans.html')
不需要csrf
校验
from django.views.decorators.csrf import csrf_exempt, csrf_protect
@csrf_exempt # 不需要csrf 校验
def tans_func(request):
if request.method == 'POST':
user1 = request.POST.get('user1')
user2 = request.POST.get('user2')
money = request.POST.get('money')
print('[%s]向[%s]转账[%s]' % (user1, user2, money))
return render(request, 'tans.html')
CBV添加装饰器的方法
CBV添加装饰器的方法(与正常的情况不一样 需要注意)
方式一(单独生效)
from django import views
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt, csrf_protect
class MyClass(views.View):
@method_decorator(csrf_protect)
def post(self, request):
user1 = request.POST.get('user1')
user2 = request.POST.get('user2')
money = request.POST.get('money')
print('[%s]向[%s]转账[%s]' % (user1, user2, money))
return render(request, 'tans.html')
def get(self, request):
return render(request, 'tans.html')
方式二(单独生效)
@method_decorator(csrf_protect, name='post')
只给这个类下面的post
方法添加装饰器
方式三(全局生效)
@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
pass
这是给这个类里面的所有方法都添加上装饰器
注意有一个装饰器是特例只能有一种添加方式
csrf_exempt
只有在dispatch
方法中添加才会生效
auth认证模块
前戏:django自带一个admin
路由 但是需要我们提供管理员账号和密码
如果想要使用admin
后台管理 需要先创建表 然后创建管理员账号
直接执行数据库迁移命令即可默认的auth_user表 该表就是admin后台管理默认的认证表
-
创建超级管理员
python38 manage.py createsuperuser
基于auth_user
表编写用户相关的各项功能
登录、校验用户是否登录、修改密码、注销登录等
auth认证相关模块及操作
-
注册
User.object.create_user(username=username, password=password')
from django.contrib import auth from django.contrib.auth.models import User def register_func(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') User.objects.create_user(username=user, password=pwd) return HttpResponse('注册成功') return render(request, 'register.html')
他会自动给你加密
-
判断用户名和密码是否正确
auth.authenticate(requser,username=username, password=password)
登录成功后返回客户端登录凭证
auth.login(request, user_obj)
def login_func(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') # 1. 校验用户名和密码是否正确(不分开校验) 自己无法比对密码 必须使用auth模块 user_obj = auth.authenticate(request, username=user, password=pwd) if user_obj: print(user_obj, type(user_obj)) print(user_obj.username, type(user_obj.username)) # 2.用户登录成功(返回给客户端登录凭证,随机字符串) auth.login(request, user_obj) return HttpResponse('登录成功') else: return HttpResponse('用户名或密码错误') return render(request, 'login.html')
-
判断用户是否登录
request.user.is_authenticated
def home_func(request): if request.user.is_authenticated: print(request.user.is_authenticated) return HttpResponse('这是home页面') else: return redirect('/login/')
返回的是一个布尔值
-
获取登录用户对象数据
request.user
def home_func(request): # 获取当前登录用户 print(request.user) print(request.user.username) return HttpResponse('这是home页面')
-
校验用户是否登录装饰器
from django.contrib.auth.decorators import login_required @login_required(login_url='/login/') @login_required 全局配置 配置文件中LOGIN_URL = '/login/'
from django.contrib.auth.decorators import login_required # 如果没有登录则跳转到 /login/ @login_required(login_url='/login/') # 局部配置 def home_func(request): return HttpResponse('这是home页面')
-
校验原密码是否正确
request.user.check_password
(原密码)修改密码
request.user.set_password(新密码) requser.user.save()
@login_required(login_url='/login/') def set_password_func(request): if request.method == 'POST': old_pwd = request.POST.get('old_pwd') new_pwd = request.POST.get('new_pwd') # 判断原密码是否正确 if request.user.check_password(old_pwd): # 修改密码 request.user.set_password(new_pwd) # 写入数据库 request.user.save() return HttpResponse('修改密码成功') else: return HttpResponse('原密码错误') return render(request, 'setPassword.html')
-
退出登录
auth.logout(request)
也就是把那条标识登录的
cookie
给删除了
扩展auth_user表
还想使用auth模块的功能 并且又想扩展auth_user表的字段
思路1:一对一字段关联
思路2:替换auth_user
表
步骤1:模型层编写模型类继承AbstractUser
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
phone = models.CharField(max_length=11, null=True)
desc = models.CharField(max_length=32, null=True)
步骤2:一定要在配置文件中声明替换关系
AUTH_USER_MIDEL = 'app01.UserInfo'
ps:替换还有一个前提 就是数据库迁移没有执行过(auth相关表没有创建)