.wiz-editor-body .wiz-code-container { position: relative; padding: 8px 0; margin: 5px 25px 5px 5px; text-indent: 0; text-align: left }
.CodeMirror { font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; color: black; font-size: 0.875rem }
.wiz-editor-body .wiz-code-container .CodeMirror div { margin-top: 0; margin-bottom: 0 }
.CodeMirror-lines { padding: 4px 0 }
.CodeMirror pre { padding: 0 4px }
.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler { background-color: white }
.CodeMirror-gutters { border-right: 1px solid #ddd; background-color: #f7f7f7; white-space: nowrap }
.CodeMirror-linenumbers { }
.CodeMirror-linenumber { padding: 0 3px 0 5px; min-width: 20px; text-align: right; color: #999; white-space: nowrap }
.CodeMirror-guttermarker { color: black }
.CodeMirror-guttermarker-subtle { color: #999 }
.CodeMirror-cursor { border-left: 1px solid black; border-right: none; width: 0 }
.CodeMirror div.CodeMirror-secondarycursor { border-left: 1px solid silver }
.cm-fat-cursor .CodeMirror-cursor { width: auto; border: 0 !important; background: #7e7 }
.cm-fat-cursor div.CodeMirror-cursors { z-index: 1 }
.cm-animate-fat-cursor { width: auto; border: 0; background-color: #7e7 }
.CodeMirror-overwrite .CodeMirror-cursor { }
.cm-tab { display: inline-block; text-decoration: inherit }
.CodeMirror-rulers { position: absolute; left: 0; right: 0; top: -50px; bottom: -20px; overflow: hidden }
.CodeMirror-ruler { border-left: 1px solid #ccc; top: 0; bottom: 0; position: absolute }
.cm-s-default .cm-header { color: blue }
.cm-s-default .cm-quote { color: #090 }
.cm-negative { color: #d44 }
.cm-positive { color: #292 }
.cm-header,.cm-strong { font-weight: bold }
.cm-em { font-style: italic }
.cm-link { text-decoration: underline }
.cm-strikethrough { text-decoration: line-through }
.cm-s-default .cm-keyword { color: #708 }
.cm-s-default .cm-atom { color: #219 }
.cm-s-default .cm-number { color: #164 }
.cm-s-default .cm-def { color: #00f }
.cm-s-default .cm-variable,.cm-s-default .cm-punctuation,.cm-s-default .cm-property,.cm-s-default .cm-operator { }
.cm-s-default .cm-variable-2 { color: #05a }
.cm-s-default .cm-variable-3 { color: #085 }
.cm-s-default .cm-comment { color: #a50 }
.cm-s-default .cm-string { color: #a11 }
.cm-s-default .cm-string-2 { color: #f50 }
.cm-s-default .cm-meta { color: #555 }
.cm-s-default .cm-qualifier { color: #555 }
.cm-s-default .cm-builtin { color: #30a }
.cm-s-default .cm-bracket { color: #997 }
.cm-s-default .cm-tag { color: #170 }
.cm-s-default .cm-attribute { color: #00c }
.cm-s-default .cm-hr { color: #999 }
.cm-s-default .cm-link { color: #00c }
.cm-s-default .cm-error { color: #f00 }
.cm-invalidchar { color: #f00 }
.CodeMirror-composing { border-bottom: 2px solid }
div.CodeMirror span.CodeMirror-matchingbracket { color: #0f0 }
div.CodeMirror span.CodeMirror-nonmatchingbracket { color: #f22 }
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3) }
.CodeMirror-activeline-background { background: #e8f2ff }
.CodeMirror { position: relative; background: #f5f5f5 }
.CodeMirror-scroll { overflow: hidden !important; margin-bottom: 0; margin-right: -30px; padding: 16px 30px 16px 0; outline: none; position: relative }
.CodeMirror-sizer { position: relative; border-right: 30px solid transparent }
.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler { position: absolute; z-index: 6; display: none }
.CodeMirror-vscrollbar { right: 0; top: 0 }
.CodeMirror-hscrollbar { bottom: 0; left: 0 !important }
.CodeMirror-scrollbar-filler { right: 0; bottom: 0 }
.CodeMirror-gutter-filler { left: 0; bottom: 0 }
.CodeMirror-gutters { position: absolute; left: 0; top: -5px; min-height: 100%; z-index: 3 }
.CodeMirror-gutter { white-space: normal; height: inherit; display: inline-block; vertical-align: top; margin-bottom: -30px }
.CodeMirror-gutter-wrapper { position: absolute; z-index: 4; background: none !important; border: none !important }
.CodeMirror-gutter-background { position: absolute; top: 0; bottom: 0; z-index: 4 }
.CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; text-align: center }
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
.CodeMirror-lines { cursor: text; min-height: 1px }
.CodeMirror pre { border-width: 0; background: transparent; font-family: inherit; font-size: inherit; margin: 0; white-space: pre; line-height: inherit; color: inherit; z-index: 2; position: relative; overflow: visible }
.CodeMirror-wrap pre { white-space: pre-wrap }
.CodeMirror-linebackground { position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 0 }
.CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto }
.CodeMirror-widget { }
.CodeMirror-rtl pre { direction: rtl }
.CodeMirror-code { outline: none }
.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber { }
.CodeMirror-measure { position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden }
.CodeMirror-cursor { position: absolute }
.CodeMirror-measure pre { position: static }
div.CodeMirror-cursors { visibility: hidden; position: relative; z-index: 3 }
div.CodeMirror-dragcursors { visibility: visible }
.CodeMirror-focused div.CodeMirror-cursors { visibility: visible }
.CodeMirror-selected { background: #d9d9d9 }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0 }
.CodeMirror-crosshair { cursor: crosshair }
.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection { background: #d7d4f0 }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0 }
.cm-searching { background: rgba(255, 255, 0, .4) }
.cm-force-border { padding-right: .1px }
.cm-tab-wrap-hack::after { content: "" }
span.CodeMirror-selectedtext { background: none }
.CodeMirror-activeline-background,.CodeMirror-selected { }
.CodeMirror-blur .CodeMirror-activeline-background,.CodeMirror-blur .CodeMirror-selected { visibility: hidden }
.CodeMirror-blur .CodeMirror-matchingbracket { color: inherit !important; outline: none !important; text-decoration: none !important }
.CodeMirror-sizer { min-height: auto !important }
html,.wiz-editor-body { font-size: 12pt }
.wiz-editor-body { font-family: Helvetica, "Hiragino Sans GB", "寰蒋闆呴粦", "Microsoft YaHei UI", SimSun, SimHei, arial, sans-serif; line-height: 1.7; margin: 0 auto; padding: 1.25rem 1rem }
.wiz-editor-body h1,.wiz-editor-body h2,.wiz-editor-body h3,.wiz-editor-body h4,.wiz-editor-body h5,.wiz-editor-body h6 { margin: 1.25rem 0 0.625rem }
.wiz-editor-body h1 { font-size: 1.67rem }
.wiz-editor-body h2 { font-size: 1.5rem }
.wiz-editor-body h3 { font-size: 1.25rem; background-color: #A3A9F5; font-weight: bold }
.wiz-editor-body h4 { font-size: 1.17rem; background-color: #8dd5f5; font-weight: bold }
.wiz-editor-body h5 { font-size: 1rem; background-color: #F5F183; font-weight: bold }
.wiz-editor-body h6 { font-size: 1rem; color: #777777; margin: 1rem 0 }
.wiz-editor-body div,.wiz-editor-body p,.wiz-editor-body ul,.wiz-editor-body ol,.wiz-editor-body dl,.wiz-editor-body li { margin: 8px 0 }
.wiz-editor-body blockquote,.wiz-editor-body table,.wiz-editor-body pre,.wiz-editor-body code { margin: 8px 0 }
.wiz-editor-body .CodeMirror pre { margin: 0 }
.wiz-editor-body ul,.wiz-editor-body ol { padding-left: 2rem }
.wiz-editor-body ol.wiz-list-level1>li { list-style-type: decimal }
.wiz-editor-body ol.wiz-list-level2>li { list-style-type: lower-latin }
.wiz-editor-body ol.wiz-list-level3>li { list-style-type: lower-roman }
.wiz-editor-body blockquote { padding: 0 12px }
.wiz-editor-body blockquote>:first-child { margin-top: 0 }
.wiz-editor-body blockquote>:last-child { margin-bottom: 0 }
.wiz-editor-body img { border: 0; max-width: 100%; height: auto !important; margin: 2px 0 }
.wiz-editor-body table { border-collapse: collapse; border: 1px solid #bbbbbb }
.wiz-editor-body td,.wiz-editor-body th { padding: 4px 8px; border-collapse: collapse; border: 1px solid #bbbbbb; min-height: 28px }
.wiz-hide { display: none !important }
认证组件
Django原生的authentic组件为我们的用户注册与登录提供了认证功能,十分的简介与强大。同样DRF也为我们提供了认证组件,一起来看看DRF里面的认证组件是怎么为我们工作的!
models.py
# 定义一个用户表和一个保存用户Token的表
class UserInfo(models.Model):
username = models.CharField(max_length=16)
password = models.CharField(max_length=32)
type = models.SmallIntegerField(
choices=((1, ‘普通用户‘), (2, ‘VIP用户‘)),
default=1
)
class Token(models.Model):
user = models.OneToOneField(to=‘UserInfo‘)
token_code = models.CharField(max_length=128)<wiz_code_mirror>
15
1
# 定义一个用户表和一个保存用户Token的表
2
3
4
class UserInfo(models.Model):
5
username = models.CharField(max_length=16)
6
password = models.CharField(max_length=32)
7
type = models.SmallIntegerField(
8
choices=((1, ‘普通用户‘), (2, ‘VIP用户‘)),
9
default=1
10
)
11
12
13
class Token(models.Model):
14
user = models.OneToOneField(to=‘UserInfo‘)
15
token_code = models.CharField(max_length=128)
url
path(‘login/‘, views.LoginView.as_view()),<wiz_code_mirror>
1
1
path(‘login/‘, views.LoginView.as_view()),
views.py
# 视图主要处理用户名、密码是否正确,用户每一次请求都要带着专有token来!
import hashlib, time
from rest_framework.response import Response
from rest_framework.views import APIView
def get_random_token(username):
"""
根据用户名和时间戳生成随机token
:param username:
:return:
"""
timestamp = str(time.time())
m = hashlib.md5(bytes(username, encoding="utf8"))
m.update(bytes(timestamp, encoding="utf8"))
return m.hexdigest()
class LoginView(APIView):
"""
校验用户名密码是否正确从而生成token的视图
"""
def post(self, request):
res = {"code": 0}
print(request.data)
username = request.data.get("username")
password = request.data.get("password")
user = models.UserInfo.objects.filter(username=username, password=password).first()
if user:
# 如果用户名密码正确
token = get_random_token(username)
models.Token.objects.update_or_create(defaults={"token_code": token}, user=user)
res["token"] = token
else:
res["code"] = 1
res["error"] = "用户名或密码错误"
return Response(res)<wiz_code_mirror>
38
1
# 视图主要处理用户名、密码是否正确,用户每一次请求都要带着专有token来!
2
import hashlib, time
3
from rest_framework.response import Response
4
from rest_framework.views import APIView
5
6
7
def get_random_token(username):
8
"""
9
根据用户名和时间戳生成随机token
10
:param username:
11
:return:
12
"""
13
timestamp = str(time.time())
14
m = hashlib.md5(bytes(username, encoding="utf8"))
15
m.update(bytes(timestamp, encoding="utf8"))
16
return m.hexdigest()
17
18
19
class LoginView(APIView):
20
"""
21
校验用户名密码是否正确从而生成token的视图
22
"""
23
def post(self, request):
24
res = {"code": 0}
25
print(request.data)
26
username = request.data.get("username")
27
password = request.data.get("password")
28
29
user = models.UserInfo.objects.filter(username=username, password=password).first()
30
if user:
31
# 如果用户名密码正确
32
token = get_random_token(username)
33
models.Token.objects.update_or_create(defaults={"token_code": token}, user=user)
34
res["token"] = token
35
else:
36
res["code"] = 1
37
res["error"] = "用户名或密码错误"
38
return Response(res)
定义认证类model_serializer.py
# 这一步是要对着源码才能写出来
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
class MyAuth(BaseAuthentication):
def authenticate(self, request):
if request.method in ["POST", "PUT", "DELETE"]:
request_token = request.data.get("token", None)
if not request_token:
raise AuthenticationFailed(‘缺少token‘)
token_obj = models.Token.objects.filter(token_code=request_token).first()
if not token_obj:
raise AuthenticationFailed(‘无效的token‘)
return token_obj.user.username, None
else:
return None, None
<wiz_code_mirror>
18
1
# 这一步是要对着源码才能写出来
2
from rest_framework.authentication import BaseAuthentication
3
from rest_framework.exceptions import AuthenticationFailed
4
5
6
class MyAuth(BaseAuthentication):
7
def authenticate(self, request):
8
if request.method in ["POST", "PUT", "DELETE"]:
9
request_token = request.data.get("token", None)
10
if not request_token:
11
raise AuthenticationFailed(‘缺少token‘)
12
token_obj = models.Token.objects.filter(token_code=request_token).first()
13
if not token_obj:
14
raise AuthenticationFailed(‘无效的token‘)
15
return token_obj.user.username, None
16
else:
17
return None, None
18
全局配置
# 在settings.py中配置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
}<wiz_code_mirror>
4
1
# 在settings.py中配置
2
REST_FRAMEWORK = {
3
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
4
}
权限组件
只有vip才能看的内容
自定义权限类
# 自定义权限类
from rest_framework.permissions import BasePermission
class MyPermission(BasePermission):
message = ‘VIP用户才能访问‘
def has_permission(self, request, view):
"""
自定义权限只有VIP用户才能访问
"""
# 因为在进行权限判断之前已经做了认证判断,所以这里可以直接拿到request.user
if request.user and request.user.type == 2: # 如果是VIP用户
return True
else:
return False<wiz_code_mirror>
15
1
# 自定义权限类
2
from rest_framework.permissions import BasePermission
3
4
class MyPermission(BasePermission):
5
message = ‘VIP用户才能访问‘
6
7
def has_permission(self, request, view):
8
"""
9
自定义权限只有VIP用户才能访问
10
"""
11
# 因为在进行权限判断之前已经做了认证判断,所以这里可以直接拿到request.user
12
if request.user and request.user.type == 2: # 如果是VIP用户
13
return True
14
else:
15
return False
视图级别配置
class CommentViewSet(ModelViewSet):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
authentication_classes = [MyAuth, ]
permission_classes = [MyPermission, ]<wiz_code_mirror>
6
1
class CommentViewSet(ModelViewSet):
2
3
queryset = models.Comment.objects.all()
4
serializer_class = app01_serializers.CommentSerializer
5
authentication_classes = [MyAuth, ]
6
permission_classes = [MyPermission, ]
全局配置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
}<wiz_code_mirror>
4
1
REST_FRAMEWORK = {
2
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
3
"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
4
}
频率组件
频率:限制用户访问网站的频率
自定义限制类
VISIT_RECORD = {}
# 自定义限制
class MyThrottle(object):
def __init__(self):
self.history = None
def allow_request(self, request, view):
"""
自定义频率限制60秒内只能访问三次
"""
# 获取用户IP
ip = request.META.get("REMOTE_ADDR")
timestamp = time.time()
if ip not in VISIT_RECORD:
VISIT_RECORD[ip] = [timestamp, ]
return True
history = VISIT_RECORD[ip]
self.history = history
history.insert(0, timestamp)
while history and history[-1] < timestamp - 60:
history.pop()
if len(history) > 3:
return False
else:
return True
def wait(self):
"""
限制时间还剩多少
"""
timestamp = time.time()
return 60 - (timestamp - self.history[-1])<wiz_code_mirror>
33
1
VISIT_RECORD = {}
2
# 自定义限制
3
class MyThrottle(object):
4
5
def __init__(self):
6
self.history = None
7
8
def allow_request(self, request, view):
9
"""
10
自定义频率限制60秒内只能访问三次
11
"""
12
# 获取用户IP
13
ip = request.META.get("REMOTE_ADDR")
14
timestamp = time.time()
15
if ip not in VISIT_RECORD:
16
VISIT_RECORD[ip] = [timestamp, ]
17
return True
18
history = VISIT_RECORD[ip]
19
self.history = history
20
history.insert(0, timestamp)
21
while history and history[-1] < timestamp - 60:
22
history.pop()
23
if len(history) > 3:
24
return False
25
else:
26
return True
27
28
def wait(self):
29
"""
30
限制时间还剩多少
31
"""
32
timestamp = time.time()
33
return 60 - (timestamp - self.history[-1])
视图级别配置
class CommentViewSet(ModelViewSet):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
throttle_classes = [MyThrottle, ]<wiz_code_mirror>
x
1
class CommentViewSet(ModelViewSet):
2
3
queryset = models.Comment.objects.all()
4
serializer_class = app01_serializers.CommentSerializer
5
throttle_classes = [MyThrottle, ]
全局配置
# 在settings.py中设置rest framework相关配置项
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
"DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]
}<wiz_code_mirror>
1
# 在settings.py中设置rest framework相关配置项
2
REST_FRAMEWORK = {
3
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
4
"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
5
"DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]
6
}
认证组件的源码阅读
源码、源码、源码!
新构建的request里面的源码的user方法
源码走到了这里其实就已经需要我们自己来进行认证了。就可以对前端的请求进行认证,到底该怎么认证,还得继续往下走!
权限组件的源码阅读
相比较与认证组件,权限组件就更加的简洁了
频率组件的注意部分
原文地址:https://www.cnblogs.com/pontoon/p/10217414.html