APIKEY 的设计与使用
一、APIKEY 的生成与存储
-
随机生成 APIKEY:常用的方法是使用随机字符串生成器或数据加密方法生成字符串,确保每个 APIKEY 都是唯一的。 -
存储:APIKEY 可以存储在数据库中,但为了安全起见,通常会使用加密的方式存储。
二、APIKEY 的传递
-
在请求头中传递:大多数情况下,APIKEY 会作为请求头的一部分发送。 -
请求参数:在某些情况下,APIKEY 也可以作为请求参数的一部分。但这种方法不安全,因为请求参数容易被记录或查看。
三、APIKEY 的使用限制
-
限制 IP 地址:可以为 APIKEY 设置允许的 IP 地址范围,增加安全性。(在模型中设置字段,访问接口做验证) -
限制使用频率:可以设置 API 请求的频率限制,防止被滥用。(设置频率字段,接口验证频率次数) -
有效期限制:为 APIKEY 设置有效期,过期后需要重新生成。(设置过期时间)
四、APIKEY 的作用
-
身份验证:APIKEY 可用于验证请求者的身份。 -
授权控制:基于 APIKEY 可以控制哪些用户或系统可以访问特定的 API。 -
跟踪和分析:APIKEY 可以用于分析请求的数据,例如流量、使用情况等。 -
安全保护:APIKEY 增加了非法访问的难度,减少了未经授权的访问。
五、注意事项
-
不要在客户端代码中硬编码 APIKEY,因为这样会导致安全风险。 -
定期审查和更新 APIKEY,确保其安全性和有效性。 -
对于不再使用的 APIKEY,应及时删除或使其失效。 -
使用 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
使用 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