目录

一、跨站请求伪造(csrf)

1. 什么是csrf

  • csrf是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任
  • 跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的

2. 钓鱼网站原理

  • 钓鱼网站利用的就是csrf

  • 通过开发一个和正规网站一模一样的页面,当用户不经意点击进去后,用户以为这就是正规的网站(因为长得都一样)。此时用户可能会在这个虚假的网页上做一些操作,最后往后端提交数据时,虚假网站其实对用户提交的数据做一定的篡改,再往正规网站后端提交。

  • 如何实现(以银行转账为例)

    • 钓鱼网站的页面写form表单的时候,让用户填写的对方账户input并没有name属性
    • 而是在内部偷偷隐藏了一个具有name属性的input,并且value值是钓鱼网站的账户

3. 如何解决csrf

(1)思路:

  • 让正规网站只处理由本正规网站发送来的post请求,不处理其他网站发送来的post请求。
  • 但是此思路有个问题:如何识别、判断当前请求是由本网站发出的

(2)实现方法

  • 当用户发送get请求想要获取到正规网站的页面时,正规网站返回给用户html页面时,会自动在该页面的源码中隐藏一个input框
  • 这个框的value是一个随机字符串,并且网站自己也保留同样的一个这个字符串
  • 当用户发送post请求时,后端会自动校验request.POST中的随机字符串是否和网站之前保存的随机字符串相同
  • 相同则处理该post请求,不同则返回403错误页面。

(3)实现的具体代码

  • 基于该项目是django项目

  • 分为2种情况的post请求

    • form表单发送post请求
    • ajax发送post请求

1. 针对form表单发送的post请求

  • 在写form表单的时候,你只需要在表单中写一个{% csrf_token %}即可
<form action="" method="post">
{% csrf_token %}
<p>username:<input type="text" name="username"></p>
<p>target_account:<input type="text" name="target_user"></p>
<p>money:<input type="text" name="money"></p>
<input type="submit">
</form>

2. 针对ajax发送post请求

  • 有3中书写方式。推荐使用第三种,最为通用
  1. 第一种(较繁琐)
先在页面任意的位置上书写{% csrf_token %}

然后在发送ajax请求的时候 通过标签查找获取随机字符串添加到data自定义对象即可

data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},
  1. 第二种(较简单)
先在页面任意的位置上书写{% csrf_token %}

然后在发送ajax请求的时候 通过标签查找获取随机字符串添加到data自定义对象即可

data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
  1. 第三种(最通用)
直接新建js文件拷贝官方代码,再在html文件中导入即可
你不需要做任何的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);
}
}
});

3. csrf相关的装饰器

  • 在django的项目中,django有一个中间件,专门用来处理csrf。
  • 这里django中提供的装饰器分为两种:
    • 对post请求进行csrf处理:csrf_protect
    • 忽略对post请求的csrf处理:csrf_exempt

(1)csrf_protect装饰器

  • 分为对FBV和CBV的装饰

1. 对FBV的装饰

  • 直接装饰在视图函数上即可
# 应用文件夹的views文件中

from django.views.decorators.csrf import csrf_protect

@csrf_protect  # 直接装饰在视图函数上
def index(request):
return HttpResponse('index')

2. 对CBV的装饰

  • 给CBV加装饰器的三种方式都可以
# 应用文件夹的views文件中

from django.views.decorators.csrf import csrf_protect
from django.views import View
from django.utils.decorators import method_decorator @method_decorator(csrf_protect,name='post') # 1. 可以
class MyIndex(views.View):
# @method_decorator(csrf_protect) # 2. 可以
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return render(request,'transfer.html')
# @method_decorator(csrf_protect) # 3. 可以
def post(self,request):
return HttpResponse('OK')

(2)csrf_exempt装饰器

  • 分为对FBV和CBV的装饰

1. 对FBV的装饰

  • 直接装饰在视图函数上即可
# 应用文件夹的views文件中

from django.views.decorators.csrf import csrf_protect

@csrf_exempt  # 直接装饰在视图函数上
def index(request):
return HttpResponse('index')

2. 对CBV的装饰

  • 注意:给CBV加装饰器的三种方式中,只有给dispatch方法装才有效
from django.views.decorators.csrf import csrf_protect
from django.views import View
from django.utils.decorators import method_decorator # @method_decorator(csrf_exempt,name='post') # 1. csrf_exempt不支持该方法
@method_decorator(csrf_exempt,name='dispatch') # 2. 可以
class MyIndex(views.View):
# @method_decorator(csrf_exempt) # 2. 可以
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return render(request,'transfer.html')
# @method_decorator(csrf_exempt,name='post') # 3. csrf_exempt不支持该方法
def post(self,request):
return HttpResponse('OK')

二、django的settings源码剖析

  • django有两个配置文件

    • 一个是直接暴露给用户,支持用户修改配置
    • 一个是内部全局的(隐藏的)
  • 当django项目启动时,先加载全局的配置,再加载局部的配置(即暴露给用户的配置)。如果两者有重复的,则局部覆盖全局的配置。

1. 模仿django的settings源码设计自定义settings

# 新建两个conf文件夹,conf1中新建一个settings.py文件,conf2中新建一个global_settings.py文件,且conf2文件夹中含有__init__.py文件。settings.py当做暴露给用户的 ,global_settings.py当做全局的

# 与conf1,conf2同一级中,新建一个启动文件start.py

# dir(obj) 作用是列出obj中所有的名字,保存成列表

# settings.py文件中
NAME = '我是暴露给用户的自定义配置' # global_settings.py文件中
NAME = '我是项目默认的配置文件' # conf2文件夹中的__init__.py文件中
import importlib
from conf2 import global_settings
import os class Settings(object):
def __init__(self):
# 先将全局中的global_settings.py文件中的配置内容加载进来
for name in dir(global_settings):
if name.isupper():
setattr(self,name,getattr(global_settings,name)) # 获取暴露给用户的配置文件字符串路径
module_path = os.environ.get('xxx')
md = importlib.import_module(module_path) # md = settings
# 再将局部中的settings文件中的配置内容加载进来,有和全局配置相同的就覆盖掉全局的
for name in dir(md):
if name.isupper():
k = name
v = getattr(md,name)
setattr(self,k,v) settings = Settings() # start.py文件中
import os
import sys BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR) # pycharm会自动将根目录添加到环境变量,但是其他开发环境可能没有这个功能,所以为了更加安全完善。这里要写这样一句话,把根目录添加到环境变量 if __name__ == '__main__':
# os.environ.setdefault('xxx','conf1.settings') # 等价于下一行
os.environ['xxx'] = 'conf1.settings' # environ 就是一个大字典
from conf2 import settings
print(settings.NAME)

三、django的auth模块

  • 在使用auth模块的时候,要用就用全套(即不要一会用普通的方法来操作表,一会又用auth模块的方法来操作。类似面向对象中,子类重用父类的方法时, super().__init__(要重用的属性)父类.__init__(self,要重用的属性)这两个也不能混用)

1. 使用终端如何创建超级用户:

python manage.py createsuperuser

2. auth模块常用方法

(1)创建用户

from django.contrib.auth.models import User
User.objects.create(username=username,password=password) # 不可用 保存的密码不是加密的
User.objects.create_user(username=username,password=password) # 创建普通用户 密码自动加密
User.objects.create_superuser(username='nick',password='123',email='123@qq.com') # 创建超级用户 必须要有邮箱数据

(2)校验用户名和密码是否正确

from django.contrib import auth

user_obj = auth.authenticate(request,username=username,password=password)  # 必须传用户名和密码两个参数,缺一不可,返回布尔值

(3)保存用户登录状态

  • 执行下面的代码后,会自动设置session并保存在django_session表中。还会把当前的用户对象保存在request.user中。
from django.contrib import auth

auth.login(request,user_obj)  # 只要这句话执行了,后面在任意位置,只要你能拿到request你就可以通过request.user获取到当前登录的用户对象。且该方法有一个返回值,会返回用户对象

(4)判断当前用户是否登录

request.user.is_authenticated()  # 返回布尔值

(5)校验密码

request.user.check_password(old_password)

(6)修改密码

request.user.set_password(new_password)
request.user.save() # 千万不要忘了

(7)注销

from django.contrib import auth

auth.logout(request)

(8)登录装饰器

  • 装饰器的配置有两种:局部配置和全局配置。(配置的作用是如果没有登录的用户访问需要登录的功能时,会将用户的浏览器页面跳转到指定的页面。配置里面书写的就是要跳转的url)

    • 局部配置:只对装饰器装饰的函数有效
    • 全局配置:对所有被装饰函数都有效
    • 注意:如果全局配置了,局部也配置了 ,则以局部的为准
# 1. 局部配置

# views文件中:
from django.contrib.auth.decorators import login_required @login_required(login_url='/login/')
def index(request):
pass # 2. 全局配置:需要在settings文件中配置一些数据 # settings配置文件中 直接配置
LOGIN_URL = '/login/' # views文件中:
from django.contrib.auth.decorators import login_required
@login_required
def index(request):
pass
# 如果全局配置了 局部也配置 以局部的为准

3. 扩展auth_user表字段

  • 有两种方式

    1. 利用一对一外键字段,再创建一张表保存新的字段

    2. 利用继承关系,重写auth_user

(1)方式一

class UserDetail(models.Model):
phone = models.BigIntegerField()
user = models.OneToOneField(to='User')

(2)方式二

  • 注意:如果要扩展auth_user表,必须在项目第一次执行数据库迁移命令时,将下面的模型类写好。(即如果已经执行完数据库迁移命令生成auth_user表后,再想扩展表字段,方式二是无法实现的)

  • 注意:下面创建模型类后,还需要去settings文件中配置(AUTH_USER_MODEL = 'app01.Userinfo' # 应用名.表名,这么写完之后,你新建的Userinfo表会代替原来的auth_user表,之前所有的auth模块功能全都以你写的表为准)

from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):
phone = models.BigIntegerField() # 新增字段phone
register_time = models.DateField(auto_now_add=True) # 新增字段register_time

跨站请求伪造(csrf),django的settings源码剖析,django的auth模块的更多相关文章

  1. django之跨站请求伪造csrf

    目录 跨站请求伪造 csrf 钓鱼网站 模拟实现 针对form表单 ajax请求 csrf相关的两个装饰器 跨站请求伪造 csrf 钓鱼网站 就类似于你搭建了一个跟银行一模一样的web页面 , 用户在 ...

  2. PHP安全编程:跨站请求伪造CSRF的防御(转)

    跨站请求伪造(CSRF)是一种允许攻击者通过受害者发送任意HTTP请求的一类攻击方法.此处所指的受害者是一个不知情的同谋,所有的伪造请求都由他发起,而不是攻击者.这样,很你就很难确定哪些请求是属于跨站 ...

  3. 跨站请求伪造(CSRF)-简述

    跨站请求伪造(CSRF)-简述 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 ...

  4. 跨站请求伪造(CSRF)攻击原理解析:比你所想的更危险

    跨站请求伪造(CSRF)攻击原理解析:比你所想的更危险 跨站请求伪造(Cross-Site Request Forgery)或许是最令人难以理解的一种攻击方式了,但也正因如此,它的危险性也被人们所低估 ...

  5. 跨站请求伪造(csrf)中间件整理

    一. CSRF中间件 字面意思跨站请求伪造; 即模仿个请求朝服务器发送,django中对跨站伪造的请求有相应的校验 from django.views.decorators.csrf import c ...

  6. 跨站请求伪造 CSRF / XSRF<一:介绍>

    跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一 ...

  7. 跨站请求伪造CSRF(Cross-site request forgery)

    CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站 ...

  8. 跨站请求伪造(csrf)的防护手段

    CSRF CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造. CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求. 造成的问题:个人隐私泄露以及财产安全. CS ...

  9. 跨站请求伪造CSRF:攻击与防御

    CSRF是什么         (Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一,也被称为&quo ...

随机推荐

  1. pytorch基础问题

    本文将自己在pytorch学习中遇见的各种问题整理起来,并且持续更新. 1:torch.Tensor和torch.tensor的区别 开始使用torch.tensor和torch.Tensor的时候发 ...

  2. 【DSP开发】【Linux开发】Linux下PCI设备驱动程序开发

    PCI是一种广泛采用的总线标准,它提供了许多优于其它总线标准(如EISA)的新特性,目前已经成为计算机系统中应用最为广泛,并且最为通用的总线标准.Linux的内核能较好地支持PCI总线,本文以Inte ...

  3. 【Spring Cloud】Spring Cloud使用总结

    项目概要 项目环境信息 IDEA ultimate 2018.3.2 springboot 2.1.7.RELEASE springCloud Greenwich.SR2 Eureka 介绍 基于ne ...

  4. 卸载pkg安装包

    1 基本原理 1.1 查看某个pkg安装包安装的所有文件 第一,查看所有安装的pkg $ pkgutil --pkgs 第二,查看指定pkg的所有安装文件 $ pkgutil --files the- ...

  5. java-selenium三种等待方式

    方式1: 线程等待:Thread.sleep(xxxx) 只要在case中加入sleep就会强制等待设置的时间后才会执行之后的命令,这种等待一般适用于调试脚本的时候. java代码 //等待3秒 Th ...

  6. .Net Core Web应用加载读取Json配置文件

    ⒈添加Json配置文件并将“复制到输出目录”属性设置为“始终复制” { "Logging": { "LogLevel": { "Default&quo ...

  7. Https接口调用工具类

    ClientUtil.java import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org. ...

  8. 使用zookeeper报错 stat is not executed because it is not in the whitelist. envi is not executed because it is not in the whitelist.

    在使用四字命令或者zk ui界面查看zookeeper集群时,出现如下提示: stat is not executed because it is not in the whitelist. envi ...

  9. linux centos系统安装

    1.下载镜像 https://www.centos.org/download/ DVD ISO 一般下载这个 erverything ISO 包含所有工具的版本 Minimal ISO最小启动版本 2 ...

  10. MySQL存储引擎知多少

    MySQL是我们经常使用的数据库处理系统(DBMS),不知小伙伴们有没有注意过其中的“存储引擎”(storage_engine)呢?有时候面试题中也会问道MySQL几种常用的存储引擎的区别.这次就简短 ...