table of Contents
Functional Configuration Design
Achieve similar in settings.py django middleware strings, a string comment, so that the corresponding function failure
importlib
Module
# 可以利用 特定格式的字符串路径 导入模块
import importlib
path_str = 'lib.test'
mod = importlib.import_module(path_str) # from lib import test
'''
文件结构
notify
__init__.py
email.py
msg.py
wechat.py
settings.py
start.py
'''
# __init__.py
import settings
import importlib
def send_all(content):
for path_str in settings.NOTIFY_LIST:
module_path, class_name = path_str.rsplit('.', maxsplit=1)
# 拿到文件对象
mod = importlib.import_module(module_path) # from notify import email/msg/wechat
# 利用反射获取文件对象中的类
cls = getattr(mod, class_name)
# 实例化对象
obj = cls(content)
# 发送通知 (鸭子类型思想, 不管你是什么对象, 都有send方法)
obj.send()
# email.py
class Email(object):
def __init__(self, content):
self.content = content
def send(self):
print(f'邮箱通知:{self.content}')
# msg.py
class Msg(object):
def __init__(self, content):
self.content = content
def send(self):
print(f'短信通知:{self.content}')
# wechat.py
class WeChat(object):
def __init__(self, content):
self.content = content
def send(self):
print(f'微信通知:{self.content}')
# settings.py
NOTIFY_LIST = [
'notify.email.Email',
'notify.msg.Msg',
'notify.wechat.WeChat',
]
# start.py
from notify import *
if __name__ == '__main__':
send_all('非常高兴的通知大家, 本周六加班')
'''
邮箱通知:非常高兴的通知大家, 本周六加班
短信通知:非常高兴的通知大家, 本周六加班
微信通知:非常高兴的通知大家, 本周六加班
'''
CSRF CSRF
What is CSRF
What is an example of cross-site request forgery it? A simple phishing website
We wrote a shining page exactly the same page of a bank, then the user will "catch" to this page to transfer our operations
A user name, password, and other accounts, as well as transfer amount, submitted
We then use the code written in advance of the "other accounts" to our own account
And then submit a request to a bank interface corresponding to the original page
So users quietly transferred the money on our account the ...
- Is modeled on the form of a Web page to submit data on the back end, submit a request to its back-end
If you implement CSRF
- User input "other accounts" of the input tag, the name attribute is not set, so you get less than the corresponding back-end data
- Use a hidden input tag, set the name attribute, the default is our own account
- Such backend can only get the value of the hidden input to carry the label
{#向真实网站接口提交请求#}
form action="http://127.0.0.1:8000/transfer/" method="post">
<p>username <input type="text" name="username"></p>
{#用户实际需要输入的标签,没有name属性#}
<p>target_account<input type="text"></p>
{#隐藏的标签, 有name属性和默认值#}
<p><input type="text" value="bigb" name="target_account" style="display: none"></p>
<p>money<input type="text" name="money"></p>
<input type="submit">
</form>
How to Avoid CSRF
Solution: only handle post their own web page request sent ---> How to determine post a request from their own web pages
---> Add a hidden input box in return html page form form, carries a random string
---> Middleware rear random string to determine whether this is a request sent from this site
form form
{#直接在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_account"></p>
<p>money<input type="text" name="money"></p>
<input type="submit">
</form>
{#然后我们在前端检查代码, 会发现多了个隐藏的input标签#}
<input type="hidden" name="csrfmiddlewaretoken" value="eYT1yNAroJidl3qjDSLSe3U2o0OTQXjD8PcSb2crNDTQijAGjRHX7ual6Y9bLg4D">
- ajax
{#方式一: 将这个随机字符串添加到ajax向后端提交的data当中即可#}
{% csrf_token %}
<script>
$('#d1').click(function () {
$.ajax({
url: '',
type: 'post',
//方式一: 利用标签的name属性查找标签并获取对应的随机字符串
data:{'username':'bigb', 'csrfmiddlewaretoken':$('input[name='csrfmiddlewaretoken']').val()}
//方式二: 'csrfmiddlewaretoken':'{{ csrf_token }}'
data:{'username':'bigb', 'csrfmiddlewaretoken':'{{ csrf_token }}'}
success: function (data) {
}
})
})</script>
{#方式二: 将如下代码放入一个静态js文件中, 再在html文件引入即可#}
//获取
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 related to two decorators
Import:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
csrf_exempt
: The view function is not a page corresponding check csrfcsrf_protect
: The view function corresponding pages check csrf
from django.views.decorators.csrf import csrf_exempt, csrf_protect
@csrf_exempt # 不校验
def index(request):
return HttpResponse('index')
@csrf_protect # 校验
def index(request):
return HttpResponse('index')
- Both the installation is mounted on CBV
- csrf_exempt can only take effect to the dispatch method to install
- csrf_protect how equipment can be
from django.views.decorators.csrf import csrf_exempt, csrf_protect
class MyIndex(views.View):
@method_decorator(csrf_exempt) # csrf_exempt只能给dispatch方法装才能生效
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def get(self, request):
renturn render(request, 'index.html')
@method_decorator(csrf_protect) # csrf_protect三种方法都可以
def post(self, request):
return HttpResponse('index')
auth module
Common method
- Create an administrator user
#命令行输入 : python manage.py makesuperuser
- Common method
# 1.创建用户(注册)
# 导入模块
from django.contrib.auth.models import User
# 创建普通用户 creatr_user
User.objects.create_user(username=username, password=password)
# 创建管理员用户 creater_superuser
User.objects.create_superuser(username=username, password=password, email=email)
# 2.校验用户名和密码是否正确(登录)
# 导入模块
from django.contrib import auth
# 必须传入username和password, 返回用户对象
user_obj = auth.authenticate(request, username=username, password=password)
if user_obj:
return HttpResponse('登录成功!')
else:
return HttpResponse('密码或用户错误!')
# 3.保存用户状态(session)
# 执行该代码后, 后面就可以通过 request.user 获取当前登录的用户对象
auth.login(request, user_obj)
# 4.判断用户是否登录
request.user.is_authenticated()
# 5.校验原密码是否正确(修改密码时需要先输入原密码)
request.user.check_password(old_password)
# 6.修改密码
request.user.set_password(new_password)
# 7.注销
auth.logout(request)
# 8. 登录认证装饰器
# 导入模块
from django.contrib.auth.decorators import login_required
# 局部配置跳转地址
@login_required(login_url='/login/')
def index(request):
return HttpRespone('index')
# 全局配置配置跳转地址
# 在settings.py中配置
LOGIN_URL = /'login'/
@login_required
def index(request):
return HttpRespone('index')
Auth_user extended fields in the table
# 1.利用一对一表关系扩展字段
class UserDetail(models.Model):
phone = models.CharField(max_length=11)
addr = models.CharField(max_length=255)
user = models.OneToOneField(to='User')
# 2.利用面向对象的继承新建一个表, 替换掉原来的User表
from django.contrib.auth.models import AbstractUser
# 继承了AbstracterUser中所有的字段
class UserInfo(AbstractUser):
# 扩展字段
phone = models.CharField(max_length=11)
addr = models.CharField(max_length=255)
# 需要在settigs.py中将默认表指定为UserInfo
AUTH_USER_MODEL = 'app01.Userinfo' # 应用名.表名