前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何让 Python 写的 API 接口同时支持 Session 和 Token 认证?

如何让 Python 写的 API 接口同时支持 Session 和 Token 认证?

作者头像
州的先生
发布2021-06-21 20:05:10
2.5K0
发布2021-06-21 20:05:10
举报
文章被收录于专栏:州的先生州的先生

Django 是 Python 语言中最受欢迎的 Web 框架之一。其开箱即用的特性,使得我们可以利用它快速搭建一个传统的 Web 应用。

在如今多端横行的互联网,单纯的传统 Web 应用开发已经越来越式微,更多的应用采用了前后端分离的 Web 开发模式,后端只是单纯地提供 API 给前端各个终端(Web、APP、小程序等)调用。

借助于 Django REST Framework 这个第三方库,Django 也能快速生成 RESTful 风格的 API 接口。

通常情况下,需要用户进行登录的 API,我们都统一使用 Token 来进行认证,这样可以确保接口对多端的支持。但是 Django 在 Web 网页端的功能实在是太好用了,以至于很多人舍不得放弃 Django 自带的认证功能。

如果让 Django 写的接口既支持 Token 认证,也能兼容 Django 自带的 Session 认证呢?DRF 框架本身就提供了支持。

DRF 支持的认证模式

REST framework 提供了许多开箱即用的身份认证方案,还允许自定义认证方案。

它一共提供了如下几种认证方案:

  • BasicAuthentication(HTTP Basic 认证):用于根据用户名和密码进行 HTTP 基础身份认证。
  • TokenAuthentication(Token 认证):用于简单的基于 Token 的认证方案,这种方案适合于 CS 模式的应用。
  • SessionAuthentication(Session 认证):使用 Django 的默认会话后端进行身份验证。会话身份验证适用于与网站在相同的会话中运行的 AJAX 客户端。
  • RemoteUserAuthentication(远程用户分组):这种身份认证允许将身份认证交给另一个 Web 服务器(通过设置REMOTE_USER变量指定认证服务器地址)

除此之外,我们还能自定义身份认证,只需要继承BaseAuthentication类进行扩展即可。

在 DRF 中使用认证

在 DRF 框架中,可以通过 2 种方式配置认证方式。

一种是在 Django 的配置文件中通过 REST_FRAMEWORK变量全局设置认证模式,例如:

代码语言:javascript
复制
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
    ]
}

另一种则是在视图中通过authentication_classes属性单独指定每一个视图的认证模式,例如:

代码语言:javascript
复制
from rest_framework.authentication import SessionAuthentication
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    authentication_classes = [SessionAuthentication]

    def get(self, request, format=None):
        content = {
            'user': str(request.user),  # `django.contrib.auth.User` instance.
            'auth': str(request.auth),  # None
        }
        return Response(content)

使用多种认证模式

在上面的示例中,我们可以看到,DRF 的认证模式配置接收的是一个列表,其实我们可以在里面添加多种认证模式。例如:

代码语言:javascript
复制
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
class ExampleView(APIView):
    authentication_classes = [SessionAuthentication, BasicAuthentication]

这样,这个接口就可以通过两种方式进行身份认证。

需要特别注意的一点是,如果使用 Session 认证,那么在登录页面的时候,需要使用 Django 默认的登录视图进行登录操作。

同时,在 Web 页面进行接口请求的时候,需要在 headers 头里面带上X-CSRFToken参数,其值为 Django 的 csrf_token,例如:

代码语言:javascript
复制
headers: {"X-CSRFToken":'{{ csrf_token }}'},

多认证方式接口示例

「觅道文档」中,我们就采用了这样的双认证方式来处理接口的认证。

例如,在用户列表接口中(/Mrdoc/app_admin/views.py 文件 283 行附近),我们是这样定义接口的:

代码语言:javascript
复制
# 后台管理 - 用户列表接口
class AdminUserList(APIView):
    authentication_classes = [SessionAuthentication,AppMustAuth]
    permission_classes = [SuperUserPermission]
    # 获取用户列表
    def get(self, request):
        username = request.query_params.get('username', '')
        page_num = request.query_params.get('page', 1)
        limit = request.query_params.get('limit', 10)
        if username == '':
            user_data = User.objects.all().values(
                'id', 'last_login', 'is_superuser', 'username', 'email', 'date_joined', 'is_active', 'first_name'
            )
        else:
            user_data = User.objects.filter(username__icontains=username).values(
                'id', 'last_login', 'is_superuser', 'username', 'email', 'date_joined', 'is_active', 'first_name'
            )
        page = PageNumberPagination()  # 实例化一个分页器
        page.page_size = limit
        page_users = page.paginate_queryset(user_data, request, view=self)  # 进行分页查询
        serializer = UserSerializer(page_users, many=True)  # 对分页后的结果进行序列化处理
        resp = {
            'code': 0,
            'data': serializer.data,
            'count': user_data.count()
        }
        return Response(resp)

这里面我们使用了SessionAuthenticationAppMustAuth这两个认证方式,其中AppMustAuth是我们自定义的 Token 认证方式,其代码如下所示:

代码语言:javascript
复制
class AppMustAuth(BaseAuthentication):
    '''自定义认证类'''
    def authenticate(self, request):
        token = request.query_params.get('token')
        # print(token)
        if token:
            # 如果请求url中携带有token参数
            user_obj = AppUserToken.objects.filter(token=token).first()
            if user_obj:
                # print("ok")
                # token 是有效的,返回一个元组
                return user_obj.user, token  # request.user, request.auth
            else:
                raise AuthenticationFailed(_('无效的token'))
        else:
            raise AuthenticationFailed(_('请求的URL中必须携带token参数'))

如果我们在未登录或不带 Token 的情况下访问接口,会直接响应 403 Forbidden:

如果浏览器未登录状态下访问接口,会直接响应 403 Forbidden:

如果我们在浏览器登录状态下访问接口,会响应成功:

如果我们在接口中携带 Token 参数,也会响应成功:

有兴趣的小伙伴下载源码看一看、试一试。


?分享、点赞、在看,给个三连击呗!?

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-06-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 州的先生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DRF 支持的认证模式
  • 在 DRF 中使用认证
  • 使用多种认证模式
  • 多认证方式接口示例
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档