您现在的位置是: 网站首页 >Django >Vue+Django REST framework前后端分离生鲜电商 Django
【Vue+DRF生鲜电商】12.用户登录之DRF Token认证登录原理和使用方法
admin2019年5月4日 21:56 【Django | Python | Vue 】 2879人已围观
Vue+Django REST framework前后端分离生鲜电商简介 Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。 Github地址:https://github.com/xyliurui/DjangoOnlineFreshSupermarket ; Django版本:2.2、djangorestframework:3.9.2。 前端Vue模板可以直接联系我拿。
在购买商品时,需要用户登录才能操作,所以就必须要增加登录和注册功能。 由于在Django中配置了`path('api-auth/', include('rest_framework.urls')), # drf 认证url`的URL,所以在DRF中可以直接使用认证功能 比如退出登录后,此时的链接为: http://127.0.0.1:8000/api-auth/login/?next=/goods/ ![BLOG_20190504_220135_67](/media/blog/images/2019/05/BLOG_20190504_220135_67.png "博客图集BLOG_20190504_220135_67.png") 在这也有csrf做表单的安全验证。但是在前后端分离的系统中是无法使用的。 前端会运行到其他站点,相当于是跨站了,无法使用csrf验证。 ## DRF Token认证登陆原理 访问 https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication 查看使用方法 此身份验证方案使用一个简单的基于令牌的HTTP身份验证方案。令牌身份验证适用于客户机-服务器设置,例如本机桌面和移动客户机。 要使用`TokenAuthentication`方案,需要将身份验证类配置为包含`TokenAuthentication`,另外还包括`rest_framework.authtoken`在`INSTALLED_APPS`设置中。 https://www.django-rest-framework.org/api-guide/authentication/#setting-the-authentication-scheme 中介绍到:可以使用`DEFAULT_AUTHENTICATION_CLASSES`设置全局设置缺省身份验证方案。也就是默认为: ```python # 文章示例 REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', ) } ``` 要使用`TokenAuthentication`认证们还需要增加`'rest_framework.authentication.SessionAuthentication',` ### 配置全局TokenAuthentication 在这个项目中配置为: ```python # DRF配置 REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 'PAGE_SIZE': 5, 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', # 上面两个用于DRF基本验证 'rest_framework.authentication.TokenAuthentication', # TokenAuthentication ) } ``` 然后添加`rest_framework.authtoken`到APPS ```python INSTALLED_APPS = [ # 'simpleui', # 第三方后台,使用https://github.com/newpanjing/simpleui 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # 添加drf应用 'rest_framework', 'rest_framework.authtoken', 'django_filters', # Django跨域解决 'corsheaders', # 注册富文本编辑器ckeditor 'ckeditor', # 注册富文本上传图片ckeditor_uploader 'ckeditor_uploader', 'users.apps.UsersConfig', 'goods.apps.GoodsConfig', 'trade.apps.TradeConfig', 'user_operation.apps.UserOperationConfig', ] ``` 配置完成后执行数据库迁移 ```bash manage.py@DjangoOnlineFreshSupermarket > makemigrations manage.py@DjangoOnlineFreshSupermarket > migrate ``` 执行完查看数据库会增加一个`authtoken_token`的表 ![BLOG_20190504_220109_13](/media/blog/images/2019/05/BLOG_20190504_220109_13.png "博客图集BLOG_20190504_220109_13.png") `user_id`是一个外键,指向现有的用户表。如果之前已经创建了用户,在这个token表是没有记录的。这个表和用户表是一一对应的。创建用户表后需要手动创建token表。也就是当用户注册时,需要调用`token = Token.objects.create(user=...)`来生成token。 对于要进行身份验证的客户机,令牌密钥应该包含在授权HTTP头中。键应该以字符串文字“Token”作为前缀,并用空格分隔两个字符串。例如:`Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b` ### 添加api-token-auth URL 在使用`TokenAuthentication`时,可能希望为客户端提供一种机制,以获得给定用户名和密码的令牌。REST框架提供了一个内置视图来提供这种行为。要使用它,请将`obtain_auth_token`视图添加到您的URLconf: ```python from rest_framework.authtoken import views urlpatterns = [ path('admin/', admin.site.urls), path('api-auth/', include('rest_framework.urls')), # drf 认证url path('api-token-auth/', views.obtain_auth_token), # drf token获取的url path('ckeditor/', include('ckeditor_uploader.urls')), # 配置富文本编辑器url path('', include(router.urls)), # API url现在由路由器自动确定。 # DRF文档 path('docs/', include_docs_urls(title='DRF文档')), ] ``` ### 测试获取token的API 当使用表单数据或JSON将有效的用户名和密码字段提交到视图时,`obtain_auth_token`视图将返回一个JSON响应,测试如下: 这儿使用了一个Google浏览器插件**Restlet Client - REST API Testing ** ![BLOG_20190504_220050_22](/media/blog/images/2019/05/BLOG_20190504_220050_22.png "博客图集BLOG_20190504_220050_22.png") ![BLOG_20190504_220031_76](/media/blog/images/2019/05/BLOG_20190504_220031_76.png "博客图集BLOG_20190504_220031_76.png") 向 http://127.0.0.1:8000/api-token-auth/ 接口 POST `username`和`password` ![BLOG_20190504_220012_22](/media/blog/images/2019/05/BLOG_20190504_220012_22.png "博客图集BLOG_20190504_220012_22.png") 然后这个接口就返回一个token,这时候刷新数据库,就可以看到数据库中已经创建该用户关联的key ![BLOG_20190504_220003_47](/media/blog/images/2019/05/BLOG_20190504_220003_47.png "博客图集BLOG_20190504_220003_47.png") 拿到这个key后,对于要进行身份验证的客户机,令牌密钥应该包含在授权HTTP头中。键应该以字符串文字“Token”作为前缀,并用空格分隔两个字符串。例如: ``` Authorization: Token ff2634eac32ffa4a057ef1f864e738c9e17890e0 ``` ### 使用token进行访问 然后将其填入到请求header中,用来请求所有商品: http://127.0.0.1:8000/goods/ 怎么查看是否是通过认证的用户呢 ![BLOG_20190504_215854_51](/media/blog/images/2019/05/BLOG_20190504_215854_51.png "博客图集BLOG_20190504_215854_51.png") 由于以下视图不好打断点 ```python class GoodsListView(generics.ListAPIView): """ 显示所有的商品列表 """ queryset = Goods.objects.all() serializer_class = GoodsSerializer pagination_class = GoodsPagination ``` 就在`mixins.ListModelMixin`中打上断点。 ![BLOG_20190504_215845_56](/media/blog/images/2019/05/BLOG_20190504_215845_56.png "博客图集BLOG_20190504_215845_56.png") 就可以看到已经可以取出user的值了。 通过以上配置后,数据表中的`token`是永久有效的,它没有被设置过期时间,只要其他人拿到了这个`token`的值,那么就可以用这个`token`来访问网站,实质上是极不安全的。 ## viewsets配置DRF Token认证类 由于已经在 settings.py 中配置了全局token认证:`'rest_framework.authentication.TokenAuthentication'`,对token进行认证,如果验证失败,就会产生异常。 测试,如果传入了一个错误的token,然后去请求: http://127.0.0.1:8000/goods/ 那么,他就会产生错误 ![BLOG_20190504_215814_96](/media/blog/images/2019/05/BLOG_20190504_215814_96.png "博客图集BLOG_20190504_215814_96.png") 但是,商品列表页这种公开的数据,用户不登陆或者登录错误的情况下都应该是可以访问的。另外用户`token`可能会过期的,这时候来访问一个公共的数据也会产生401错误。访问公共数据可以不带`token`,但是很多前端在写的时候都是全局带`token`的。如果在后端解决这个问题? ### 取消全局TokenAuthentication 就需要在 settings.py 中全局`TokenAuthentication`放在视图中处理,那么 settings.py 就需要进行修改,注释掉`TokenAuthentication` ```python # DRF配置 REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 'PAGE_SIZE': 5, 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', # 上面两个用于DRF基本验证 # 'rest_framework.authentication.TokenAuthentication', # TokenAuthentication,取消全局token,放在视图中进行 ) } ``` ### 视图中添加TokenAuthentication 在`GoodsListViewSet`视图中进行测试,添加`authentication_classes` ```python from rest_framework.authentication import TokenAuthentication class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ 显示商品列表,分页、过滤、搜索、排序 """ queryset = Goods.objects.all() # 使用get_queryset函数,依赖queryset的值 serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter,) # 将过滤器后端添加到单个视图或视图集 filterset_class = GoodsFilter authentication_classes = (TokenAuthentication, ) # 只在本视图中验证Token search_fields = ('name', 'goods_desc', 'category__name') # 搜索字段 ordering_fields = ('click_num', 'sold_num', 'shop_price') # 排序 ``` 调试看下能否在继承成类`mixins.ListModelMixin`---`ListModelMixin`---`list`函数中获取到`token`,添加断点 使用正确的`token`请求 http://127.0.0.1:8000/goods/ ![BLOG_20190504_215802_47](/media/blog/images/2019/05/BLOG_20190504_215802_47.png "博客图集BLOG_20190504_215802_47.png") 可以在调试结果中获取到`user`和`token`的值 ![BLOG_20190504_215746_23](/media/blog/images/2019/05/BLOG_20190504_215746_23.png "博客图集BLOG_20190504_215746_23.png") 如果取消视图中的`authentication_classes`类 ```python class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ 显示商品列表,分页、过滤、搜索、排序 """ queryset = Goods.objects.all() # 使用get_queryset函数,依赖queryset的值 serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter,) # 将过滤器后端添加到单个视图或视图集 filterset_class = GoodsFilter # authentication_classes = (TokenAuthentication, ) # 只在本视图中验证Token search_fields = ('name', 'goods_desc', 'category__name') # 搜索字段 ordering_fields = ('click_num', 'sold_num', 'shop_price') # 排序 ``` 再来做同样的请求,就获取不到`user`的值了 ![BLOG_20190504_215734_16](/media/blog/images/2019/05/BLOG_20190504_215734_16.png "博客图集BLOG_20190504_215734_16.png")
很赞哦! (2)
相关文章
文章交流
- emoji
当前用户
未登录,点击 登录专题目录
- 【Vue+DRF生鲜电商】01.课程结构介绍,开发环境搭建
- 【Vue+DRF生鲜电商】02.设置users、goods、trade、user_operation数据库并导入原始数据
- 【Vue+DRF生鲜电商】03.Restful API基础
- 【Vue+DRF生鲜电商】04.Vue项目结构介绍
- 【Vue+DRF生鲜电商】05.商品列表序列化普通方法
- 【Vue+DRF生鲜电商】06.DRF环境配置,使用Serializer类序列化商品列表
- 【Vue+DRF生鲜电商】07.序列化商品分页功能
- 【Vue+DRF生鲜电商】08.ViewSets & Routers显示商品列表
- 【Vue+DRF生鲜电商】09.使用DRF的filter过滤商品列表
- 【Vue+DRF生鲜电商】10.商品分类层级获取,Vue跨域请求商品分类
- 【Vue+DRF生鲜电商】11.Vue展示左侧分类、面包屑、排序、商品列表、分页
- 【Vue+DRF生鲜电商】12.用户登录之DRF Token认证登录原理和使用方法
- 【Vue+DRF生鲜电商】13.JWT用户认证原理配置,Vue登录接口调试
- 【Vue+DRF生鲜电商】14.用户注册发送短信验证码、登录字段验证
- 【Vue+DRF生鲜电商】15.用户注册使用信号量实现密码加密
- 【Vue+DRF生鲜电商】16.Vue中注册、退出功能交互
- 【Vue+DRF生鲜电商】17.DRF实现商品详情及热卖商品接口,Vue中显示商品详情和热卖
- 【Vue+DRF生鲜电商】18.用户收藏、取消收藏商品接口实现
- 【Vue+DRF生鲜电商】19.用户添加、删除收藏权限处理,根据商品id显示收藏,在Vue中实现收藏功能
- 【Vue+DRF生鲜电商】20.使用DRF自动生成文档的功能
- 【Vue+DRF生鲜电商】21.用户中心个人资料的展示,并在Vue中实现个人资料更新
- 【Vue+DRF生鲜电商】22.个人中心显示用户收藏功能,对收藏进行删除
- 【Vue+DRF生鲜电商】23.个人中心用户留言功能
- 【Vue+DRF生鲜电商】24.用户收货地址功能
- 【Vue+DRF生鲜电商】25.商品添加购物车接口功能,Vue和购物车联调
- 【Vue+DRF生鲜电商】26.使用Pycharm远程代码调试服务器Django代码
- 【Vue+DRF生鲜电商】26.订单接口功能,Vue和订单接口联调
- 【Vue+DRF生鲜电商】27.支付宝公钥,私钥,沙箱环境配置
- 【Vue+DRF生鲜电商】28.支付宝支付接口类解读,支付逻辑编辑
- 【Vue+DRF生鲜电商】29.线上服务支付宝接口和Vue联调,Django代理Vue运行
- 【Vue+DRF生鲜电商】30.首页轮播图、新品展示功能
- 【Vue+DRF生鲜电商】31.首页商品按分类显示推荐功能
- 【Vue+DRF生鲜电商】32.商品操作后计数更改,热搜榜关键字功能实现
- 【Vue+DRF生鲜电商】33.数据缓存、接口访问限速功能
- 【Vue+DRF生鲜电商】34.第三方登录(微博、qq和微信)之微博登录登录测试
- 【Vue+DRF生鲜电商】35.使用social-app-django集成第三方登录