1205 CSRF 장고 크로스 역은 모듈의 인증을 요청

컨텐츠 오늘

今日内容:
    
    基于配置文件的编程思想
    
    跨站请求伪造csrf
    
    django auth模块
    
    django settings源码剖析
    
    基于django settings源码实现自己项目配置文件插拔式设计

어제 검토

cookie与session
        cookie与session发展史
            由于http协议是无状态的 所以我们需要发明一些能够保存用户的技术
        
        cookie
            保存在客户端浏览器上面的键值对(可以有多个)
            cookie是后端服务器控制与设值的 浏览器只是奉命行事
            浏览器也有权利拒绝写入cookie(一切需要登录认证的网站全都无法正常登录)
            
            如何查看浏览器上面的cookie
                application/COOKIES/信息
        
        session
            保存在服务端上的键值对(可以有多个)
            
        django如何操作cookie
            前提是需要用到HttpResponse对象
            obj = HttpResponse()
            obj1 = render()
            obj2 = redirect()
            
            设值cookie
                obj.set_cookie('k1','v1')
            获取cookie
                request.COOKIES.get('k1')
            设值失效时间
                obj.set_cookie('k1','v1',max_age=10)
                obj.set_cookie('k1','v1',expires=5)
                都以秒为单位expires针对IE浏览器
            删除cookie
                obj.delete_cookie('k1')
            
            基于cookie实现用户登录校验
                装饰器
                用户在没有登录之前如果访问了一个需要登录之后才能访问的页面
                那么会先跳转到登录页面 用户输入用户名和密码并正确的情况下
                再自动跳转到之前用户想要访问的页面
                    1.request.path_info
                    2.利用get请求携带参数的方法
    
    
        session操作
            django默认的session失效时间是14天,你也可以设置
            session是保存在服务端的 默认情况下 你的django需要先执行数据库迁移命令
            因为保存sesson数据的表需要先提前创建出来,如果不创建会报错(no such table:django_session)
            session不单单可以放在django_session表中  也可以放在任意能够作为数据库的地方
                文件
                内存
                缓存
                ...
                配置文件
                
            django的session表中的数据是针对浏览器的 同一个浏览器只会存一行数据
                
            
            设置session
                request.session['k1'] = 'v1'
                """
                    1.django内部自动调用算法 生成一个随机字符串
                    2.将随机字符串与设置的值保存到django_session表中(真正写入数据的操作是在django中间件里面的session相关中间件发生的)
                    3.将随机字符串返回给浏览器保存到cookie
                        sessionid:随机字符串
                """
            获取session
                request.session.get('k1')
                """
                    1.django内部会自动获取浏览器发送过来的cookie中的获取sessionid所对应的随机字符串
                    2.拿着随机字符串去django_session表中比对
                    3.如果有拿出数据放到request.session中供用户调用
                """
            删除session
                request.session.delete()
                request.session.flush()
            失效时间
                request.session.set_expiry()
                    1.数字(不能是0)   秒数
                    2.数字0    浏览器关闭自动失效
                    3.时间格式数据  datetime
                    4.不写    默认参考的是全局的失效时间
            
            基于session实现用户登录校验
    
    django中间件
        django中间件就类似于django的门户或者保安
        所有的请求和响应都必须经过中间件才能够正常通过
        并且在中间件中可以对请求和响应的数据进行处理
        django中间件在设计到一些全局方面的功能时 作用非常大
            1.网站全局的用户登录校验
            2.网站全局的访问频率校验
            3.网站全局的用户权限校验
            ...
            只要是全局的功能,你都应该第一个想到中间件
        
        django默认有七个中间件 每个中间件都有自己独立的功能 如果你想用 你直接注释掉即可
        django还支持用户自定义自己的中间件 并且暴露给用户五个可以自定义的方法
        
        前提
            1.只要是设计到处理前端业务逻辑的视图函数 都需要有形参request
            2.如果你想自定义中间件 你必须写一个类并且继承MiddlewareMixin
            3.一旦形参中reponse你就必须返回  因为response就是后端想要返回前端的数据
        五个方法
            需要掌握的
                1.process_request(self,request)  (******)
                    1.请求到来的时候 会按照配置文件注册的从上往下的顺序依次经过每一个中间件里面的该方法
                        如果中间件中没有定义该方法 直接跳过执行下一个
                    2.一旦该方法返回了一个HttpResponse对象 那么请求不再往后走 而是走到同级别的process_response依次返回
                
                2.process_response(self,request,response)
                    1.响应走的时候 会按照配置文件注册的从下往上的顺序依次经过每一个中间件里面的该方法
                        该方法默认必须返回response 如果你返回了自己的HttpResponse对象 那么用户收到的就是你的
            需要了解的
                3.process_view(self,request,view_name,*args,**kwargs)
                    1.路由匹配成功之后执行视图函数之前
                4.process_exception(self,request,response)
                    1.视图函数中出现错误的时候自动触发
                5.process_template_response(self,request,response)
                    1.返回的对象中含有render方法

구성 파일 프로그래밍 아이디어를 바탕으로

importlib 모듈

문자열로 가져 오기 모듈을 사용하여

import importlib
res = 'lib.bbb'
md = importlib.import_moudle(res)
print(md)

IMG

간단한 코드 구현

首先定义一个配置路径列表
NOTIFY_LIST = [
    'notify.email.Email',
    'notify.msg.Msg',
    'notify.wechat.WeChat'
]

-------------------------------------------------------


在包的__init__文件中设置send_all函数

# import settings
import importlib
def send_all(countent):
    # 将settings文件中的存储函数路径迭代循环
    for path in settings.NOTIFY_LIST:
        # 通过.切割,获取每一个文件的的路径,以及cls类名
        module_path,cls_name = path.rsplit('.',maxsplit=1)
        # 通过importlib方法传入路径,获取导入文件对象
        md = importlib.import_module(module_path)
        # getattr反射获取md文件中的相对应cls类
        cls = getattr(md,cls_name)
        # 实例化类,获取一个个类的对象
        obj = cls()
        # 调用类中的发送方法
        obj.send(countent)

CSRF의 CSRF

1. 피싱 사이트

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

어떻게 달성하기 위해

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

아날로그는이 현상을 생산

创建两个django项目
------------------------------------------------------
html
<p>假的</p>
//  提交的地址是真正的网站地址
<form action="http://127.0.0.1:8000/transfer/" method="post">
    <p>username<input type="text" name="username"></p>
    <p>
        target_account:
        <input type="text">
        <input type="text" name="target_account" value="jason" style="display: none;">
        // 通过设置两个input框,并隐藏自定义value的框,获得该白转账人的目的
    </p>

    <p>money:<input type="text" name="money"></p>
    <input type="submit">
    
------------------------------------------------------
    
<p>这是正经的网站</p>
<form action="" method="post">
    <p>username<input type="text" name="username"></p>
    <p>target_account<input type="text" name="target_account"></p>
    <p>money:<input type="text" name="money"></p>
    <input type="submit">
</form>

이 문제를 해결합니다

django中的中间件`'django.middleware.csrf.CsrfViewMiddleware',`就是负责校验csrf的

만 사후 처리는이 사이트에서 전송 된 요청

如何识别如何判断当前请求是否是本网站发出的
**防御CSRF攻击:**

    目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。

해결 {% csrf_token %}

형태에서 추가 {% 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>

IMG

해결 방법 3. 아약스

모드 1

  • 먼저 페이지에 어떤 위치에 작성{% csrf_token %}
  • 이어서 AJAX 요청에 사용자 객체에 부가 된 태그 데이터를 취득하여 임의의 문자열을 보낼 때
data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},

모드 2

  • 먼저 페이지에 어떤 위치에 작성{% csrf_token %}

  • 에서 데이터를 직접 작성 'csrfmiddlewaretoken':'{{ csrf_token }}키 - 값 쌍

  • data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},    

모드 3

파일 공식 웹 사이트는 방법으로 다양한 최대한 제공

  • 새로운 코드를 직접 JS 파일 복사, 수입 script
  • 당신은 어떤 코드 관련 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);
    }
  }
});

정적 파일에 다음과 같은 구성 파일 전에 HTML 페이지에서 장고 프로젝트가 자동으로 우리가 설정 파일을 가져옵니다 (파일을 가져 csrf_token 후 데이터 유효성 검사를 제출 AJAX 문제를 해결하는 데 도움이됩니다, 당신은 가져올 필요 jQuery를,이 프로파일의 콘텐츠 달성 jQuery를 기반으로하기 때문에)

자세한 내용은 다음을 참조하십시오 CSRF의 내용에 대한 Djagno 공식 문서를

4 개의 연관된 CSRF 장식

두 장식, 방법이 개발보기 CSRF를 검증 할 필요가 함수 또는 패리티했다

1.

가져 오기

from django.views.decorators.csrf import csrf_exempt,csrf_protect

확인하지 마십시오 @csrf_exempt

@csrf_exempt           # 不校验 csrf
def index(request):   
    return HttpResponse('index')

확인 @csrf_protect

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

2. 상사와 CBV에있는 두 개의 장식의 차이

CBV

CBV就是在url中一个路径对应一个类
    基于FBV的模式就是在Django的路由映射表里进行url和视图函数的关联,而基于CBV的模式则是在views.py文件中定义视图类,在视图类中视图函数,如get,post,put,delete等
    
    
在写代码中的几点注意事项:
    cbv定义类的时候必须要继承view
    在写url的时候必须要加as_view
    类里面使用form表单提交的话只有get和post方法
    类里面使用ajax发送数据的话支持定义以下很多方法
    restful规范:
    'get'获取数据, 'post'创建新数据, 'put'更新, 'patch'局部更新, 'delete'删除, 'head', 'options', 'trace'

----------------------------------------------------
视图函数中

from django.views import View
 
class IndexView(View):
   # 以get形式访问会执行get函数,一般情况下获取数据
   def get(self, *args, **kwargs):
      return HttpResponse('666')
 
   # 以post形式访问的话会执行post函数,一般情况下发送数据
   def post(self, *args, **kwargs):
      return HttpResponse('999')

@ csrf_exempt

이 장식은 파견 장비하기 위해 적용 할 수 csrf_exempt

# @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_protect

일반 장식 일관성 CBV와 csrf_protect 방법은 모든 당신이 장식 할 수 있습니다

# @method_decorator(csrf_protect,name='post')  # 可以
                class MyIndex(views.View):
                    @method_decorator(csrf_protect)
                    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)  # 可以
                    def post(self,request):
                        return HttpResponse('OK')

설정에서 장고 소스 분석

另外的配置文件settings在
from django.conf import settings  中

장고는 두 개의 구성 파일이

一个是暴露给用户可以配置的
            
            一个是内部全局的(用户配置了就用用户的 用户没有配就用自己的)
            obj
            obj.name = 'egon'  # 全局
            obj.name = 'jason'  # 局部
  • 첫 번째 개체에 대한 글로벌 구성 설정을로드
  • 그런 부분 설정 로딩에 배치 된 오브젝트를 수득
  • 일단 전 중복 된 항목을 통해 후자
思考题
    参看django settings源码 应用到自己的项目中 
    在你的项目中 实现配置文件的插拔式设计
    用户配置了就用用户的 用户没有配就用自己的

IMG

IMG

IMG

장고 인증 모듈

1. 무엇이다

장고 인증 모듈이 내장되어 사용자 인증 모듈 :

우리는 사이트 사용자의 시스템을 달성하기 위해 웹 사이트를 디자인하는 불가피한 필요성을 개발하고있다. 이 시점에서 우리는이 정말 아직 귀찮은 일, 변경, 암호 및 기타 기능을 로그 오프, 사용자 등록, 사용자 로그인, 사용자 인증을 포함하여 달성해야합니다.

장고는 궁극적 인 완벽을위한 프레임 워크로, 물론, 이러한 고충 사용자의 생각합니다. 그것은 사용자 데이터를 저장에 AUTH_USER 테이블에 강력한 사용자 인증 시스템 --auth, 기본값을 만들었습니다.

슈퍼 유저 (루트) 만들기

python3 manage.py createsuperuser

tool中直接createsuperuser

IMG

2. 일반적인 방법

2.1 사용자 만들기 create_user()

가져 오기 표

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='[email protected]')  # 创建超级用户   需要邮箱数据

2.2 체크 auth.authenticate

가져 오기 모듈 인증

from django.contrib import auth
校验用户名和密码是否正确
user_obj = auth.authenticate(request,username=username,password=password)
# 必须传用户名和密码两个参数缺一不能

2.3 로그 저장 login(request,对象)

auth.login(request,user_obj)
# 只要这句话执行了 后面在任意位置 只要你能拿到request你就可以通过request.user获取到当前登录的用户对象

2.4 로그인 여부를 결정 is_authenticated()

request.user.is_authenticated()

2.5 원래 암호가 정확한지 확인 check_password(旧密码)

request.user.check_password(old_password)

2.6 암호 변경 set_password(新密码)

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

2.7 로그 아웃 logout(request)

auth.logout(request)

# request.session.flush()

2.8 로그인 장식 @login_required

가져 오기

from django.contrib.auth.decorators import login_required

로컬 구성

당신은 인터페이스 등록되지 않은 오류 점프를 사용자 정의 할 수 있습니다login_url = '/跳转连接/'

@login_required(login_url='/login/')
def index(request):
    pass

글로벌 구성

settings配置文件中 直接配置
LOGIN_URL = '/login/'

然后在视图函数添加
@login_required
def index(request):
    pass

만약 지역 로컬 구성 또한 대상의 글로벌 구성

AUTH_USER 필드를 확장합니다

모드 1

확장 외래 키 하나

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

모드 2

객체 지향 상속

导入AbstractUser类
    from django.contrib.auth.models import AbstractUser
    
定义模型表类
    class Userinfo(AbstractUser):
        phone = models.BigIntegerField()
        register_time = models.DateField(auto_now_add=True)
        
settings配置文件中设置
    AUTH_USER_MODEL = 'app01.Userinfo'  # 应用名.表名

执行数据库迁移命令

# 这么写完之后 之前所有的auth模块功能全都以你写的表为准 

전파

장고 설정 구성 파일을 기반으로 설계 플러그인 달성하는 것입니다

# 执行start文件中
if __name__ == '__main__':
    设置全局大字典的键值 键(随便) 值(文件的路径)
    os.environ['xxx'] = 'conf.settings'
    form lib.conf import settings
    print(settings.NAME)
    
有两个settings配置文件,分别对应暴露给用户,以及隐藏的全局配置
各自有NAME属性


------------ conf.settings.__init__配置-------------------
class Settings(object):
    def __init__(self):
        # 获取全局配置中的所有变量名
        for name in dir(global_settings):
            # 筛选出需要的大写变量名
            if name.isupper():
                # 给self对象设置全局配置中的大写变量名 属性值
                setattr(self,name,getattr(globals_settings,name))

        # 获取暴露给用户的配置文件字符串路径
        module_path = os.environ.get('xxx')
        md = importlib.import_module(module_path)
        for name in dir(md):
            if name.isupper():
                k = name
                v = getattr(md,name)
                setattr(self,k,v)

# 实例化类获得对象
settings = Settings()

추천

출처www.cnblogs.com/fwzzz/p/11992591.html