REST-framework快速构建API--认证

时间:2024-05-31 21:05:32

一、API使用流程

使用过API的同学都知道,我们不可能任意调用人家的API,因为通过API可以获取很多关键数据,而且这个API可能供多个部门或个人使用,所以必须是经过授权的用户才能调用。

API的使用过程一般是:

携带用户名和密码(或者是AK/SK)之类的信息进行登陆,获得一个授权的Token,后续通过此Token进行资源申请。流程图如下:

REST-framework快速构建API--认证

(A)用户打开客户端以后,客户端要求用户给予授权。

(B)用户同意给予客户端授权,给用户username和password。

(C)客户端使用B中的信息获得的授权,向认证服务器申请令牌。

(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E)客户端使用令牌,向资源服务器申请获取资源。

(F)资源服务器确认令牌无误,同意向客户端开放资源。

二、REST-framework实现

REST-framework快速构建API--认证

1、用户登陆url

urls文件

  url(r'^login/$', views.LoginView.as_view(),name="login"),

2、models文件

新增用户表和token表

class User(models.Model):
name=models.CharField(max_length=32)
pwd=models.CharField(max_length=32) class Token(models.Model):
user=models.OneToOneField("User")
token = models.CharField(max_length=128) def __str__(self):
return self.token

3、serializer.py文件

用户表api序列化

class AuthorModelSerializers(serializers.ModelSerializer):
class Meta:
model = Author
fields = "__all__"

 

4、views函数

1、实现user表API

2、通过LoginView函数,实现用户登陆,登陆成功后保存token到数据库,并返回给用户信息;登陆失败则给用户提示。

注意:

用户每次登陆时才会进行认证,生成一次token,不需要每次调用api接口都生成新的token。

class AuthorModelView(viewsets.ModelViewSet):
queryset = Author.objects.all()
serializer_class = AuthorModelSerializers def get_random_str(user):
import hashlib,time
ctime=str(time.time()) md5=hashlib.md5(bytes(user,encoding="utf8"))
md5.update(bytes(ctime,encoding="utf8")) return md5.hexdigest() from .models import User class LoginView(APIView): def post(self,request): name=request.data.get("name")
pwd=request.data.get("pwd")
user=User.objects.filter(name=name,pwd=pwd).first()
res = {"state_code": 1000, "msg": None}
if user: random_str=get_random_str(user.name)
token=Token.objects.update_or_create(user=user,defaults={"token":random_str})
res["token"]=random_str
else:
res["state_code"]=1001 #错误状态码
res["msg"] = "用户名或者密码错误" import json
return Response(json.dumps(res,ensure_ascii=False))

  

注意:在python2中需要修改

def get_random_str(user):
import hashlib, time
ctime = str(time.time()) md5 = hashlib.md5(str(user))
md5.update(ctime) return md5.hexdigest()

5、utils.py

将TokenAuth功能模块单独放入utils文件,便于扩展。

注意:

如果不继承BaseAuthentication,则需要我们自己写authenticate_header函数。

def authenticate_header(self, request):
pass

  继承BASEAuthenticate后,则可以省略,因为他自带了。

from rest_framework import exceptions

from rest_framework.authentication import BaseAuthentication

from .models import *
class TokenAuth(BaseAuthentication):
def authenticate(self,request):
token = request.GET.get("token")
token_obj = Token.objects.filter(token=token).first()
if not token_obj:
raise exceptions.AuthenticationFailed("验证失败123!")
else:
return token_obj.user.name,token_obj.token

三、应用

1、局部应用

当我们只需要对局部资源进行认证时,可以单独设定authentication_classes变量,指定token功能模块即可。

class AuthorModelView(viewsets.ModelViewSet):
authentication_classes = [TokenAuth,]
queryset = Author.objects.all()
serializer_class = AuthorModelSerializers

 

测试:

REST-framework快速构建API--认证

加上Token后:

REST-framework快速构建API--认证

2、全局应用

 我们在setttings文件里面指定REST_FRAMEWORK变量即可。

REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.TokenAuth",]
}

 

3、免token访问

全局应用后,所有资源都需要携带token才能访问,如果不希望经过认证的话,可以如下设置:

在对应View函数里面,设置变量authentication_classes为空列表即可。

authentication_classes = []

REST-framework快速构建API--认证