Python项目单独设置API-KEY

APIKEY 的设计与使用

Python项目单独设置API-KEY
cc6619482f68483bd738c264112c3721

一、APIKEY 的生成与存储

  1. 随机生成 APIKEY:常用的方法是使用随机字符串生成器或数据加密方法生成字符串,确保每个 APIKEY 都是唯一的。
  2. 存储:APIKEY 可以存储在数据库中,但为了安全起见,通常会使用加密的方式存储。

二、APIKEY 的传递

  1. 在请求头中传递:大多数情况下,APIKEY 会作为请求头的一部分发送。
  2. 请求参数:在某些情况下,APIKEY 也可以作为请求参数的一部分。但这种方法不安全,因为请求参数容易被记录或查看。

三、APIKEY 的使用限制

  1. 限制 IP 地址:可以为 APIKEY 设置允许的 IP 地址范围,增加安全性。(在模型中设置字段,访问接口做验证)
  2. 限制使用频率:可以设置 API 请求的频率限制,防止被滥用。(设置频率字段,接口验证频率次数)
  3. 有效期限制:为 APIKEY 设置有效期,过期后需要重新生成。(设置过期时间)

四、APIKEY 的作用

  1. 身份验证:APIKEY 可用于验证请求者的身份。
  2. 授权控制:基于 APIKEY 可以控制哪些用户或系统可以访问特定的 API。
  3. 跟踪和分析:APIKEY 可以用于分析请求的数据,例如流量、使用情况等。
  4. 安全保护:APIKEY 增加了非法访问的难度,减少了未经授权的访问。

五、注意事项

  1. 不要在客户端代码中硬编码 APIKEY,因为这样会导致安全风险。
  2. 定期审查和更新 APIKEY,确保其安全性和有效性。
  3. 对于不再使用的 APIKEY,应及时删除或使其失效。
  4. 使用 HTTPS 协议来传输 API 请求和数据,确保数据的安全性。

Django 框架中如何实现单独设置 APIKEY

新建 APIKEY 模型

class ApiKeyToken(models.Model):
    key = models.CharField(max_length=40, primary_key=True, verbose_name='key')
    platform = models.CharField(max_length=40, verbose_name='api-key运用平台', default='netops')
    is_active = models.BooleanField(default=True, verbose_name='状态')
    lastGetTime = models.DateTimeField(blank=True, auto_now=True, null=True, verbose_name='最近查询时间')
    expireTime = models.DateTimeField(blank=True, auto_now=True, null=True, verbose_name='key过期时间')
    countTimes = models.IntegerField(blank=True, null=True, verbose_name='key使用次数')
    serverIp = models.CharField(blank=True, null=True, verbose_name='key提供服务的IP或IP范围',max_length=100)

    def save(self, *args, **kwargs):
        if not self.key:
            self.key = self.generate_key()
        return super(ApiKeyToken, self).save(*args, **kwargs)

    def generate_key(self):
        return binascii.hexlify(os.urandom(20)).decode()

    def __unicode__(self):
        return self.key

    class Meta:
        # abstract = True
        db_table = 'apikey_model'  # 通过db_table自定义数据表名
        verbose_name = _('ApiKey')
        verbose_name_plural = _('ApiKey')


执行数据迁移

python manage.py makemigrations

python manage.py migrate

Python项目单独设置API-KEY
image

使用 APIKEY 模型

生成 APIKEY


api_key_token = ApiKeyToken()
api_key_token.key = api_key_token.generate_key()
api_key_token.save()

使用 APKEY

新建验证类 auth.py

from rest_framework.authentication import TokenAuthentication, get_authorization_header
from rest_framework.exceptions import AuthenticationFailed

from open_ipam.models import ApiKeyToken


class ApiKeyAuthentication(TokenAuthentication):

    def get_token_from_auth_header(self, auth):
        auth = auth.split()
        # print(auth)
        if not auth or auth[0].lower() != b'api-key':
            return AuthenticationFailed('Invalid api-key header. No credentials provided.')

        if len(auth) == 1:
            raise AuthenticationFailed('Invalid api-key header. No credentials provided.')
        elif len(auth) > 2:
            raise AuthenticationFailed('Invalid api-key header. Token string should not contain spaces.')

        try:
            return auth[1].decode()
        except UnicodeError:
            raise AuthenticationFailed('Invalid api-key header. Token string should not contain invalid characters.')

    def authenticate(self, request):
        auth = get_authorization_header(request)
        token = self.get_token_from_auth_header(auth)

        if not token:
            token = request.GET.get('api-key', request.POST.get('api-key', None))

        if token:
            return self.authenticate_credentials(token)

    def authenticate_credentials(self, key):
        try:
            token = ApiKeyToken.objects.get(key=key)
        except ApiKeyToken.DoesNotExist:
            raise AuthenticationFailed('Invalid Api key.')

        if not token.is_active:
            raise AuthenticationFailed('Api key inactive or deleted.')

        # user = token.company.users.first()  # what ever you want here
        return token

新建装饰器

def check_api_key(func):
    auth_check = ApiKeyAuthentication()

    def wrap(view, request):
        if request.headers['Authorization']:
            if 'api-key' in request.headers['Authorization']:
                auth_check.authenticate(request)
                return func(view, request)
            else:
                raise AuthenticationFailed('Invalid api-key header. No credentials provided.')
        raise "Invalid Api key"

    return wrap

使用装饰器

class IpamOpenAPI(APIView):
    @check_api_key
    def post(self, request):
        pass

如此用户请求当前 View 时候,则会先经过装饰器进行 APIKEY 的校验。在视图函数中,我们首先从请求头中获取 APIKEY,然后查询数据库验证 APIKEY 的有效性。如果 APIKEY 无效或缺失,我们返回相应的错误响应。如果 APIKEY 有效,则继续处理请求。

目前实现的 APIKEY 校验方式仅仅是一种类型,需要注意的是,在实际应用中,应该使用更加安全的方式来存储和验证 APIKEY,例如使用加密的存储方式、引入更强大的身份验证机制等。此外,还应该考虑其他的安全措施,例如限制 API 的访问频率、限制 IP 地址等


原文始发于微信公众号(有追求的开发者):Python项目单独设置API-KEY

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/256948.html

(0)
李, 若俞的头像李, 若俞

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!