跨站请求伪造 auth模块

importlib  利用字符串形式导入模块

import importlib
res = 'lib.bbb'
# 利用字符串的形式导入模块
md = importlib.import_module(res)  # from lib import bbb
print(md)  # 该模块字符串最小单位只能到文件名

 

 跨站请求伪造 csrf

钓鱼网站
  你自己写一个跟中国银行正规网站一模一样的页面
  用户输入用户名 密码 对方账户 转账金额提交
  请求确实是朝中国银行的接口发送的 钱也扣了
  但是对方账户变了 变成了钓鱼网站自己提前设置好的账户

如何实现
  你在写form表单的时候 让用户填写的对方账户input并没有name属性
  而是你自己在内部偷偷隐藏了一个具有name属性的input框
  并且value值是你自己的账户 然后将该标签隐藏了

跨站请求伪造解决思路

解决
  网站在返回给用户一个form表单的时候 会自动在该表单隐藏一个input框
  这个框的value是一个随机字符串 但是网站能够记住每一个浏览器发送的随机字符串

 

你以后在写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>
# 自动添加隐藏的input框 <input type="hidden" name="csrfmiddlewaretoken" value="rJ47FeK9T55wavvVJGY6UxdM1kTMHhTqotGfaXjXIK8Ahz2Uvs02yR9T8bBn5q2D">

ajax如何解决POST请求csrf校验

方式1 较为繁琐
先在页面任意的位置上书写{% csrf_token %}
然后在发送ajax请求的时候 通过标签查找获取随机字符串添加到data自定义对象即可
data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},

方式2 较为简单
data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},


方式3 官网提供的文件 最通用的一种方式
直接新建js文件,放在static下面(注意配置static)拷贝代码 导入即可
你不需要做任何的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);
    }
  }
});

csrf的校验装饰器

from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_exempt # 不校验 csrf
def index(request):
return HttpResponse('index')


@csrf_protect # 校验
def login(request):
return HttpResponse('login')

csrf的校验装饰器在CBV上有何异同

# @method_decorator(csrf_exempt,name='post') # csrf_exempt不支持该方法
@method_decorator(csrf_exempt,name='dispatch') # csrf_exempt
class MyIndex(views.View):
  # @method_decorator(csrf_exempt) # 可以
  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') # csrf_exempt不支持该方法
  def post(self,request):
    return HttpResponse('OK')


csrf_exempt这个装饰器只能给dispatch装才能生效


"""
csrf_protect方式全都可以 跟你普通的装饰器装饰CBV一致
"""

 django settings源码剖析

django有两个配置文件
  一个是暴露给用户可以配置的

  一个是内部全局的(用户配置了就用用户的 用户没有配就用自己的)
obj
obj.name = 'egon' # 全局
obj.name = 'jason' # 局部

先加载全局配置 给对象设置
然后在加载局部配置 再给对象设置
一旦有重复的项 后者覆盖前者

 auth模块简介

如何创建超级用户(root)
python3 manage.py createsuperuser


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=username,password=password,email='123@qq.com') # 创建超级用户 需要邮箱数据
  2.校验用户名和密码是否正确
    from django.contrib import auth
    user_obj = auth.authenticate(request,username=username,password=password)
    # 必须传用户名和密码两个参数缺一不能
  3.保存用户登录状态
    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.注销
    auth.logout(request)
  8.校验用户是否登录装饰器
    from django.contrib.auth.decorators import login_required

  局部配置
    @login_required(login_url='/login/')
    def index(request):
      pass
  全局配置
    settings配置文件中 直接配置
    LOGIN_URL = '/login/'
    @login_required
    def index(request):
      pass
  # 如果全局配置了 局部也配置 以局部的为准

from django.contrib.auth.models import User
from django.contrib import auth
from django.contrib.auth.decorators import login_required

def register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # models.User.objects.create(username=username,password=password)
        # User.objects.create(username=username,password=password)  # 不可用  密码不是加密的
        # User.objects.create_user(username=username,password=password)  # 创建普通用户    密码自动加密
        # User.objects.create_superuser(username=username,password=password,email='123@qq.com')  # 创建超级用户   需要邮箱数据
        return HttpResponse('OK')
    return render(request,'register.html')


def lgg(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 校验当前用户名和密码是否正确
        # models.User.objects.filter(username=username,password=password)
        # res = User.objects.filter(username=username,password=password)  # 密码无法校验
        # print(res)
        res = auth.authenticate(request,username=username,password=password)  # 自动给你加密密码 然后去数据库校验
        # print(res)  # 数据对象
        # print(res.username)
        # print(res.password)  # 密码是密文
        if res:
            # 保存用户登录状态
            # request.session['user'] = 'jason'
            auth.login(request,res)
            """
            只要执行了这一句话 之后你可以在任意位置
            通过request.user获取到当前登录用户对象
            """
            return HttpResponse('ok')
    return render(request,'lgg.html')


def get_user(request):
    print(request.user)  # 如果用户没有登录就返回AnonymousUser匿名用户
    print(type(request.user))
    print(request.user.is_authenticated())  # 判断当前用户是否登录
    return HttpResponse('ok')

# @login_required(login_url='/lgg/')  # 局部配置  如果没有登录就跳转到/lgg/登录
# 或者全局配置,现在配置文件中写 LOGIN_URL = '/lgg/'
@login_required
def check_password(request):
    if request.method == "POST":
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        # 校验老密码是否正确
        is_right = request.user.check_password(old_password)
        if is_right:
            request.user.set_password(new_password)
            request.user.save()  # 修改密码一对要保存
    user_obj = request.user
    return render(request,'change_password.html',locals())


@login_required
def logout(request):
    # request.session.flush()
    auth.logout(request)
    return HttpResponse('注销了')

 auth拓展表

方式1
利用一对一外键字段关系
class UserDetail(models.Model):
  phone = models.BigIntegerField()
  user = models.OneToOneField(to='User')

方式2
利用继承关系
from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):
  phone = models.BigIntegerField()
  register_time = models.DateField(auto_now_add=True)

# 一定要注意 还需要去配置文件中配置
AUTH_USER_MODEL = 'app01.Userinfo' # 应用名.表名
# 这么写完之后 之前所有的auth模块功能全都以你写的表为准

基于djangosettings配置文件实现插拔式设计

import importlib
from lib.conf import global_settings
import os

class Settings(object):
    def __init__(self):
        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
        for name in dir(md):
            if name.isupper():
                k = name
                v = getattr(md,name)
                setattr(self,k,v)


settings = Settings()

 

import os
import sys


BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR)


if __name__ == '__main__':
    # os.environ.setdefault('xxx','conf.settings')
    os.environ['xxx'] = 'conf.settings'
    from lib.conf import settings
    print(settings.NAME)

 

 

posted on 2019-12-05 17:53  啥是py  阅读(230)  评论(0编辑  收藏  举报

导航