1.登录鉴权跟 Token 的鉴权区别

以 Django 的账号密码登录为例来说明传统的验证鉴权方式是怎么工作的,当我们登录页面输入账号密码提交表单后,会发送请求给服务器,服务器对发送过来的账号密码进行验证鉴权,验证鉴权通过后,把用户信息记录在服务器端( django_session 表中),同时返回给浏览器一个 sessionid 用来唯一标识这个用户,浏览器将 sessionid 保存在 cookie 中,之后浏览器的每次请求都一并将 sessionid 发送给服务器,服务器根据 sessionid 与记录的信息做对比以验证身份

Token 的鉴权方式就清晰很多了,客户端用自己的账号密码进行登录,服务端验证鉴权,验证鉴权通过生成 Token 返回给客户端,之后客户端每次请求都将 Token 放在 header 里一并发送,服务端收到请求时校验 Token 以确定访问者身份

session 的主要目的是给无状态的 HTTP 协议添加状态保持,通常在浏览器作为客户端的情况下比较通用。而 Token 的主要目的是为了鉴权,同时又不需要考虑 CSRF 防护以及跨域的问题,所以更多的用在专门给第三方提供 API 的情况下,客户端请求无论是浏览器发起还是其他的程序发起都能很好的支持。所以目前基于 Token 的鉴权机制几乎已经成了前后端分离架构或者对外提供 API 访问的鉴权标准,得到广泛使用

2.基于restframework 的用户验证跟 django 用户验证的区别

基于restframework 的用户验证跟 django 用户验证的区别 :

django 用户验证只是基于 cookie 与 session 来完成的。而restframework还可以通过token 

其中的问题就在于中间件的差距。

 

我现在访问我的 restf api 接口时可以看到浏览器会有一个登陆 ,这里通过 django 创建的 超级用户或者注册的用户就可以登陆

这是因为我们在 django 的url 中配置了

url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),

而 对应的 rest_framework.urls 有 包含 login 和 logout 两个url。

如果使用django会验证 csrf ,我们登陆时 django 返回的 html 中其实是包含一个 csrf 的 code 的,用来做表单的 安全验证的。(这是因为django默认打开 csrf 中间件,如果关闭了就不会校验csrf)

所以如果用户验证需要做成 restful api ,这个 自带的 login是无法拿来直接用的。

如果我们需要做成一个前后端分离的用户验证, 就需要通过其他的方法。 【Auth 模块】 django 的 MIDDLEWARE 中包含的以下两个 MIDDLEWARE 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 可以在一个 request 进来的时候,将request里的 cookie 里面的 session_id 转换成 我们的 user !!!!! 也就是我们之前看到的 request.user 。   我们现在需要配置 restful 的 MIDDLEWARE , 直接在 django 的 settings.py 里面添加 REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', ) } 官方文档显示 restful 提供的 auth 有三种 : BasicAuthentication 、 TokenAuthentication 、 SessionAuthentication 。 其中 : SessionAuthentication :跟django中的机制是一样的, 常用于浏览器, 因为浏览器会自动设置 cookie ,并将他的 cooike 和session 带到服务器, 所以前后端分离的系统用这种机制比较少见,但是还是可以做。 TokenAuthentication : 是需要重点关注的,使用他前 ,必须先将 'rest_framework.authtoken' 添加到 django 的 INSTALLED_APPS 中。 INSTALLED_APPS = ( ... 'rest_framework.authtoken' ) 这个 tokenauth 实际上会给我们创建一张表,凡是有表的 app 都要加入到 INSTALLED_APPS 中。 如果不加人,就不会帮我们生成这些表。 此时执行 migrate 进行数据迁移。 可以看到为我们生成了一张表,该表有一个外键指向我们的 UserProfile (用户信息)表。   一个用户对于一个 token 。 而我创建一个超级用户的时候,并没有在 authtoken_token 这张表里面给我添加一个对应的 token 。 这个 token 需要我们自己来创建 。创建方法如下 ,调用 Token 模块,将 user 传进去:   from rest_framework.authtoken.models import Token token = Token.objects.create(user=...) print token.key   所以 当用户注册时保存了提交的 UserProfile 之后,调用这段代码,把保存的 UserProfile 传进去。 这样就会生成 token 。

而后端需要在 django 的 url 中配置 token 的url :


from rest_framework.authtoken import views urlpatterns += [ url(r'^api-token-auth/', views.obtain_auth_token) ]


现在可以通过向 http://127.0.0.1:8000/api-token-auth/ 这个url 发送 post 请求并且携带


{


"username":"admin",


"password":"admin123456"


}


这个方式来获取 token ,发送请求后,他会返回一个 token 。此时如果这个 UserProfile


没有对应的 key ,就会在 authtoken_token 这张表创建一条数据 ,并且关联到你提交的


用户 ,给他生成一个 key 。




前端如何使用这个 token ? 【把他放到 http 的 header 里面】


对于客户端进行身份验证,令牌密钥应该包含在AuthorizationHTTP头中。关键字应以字符串文字“Token”为前缀,用空格分隔两个字符串。例如:


Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b



此时我在我的 url 请求的头部添加这个之后,访问我的 restful api 资源了后台获取到这个 token 后


还不能解析出这个 token 对应的用户是谁,我们需要在 REST_FRAMEWORK 里添加


'rest_framework.authentication.TokenAuthentication',


才能解析出对应的用户 。


REST_FRAMEWORK = {


'DEFAULT_AUTHENTICATION_CLASSES': (


'rest_framework.authentication.BasicAuthentication',


'rest_framework.authentication.SessionAuthentication',


'rest_framework.authentication.TokenAuthentication',


)


}


此时需要知道用户传递过来的 token 是什么 ,直接通过 request.auth 就可以看到。


完成 上面两步,就可以访问我的 restful api 资源了。


(以前需要登录,现在只要头部包含 这个 token 就可以访问。)



如果用户在 token 过期的情况下访问公共url , 就会报错, 这个问题前端也可以解决,后端的解决方案是, 把这个 token 验证不放在 settings.py 里做全局验证, 只对部分接口做验证。


把 REST_FRAMEWORK 中下面这个


1. 'rest_framework.authentication.TokenAuthentication',


注释掉 ,


2.在需要做验证的视图那里 导入


from rest_framework.authentication import TokenAuthentication


然后在视图里添加 authentication_classes 属性。 因为要给他个元组, 所以记得用逗号


authentication_classes = (TokenAuthentication, )




这个 token 的缺点是 :


1.这个token 是保存在服务器里面的。


如果我们是一个分布式系统,有两套子系统想要使用同一个认证系统,他就会出现问题,


因为他的 token 是放在某一台服务器的,如果是分布式的,那我们还得将这些用户同步过去。


2.这个 toen 是没有过期时间的,永久有效,一旦泄露了别人就可以一直用。

2 django中实现token:引入DRF 框架

注意DRF框架是基于django,也就是说使用DRF包就必须安装django。所以文件结构和django一样,可以混用:既开发django也开发djangorestframework。

setting中的配置:REST框架API的任何全局设置都保存在一个名为REST framework的配置字典中。与django不冲突。

当我们用浏览器访问rest_framework 的应用时REST framework的配置生效,而我们访问我们正常的django的app时django的配置生效。注意这里都是全局配置

尤其是对应中间件的配置,和项目目录下的url文件息息相关。

 正常情况下我们会引入:

'rest_framework',而我们现在只需要认证功能 rest_framework.authtoken

在配置中加入TokenAuthentication,也就是通过token 我们就可以直接从request 中取出user(这就是中间件的好处)取出user意味着登陆状态

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
)
}

setting文件 REST_FRAMEWORK 配置:https://www.django-rest-framework.org/ (中间件)

DEFAULT_AUTHENTICATION_CLASSES
身份验证类的列表或元组,用于确定访问request.user或request.auth属性时使用的默认验证器集。 默认: (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
)
DEFAULT_PERMISSION_CLASSES
权限类的列表或元组,用于确定在视图开头检查的默认权限集。必须由列表中的每个类授予权限。
# Use Django's standard `django.contrib.auth` permissions,

 # or allow read-only access for unauthenticated users.

 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'

 'rest_framework.permissions.IsAdminUser',(仅管理员可以访问DRF的所有url)

 'rest_framework.permissions.IsAuthenticated', #必须有(必需认证过才能访问DRF所有url)


默认:
( 'rest_framework.permissions.AllowAny', )

PAGE_SIZE
用于分页的默认页面大小。如果设置为None,则默认情况下禁用分页。

使用:

配置所有,

sender指定settings.AUTH_USER_MODEL

设置每次新生成用户时,自动生成token的signals。

from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token # 为每个用户添加token验证
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)

.__init__.py 将它放在models.py文件中的任何地方,它将在Django线程启动时注册(__init__.py也是可以的)

from .signals import create_auth_token

sender指定实体

from django.contrib.auth.models import User
@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)

在view中进行token验证

没有就创建并且取出token,有就直接取出token

        token, created = Token.objects.get_or_create(user=user)

虽然在django设置文件中指定了REST_FRAMEWORK设置,但是基于函数的视图需要@api_view装饰器,否则,根本不执行令牌认证

django自带app和django_rest_framework的区别:

from rest_framework.decorators import api_view

@api_view(['POST','GET'])
def my_view(request):
if request.user.is_authenticated():
...

过期时间:

https://www.cnblogs.com/hello-/articles/9090786.html

https://www.jianshu.com/p/078fb116236e

3.django中实现:JWT

https://www.v2ex.com/t/530103

django认证01---token的更多相关文章

  1. django 认证系统--3

    WEB request中的认证 django使用sessions和middleware和reqeust对象联系在一起 它们通过给每一个reqeust请求添加一个request.user属性来代表当前用 ...

  2. 应用JWT进行用户认证及Token的刷新

    本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及Token的刷新方案(ASP.NET Core 系列目录) 一.什么是JWT? JWT(json web token ...

  3. ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证及Token的刷新

    来源:https://www.cnblogs.com/FlyLolo/p/ASPNETCore2_26.html 本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及T ...

  4. Django框架01 / http协议、web框架本质

    Django框架01 / http协议.web框架本质 目录 Django框架01 / http协议.web框架本质 1.http协议 1.1 http协议简介 1.2 什么是http协议 1.3 H ...

  5. Django认证系统并不鸡肋反而很重要

    在使用django-admin startproject创建项目后,Django就默认安装了一个采用session实现的认证系统.这是Django相比于其他框架的一大特点:自带认证系统,开箱即用.有人 ...

  6. 自定义Django认证系统的技术方案

    Django已经提供了开箱即用的认证系统,但是可能并不满足我们的个性化需求.自定义认证系统需要知道哪些地方可以扩展,哪些地方可以替换.本文就来介绍自定义Django认证系统的相关技术细节. 自定义认证 ...

  7. Django(72)Django认证系统库--djoser

    djoser是什么?   作用:Django认证系统的REST实现.djoser库提供了一组Django Rest Framework视图,用于处理注册.登录.注销.密码重置和帐户激活等基本操作.它适 ...

  8. Django认证系统auth认证

    使用Django认证系统auth认证 auth认证系统可以处理范围非常广泛的任务,且具有一套细致的密码和权限实现.对于需要与默认配置不同需求的项目,Django支持扩展和自定义认证;会将用户信息写入到 ...

  9. django认证系统 Authentication

    Django自带一个用户认证系统,用于处理用户账户.群组.许可和基于cookie的用户会话. Django的认证系统包含了身份验证和权限管理两部分.简单地说,身份验证用于核实某个用户是否合法,权限管理 ...

随机推荐

  1. F 阎小罗的Minimax (第十届山东理工大学ACM网络编程擂台赛 正式赛 )

    题解:by Mercury_Lc 阎小罗的矩阵给的n和m都不超过300,枚举一下所有情况就可以了,用前缀和来储存.数组a[x][y]代表前x行前y列的和是多少,那么枚举每一种切割的方式就可以.注意一下 ...

  2. sweiper做一个tab切换

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Maven项目打包时指定配置策略

    以数据库连接池的配置文件(db.properties)为例,一般的项目会有开发用数据库,测试用数据库,正式环境数据库三种配置. 以前的做法是拷贝成三份,注释掉其他了两份 # 开发用 jdbc.url ...

  4. org.springframework.expression.spel.SpelEvaluationException: EL1030E

    问题与分析 在本地开发项目时发现报错如下: org.springframework.expression.spel.SpelEvaluationException: EL1030E: The oper ...

  5. avalon background-image写法

    ms-css="{backgroundImage: 'url('+reportdata.avatar + ')'}"

  6. Java核心复习——J.U.C LinkedBlockingQueue源码分析

    参考文档 LinkedBlockingQueue和ArrayBlockingQueue的异同

  7. ORACLE数据库误删恢复

    一.表的恢复 对误删的表,只要没有使用PURGE永久删除选项,那么从flash back区恢复回来希望是挺大的.一般步骤有: 1.从flash back里查询被删除的表 select * from r ...

  8. Comet OJ - Contest #6 B.双倍快乐(二维最大上升子序列和)

    双倍快乐 题目描述 Illyasviel:"你想要最长不下降子序列吗?" star-dust:"好啊!" Illyasviel:"老板,给我整两个最长 ...

  9. Linux 系统配置IPv6

    1.自动获取IPV6地址 1)修改/etc/sysconfig/network文件,修改如下字段,不存在则手动添加,部分系统默认是开启的NETWORKING_IPV6=yes 2)修改/etc/sys ...

  10. Spring @RestController、@Controller区别

    一.用@Controller,返回的是页面:@Controller加上@ResponseBody,返回的是JSON.XML或其他文本. @Controller @RequestMapping(&quo ...