目录
扩展方式二 : 继承 AbstractUser 类来扩写 (步骤)
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding, 缩写为:CSRF/XSRF
CSRF可以用来做钓鱼网站: 假设是一个和银行一模一样的网址页面,用户在该页面上转账账户的钱就会减少,三十受益人却不是自己指定想要转账的那个人.
你可以这么理解CSRF共计:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你的名义发送邮件,发信息,盗取你的账号,甚至于购买商品,虚拟货币转账...造成的问题包括:个人隐私泄露以及财产安全
一台计算机上的两个服务端口启动,钓鱼网站提交地址改为正规网站的地址
用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
消息[msg]:而msg本身也有两部分组成:一部分:随即字符串,过期时间戳。
分隔符[separator]:用于分割msg部分与加密后生成的signature签名部分,这里用的是"."
签名[signature]:singnature.signature签名,是对“msg消息”用特定算法进行加密后的字符串
token = base64(msg)格式化..base64(sha256("密码",msg))
Token由被base64的msg编码穿+256加密msg再进行Base64编码,两个字符串的内容结合
- <h1>这是一个真实的网站h1>
- <form action="" method="post">
- {% csrf_token %}
- form>
方法一:先编写csrf模板语法,然后利用标签查找和值获取,手动添加
data:{'username':'','csrmiddlewaretoken':$('[name="csrmiddlewaretoken"]').val()},
方法二:直接利用模板语法即可
data:{'username':'','csrfmiddlewaretoken':'{{ csrf_token }}'},
方法三:通用方法(js脚本)CV大法即可
更多详情请见: https://docs.djangoproject.com/en/1.11/ref/csrf/
-
- 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);
- }
- }
- });
1.当整个网站默认都不校验csrf,但是有局部视图函数需要校验
关键字:@csrf_protect
2.当整个网站默认都校验csrf,但是有局部视图函数不需要校验
关键字:@csrf_exempt
3.两种装饰器的使用
先导入装饰器:
form django.views.decorators.csrf import csrf_protect,csrf_exempt
4.针对FBV添加装饰器
- @csrf_protect
- def home(request):
- return HttpResponse('哈哈哈')
-
- @csrf_exempt
- def index(request):
- return HttpResponse('嘿嘿嘿')
5.针对CBV不能直接在方法上添加装饰器,需要借助专门添加装饰器的方法mothod_decorator
- from django import views
- from django.utils.decorators import method_decorator
6.针对CBV添加装饰器
- @method_decorator(csrf_protect, name='post') # 方法二:指名道姓的添加
- class MyHome(views.View):
- @method_decorator(csrf_protect) # 影响类中所有的方法
- def dispatch(self, request, *args, **kwargs):
- super(MyHome, self).dispatch(request, *args, **kwargs)
-
- def get(self, request):
- return HttpResponse('Home Get view')
-
- @method_decorator(csrf_protect) # 方法一:直接在该函数头上添加
- def post(self, request):
- return HttpResponse('Home Post view')
7.针对csrf_exempt这个装饰器只有方法三有效,其他的装饰器上述方法都可以直接使用(包括自定义装饰器)
1.我们在开发一个网页的时候无可避免的需要设计实现网站的用户系统,此时我们需要实现包括用户注册、用户登录、注销、修改密码等功能。为了节省这个麻烦的过程,Django自带了强大的用户认证系统Auth,它默认使用auth_user表来存储用户的数据。
2.该表还是Django admin后台管理默认的表
django admin后台管理员账号创建
3.创建方法:
python manage.py createsuperuser
4.导入auth模块
from django.contrib import auth
| 字段 | 释义 |
|---|---|
| id | ID |
| password | 密码 |
| last_login | 最后登录时间 |
| is_superuser | 是否是管理员 |
| username | 用户名 |
| first_name | 姓 |
| last_name | 名 |
| 邮箱 | |
| is_staff | 是否是工作人员 |
| is_active | 是否激活 |
| date_joined | 创建时间 |
- from django.contrib.auth.models import User
- 1.普通用户
- user = User.objects.create_user(username='用户名',password='密码',...)
- 2.管理员用户,必须要有email
- user = User.object.create_superuser(username='用户名',password='密码',email='邮箱',...)
1.作用:提供了用户认证功能,即验证用户名以及密码是否正确
2.必须传入两个参数:username & password
3.校验成功返回True,失败返回None
- from django.contrib import auth
- user_obj = auth.authenticate(request,username=username,password=password)
- if user_obj:
- print(user_obj.username)
- print(user_obj.password)
- else:
- print('验证失败')
1.作用:该函数接受了一个HttpResponse对象,以及一个经过认证的User对象
2.实现一个用户登录功能,本质上会在后端为用户生成session数据存在于session表中
3.只要执行了该方法,你就可以在任何地方通过request.user获取到当前登录的用户对象,否则拿到的就是一个匿名用户对象也就是none
auth.login(request,user_obj) # 内部调用的就是request.session['key']=user_obj
1.作用:用来判断当前请求是否用过了认证
视图中使用
- if not request.user.is_authenticated():
- print('未登入,请先登入')
模板中使用
- {% if request.user.is_authenticated %}
- {{ request.user.username }} 欢迎回家
- {% else %}
- {% endif %}
1.作用:获取当前登录的用户对象
user_obj = request.user
1.作用:一个装饰器工具,用来快捷的给某个视图添加登录校验
from django.contrib.auth.decorators import login_required
使用方式一: 直接在视图函数上添加
- @login_required(login_url='/login/') # 需要指定url
- @login_required # 全局配置
- def logout_func(request):
- auth.login(request)
- return redirect("/login/")
-
方法二:在配置文件中全局配置
LOGIN_URL = '/login/'
1.作用:提供一个检查密码是否正确的方法,需要提供当前请求用户的密码
2.密码正确返回True,否则返回False
if user.check_password('你的密码old_password')
print('ok')
1.作用:提供一个需要改密码的方法,接受要设置新密码作为参数
2.设置完一定要调用用户对象的save方法
request.user.set_password(new_password)
request.user.save()
1.作用:该函数接收一个HttpResponse对象,无返回值
2.当调用该函数时,当前请求的session信息会全部清除,该用户既没有登录,使用该函数也不会报错
auth.login(request) # 内部使用的就是request.session.flush()
1.models.py
- from django.contrib.auth.models import AbstractUser
-
- class Userinfo(AbstractUser):
- '''扩展auth_user表中没有的字段'''
- phone = models.BigIntegerField()
- desc = models.TextField()
2.setting.py
AUTH_USER_MODEL = 'app01.Userinfo'
1.1import 句式
1.2from ... import ...
1.3类似中间件功能的导入方式(importlib)
- s1 = 'dajngo.bbb.b'
- print(s1.rsplit('.',maxsplit=1)) # 底层原理
- import importlib
- res = importlib.import_module(s1) # 自动将点号做标记来切割 from bbb import b
- print(res.name)
2.1简单的函数式封装
- def send_qq(content):
- print('qq消息通知:',content)
-
- def send_wx(content):
- print('微信消息通知:',content)
-
- def send_mag(content):
- print('短信消息通知:',content)
-
-
- def seed_all(content):
- send_qq(content)
- send_wx(content)
- send_mag(content)
-
-
- if __name__ == '__main__':
- seed_all('累了,毁灭吧')
auth_user 中的字段有限, 想要在 auth_user 表中添加新的字段, 我们可以对其进行扩展。
新建一个模型类, 比如要添加 Phone 字段, 在该模型内中写入, 并添加 User 的外键字段
- from django.contrib.auth.models import User
- class user_detail(models.Model):
- user=models.OneToOneField(to='User')
- phone=models.CharField(max_length=32)
1. 首先大前提是没有生成 auth_user 表(也就是没进行数据库迁移操作)(有的话需要删干净迁移记录和表)
2. 书写一个类, 并继承 AbstractUser 类
3. 在类中可以书写你需要扩展的字段, 也可以重写原来的字段
- class MyAuthUser(AbstractUser):
- username=models.CharField(max_length=12) # 重写字段
- phone=models.CharField(max_length=32) # 书写新字段
-
4. 到 setting.py 配置文件中设置 AUTH_USER_MODEL 参数, 不然报错
- AUTH_USER_MODEL = "[app名].[类名]"
- AUTH_USER_MODEL = "app01.MyAuthUser" # 示例
-
5. 最后进行数据库迁移命令
- python3 manage.py makemigrations
- python3 manage.py migrate
1. 先删库
2. 并清空项目中所有的 makemigrations 而来的迁移记录
3. 再清空源码中admin,auth俩app的 makemigrations 产生的记录