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

1、API使用流程

使用过API的同窗都知道,咱们不可能任意调用人家的API,由于经过API能够获取不少关键数据,并且这个API可能供多个部门或我的使用,因此必须是通过受权的用户才能调用。python

API的使用过程通常是:数据库

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

 

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

(B)用户赞成给予客户端受权,给用户username和password。

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

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

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

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

 

2、REST-framework实现

一、用户登录url

urls文件api

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

二、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
 

三、serializer.py文件

用户表api序列化app

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

 

 

四、views函数

一、实现user表APIdom

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

注意:post

用户每次登录时才会进行认证,生成一次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()

 

五、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
 

 

3、应用

一、局部应用

当咱们只须要对局部资源进行认证时,能够单独设定authentication_classes变量,指定token功能模块便可。

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

 

测试:

 

加上Token后:

 

二、全局应用

 咱们在setttings文件里面指定REST_FRAMEWORK变量便可。

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

 

三、免token访问

全局应用后,全部资源都须要携带token才能访问,若是不但愿通过认证的话,能够以下设置:

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

 

authentication_classes = []

 

相关文章
相关标签/搜索