认证

(我是谁?)

身份认证是将传入请求与一组标识凭据相关联的机制,然后,权限和限制策略可以使用这些凭据来确定是否应该允许该请求.

REST框架提供了许多开箱即用的身份验证方案,还允许您实现自定义方案。

身份验证始终在视图的最开始,在发生权限和限制检查之前,以及允许任何其他代码继续之前运行。

request.user 属性通常将设置为contrib.authUser类的实例。

request.auth 属性用于任何其他身份验证信息,例如,它可用于表示请求已签名的身份验证令牌。

DRF 5种验证方式

# 基于用户名和密码的认证
class BasicAuthentication(BaseAuthentication):
pass # 基于Session的认证
class SessionAuthentication(BaseAuthentication):
pass # 基于Tokend的认证
class TokenAuthentication(BaseAuthentication):
pass # 基于远端用户的认证(专用用户管理服务器)
class TokenAuthentication(BaseAuthentication):
pass

如何确定身份验证?

身份验证方案始终定义为类列表。REST框架将尝试对列表中的每个类进行身份验证,并将设置request.user和request.auth使用成功进行身份验证的第一个类的返回值。

如果没有类进行身份验证,request.user则将设置为实例django.contrib.auth.models.AnonymousUser,request.auth并将其设置为None。

的价值request.user和request.auth对身份认证的请求可以通过修改UNAUTHENTICATED_USER和UNAUTHENTICATED_TOKEN设置。

设置身份验证方案

  1. 可以使用该DEFAULT_AUTHENTICATION_CLASSES设置全局设置默认认证方案。例如

     REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.BasicAuthentication',
    'rest_framework.authentication.SessionAuthentication',
    )
    }
  2. 您还可以使用APIView基于类的视图在每个视图或每个视图集的基础上设置身份验证方案。

     from rest_framework.authentication import SessionAuthentication, BasicAuthentication
    from rest_framework.permissions import IsAuthenticated
    from rest_framework.response import Response
    from rest_framework.views import APIView class ExampleView(APIView):
    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (IsAuthenticated,) def get(self, request, format=None):
    content = {
    'user': unicode(request.user), # `django.contrib.auth.User` instance.
    'auth': unicode(request.auth), # None
    }
    return Response(content)
  3. 或者,如果您正在使用@api_view具有基于功能的视图的装饰器。

     @api_view(['GET'])
    @authentication_classes((SessionAuthentication, BasicAuthentication))
    @permission_classes((IsAuthenticated,))
    def example_view(request, format=None):
    content = {
    'user': unicode(request.user), # `django.contrib.auth.User` instance.
    'auth': unicode(request.auth), # None
    }
    return Response(content)

案例: 基于自定义Token认证

第一步: 定义一个用户表和一个保存用户Token的表

class UserInfo(models.Model):
username = models.CharField(max_length=16)
password = models.CharField(max_length=32)
type = models.SmallIntegerField(
choices=((0, '普通用户'), (1, 'VIP用户')),
default=0
) class Token(models.Model):
user = models.OneToOneField(to='UserInfo')
token_code = models.CharField(max_length=128)

第二步: 定义一个登陆视图

from rest_framework.views import APIView
from app2 import models
from rest_framework.response import Response
import hashlib, time def get_random_token(username):
"""
根据用户名和时间戳生成随机token
"""
timestamp = str(time.time())
m = hashlib.md5(bytes(username, encoding="utf-8"))
m.update(bytes(timestamp, encoding="utf-8"))
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)

第三步定义一个认证类

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app2 import models class MyAuth(BaseAuthentication):
def authenticate(self, request):
# if request.method in ["POST", "PUT", "DELETE"]: # 如果在表单中需要判断请求方式 由于表单是post请求,所以获取token 的方式为 request.data.get("token")
# request.query_params为url中的参数
request_token = request.query_params.get("token", None)
if not request_token:
raise AuthenticationFailed('q.缺少token') token_obj = models.Token.objects.filter(token_code=request_token).first()
if not token_obj:
raise AuthenticationFailed("无效的Token")
# token_obj.user 通过token这张表的对象和user这个关联字段 找到 UserInfo表的对象及当前用户对象
return token_obj.user, request_token # else:
# return None, None

第四步: 使用认证类

视图级别认证

# (用的不多)
class CommentViewSet(ModelViewSet): queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
authentication_classes = [MyAuth, ]

全局级别认证

# 在settings.py中配置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
}

最新文章

  1. 网络爬虫: 从allitebooks.com抓取书籍信息并从amazon.com抓取价格(3): 抓取amazon.com价格
  2. jquery placeholder
  3. Python--逆序打印
  4. MVC应用程序的生命周期图
  5. 【Jquery mobile】动态加载ListView 转
  6. [ruby on rails] 跟我学之(7)创建数据
  7. erlang mnesia 数据库实现SQL查询
  8. Python核心编程(第九章)--文件和输入输出
  9. Content-Disposition的使用和注意事项(转载)
  10. Ansible系列(一):基本配置和使用
  11. C语言超级搞笑的代码,冷笑话我们程序员也会讲的啊!
  12. WordPress安装官方文档教程
  13. SpringMVC+Shiro不拦截静态资源配置
  14. [PHP]误读支付宝接口可能引发的乌龙
  15. SoapUI 接口测试之post提交本地数据文件
  16. 准确率,召回率,F值,机器学习分类问题的评价指标
  17. 3. 支持向量机(SVM)拉格朗日对偶性(KKT)
  18. Java Web知识梳理
  19. git log 查找
  20. ComboBoxEdit 数据绑定 使用模板

热门文章

  1. Configuration.SectionGroups
  2. [Django基础] gunicorn启动django时静态文件的加载
  3. Java多线程相关的常用接口
  4. Scala快速统计文件中特定单词,字符的个数
  5. 69.资金管理-税率表管理extjs 页面
  6. 过河 2005年NOIP全国联赛提高组(离散化+dp)
  7. [Swift通天遁地]四、网络和线程-(9)上传图片并实时显示上传进度
  8. xfs文件备份恢复篇一vm中linux新增磁盘
  9. jeecg中列表查询数据关联其他表的显示
  10. BZOJ 3779 LCT 线段树 DFS序 坑