App开放接口api安全性的设计与实现

Stella981
• 阅读 779

前言

在app开放接口api的设计中,避免不了的就是安全性问题,因为大多数接口涉及到用户的个人信息以及一些敏感的数据,所以对这些接口需要进行身份的认证,

那么这就需要用户提供一些信息,比如用户名密码等,但是为了安全起见让用户暴露的明文密码次数越少越好,我们一般在web项目中,大多数采用保存的session中,

然后在存一份到cookie中,来保持用户的回话有效性。但是在app提供的开放接口中,后端服务器在用户登录后如何去验证和维护用户的登陆有效性呢?

回到目录

设计

对于敏感的api接口,需使用https协议

https是在http超文本传输协议加入SSL层,它在网络间通信是加密的,所以需要加密证书。https协议需要ca证书,一般需要交费。

回到目录

  1、原理

用户登录后向服务器提供用户认证信息(如账户和密码),服务器认证完后给客户端返回一个PID令牌,用户再次获取信息时,

带上此令牌,如果令牌正取,则返回数据。对于获取Token信息后,访问用户相关接口,客户端请求的url需要带上如下参数:

① 时间戳:timestamp

② PID令牌:PID(在这我们给定义为PID)

然后将所有用户请求的参数(包括timestamp,pid),然后更具MD5加密(可以加点盐),生成动态的url。

然后登陆后每次调用用户信息时,带上timestamp,pid参数。

加上时间戳和pid后的URL:http://127.0.0.1:8888/index?pid=d073dae99f70b0cda2fa1ef8d25c527f|1475117419.5424652|0

就变成一个动态的而且相对的具有高安全的,保证数据安全的访问。

回到目录

  2、具体实现

1. api请求客户端想服务器端一次发送用用户认证信息(用户名和密码),服务器端请求到改请求后,验证用户信息是否正确。
  如果正确:则返回一个唯一不重复的字符串,然后在Redis(任意缓存服务器)中维护这个用户信息关系,以便其他api对pid的校验。
  如果错误:则返回错误码。

2.服务器设计一个url请求拦截规则

①判断是否包含timestamp,pid参数,如果不含有返回错误码。

②根据用户请求的url参数,服务器端按照同样的规则生成动态的URL,对比请求的动态url与服务端生成的是否相等,相等则放行允许访问。

③判断服务器接到请求的时间和参数中的时间戳是否相差很长一段时间(时间自定义如十秒),如果超过则说明该url已经过期。

④记录下每次请求的动态URL,规定一个动态的URL只能访问一次,检测每次请求的url是否请求过,去过存在就返回错误代码(处理url被拦截并且在十秒内请求的访问)。

⑤此url拦截只需对获取身份认证的url放行(如登陆url),剩余所有的url都需拦截。

3.定期处理保存下来的动态请求URL

回到目录

代码实现

服务端规定的规则

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import tornado.ioloop

import tornado.web

import hashlib

import time

access_record = [] # 创建第一次登录过URL列表

PID_LIST = [ # pid列表

'qwe'``,

'ioui'``,

'234s'``,

]

class MainHandler(tornado.web.RequestHandler):

def get(``self``):

# 获取url中全部数据

pid = self``.get_argument(``'pid'``, None``)

# 获取变量

m5, client_time, i = pid.split(``'|'``) # 获得数据,以“|”分割开

print``(m5, client_time, i)

server_time = time.time() # 服务端的当前时间

# 时间超过10s禁止

if server_time > float``(client_time) + 10``: # 服务端的当前时间大于客户端当前时间加10秒,表示过期不允许访问

self``.write(``'gun'``)

return

# 处理10s内容重复的请求

if pid in access_record: # 如果客户端请求的动态URL在第一次登录过的URL列表中

self``.write(``'gun'``)

return

access_record.append(pid) # 允许通过的url添加到列表中

pid = PID_LIST[``int``(i)] # 获得客户端发来的pid后面携带的数字

ramdom_str = "%s|%s" % (pid, client_time) # 把客户的pid与当前时间戳拼接

h = hashlib.md5() # MD5加密值

h.update(bytes(ramdom_str, encoding``=``'utf-8'``)) # 把客户的pid与当前时间戳拼接一个字符串再尽心md5加密

server_m5 = h.hexdigest() # 服务端生成的动态URL

# print(m5,server_m5)

if m5 =``= server_m5: # 客户生成的与服务端生成的进行对比

self``.write(``"Hello, world"``)

else``:

self``.write(``'gun'``)

application = tornado.web.Application([

(r``"/index"``, MainHandler),

])

if __name__ =``= "__main__"``:

application.listen(``8888``)

tornado.ioloop.IOLoop.instance().start()

客户端按规则生成符合的

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import time

import requests

import hashlib

PID = 'qwe'  # 客户的PID

current_time = time.time() # 当前时间戳

ramdom_str = "%s|%s" % (PID, current_time) # 把pid与当前时间戳拼接成一个字符串

h = hashlib.md5() # md5加密

h.update(bytes(ramdom_str, encoding``=``'utf-8'``)) # 把pid与当前时间戳拼接成一个字符串再进行md5加密

UID = h.hexdigest() # 加密后的字符串

q = "%s|%s|0" % (UID, current_time) # 在把这个字符串后面拼接一个数值 0

url = 'http://127.0.0.1:8888/index?pid=%s' % q # 生成最后生成的动态url

print``(url)

ret = requests.get(url)

print``(ret.text)

测试效果代码

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import requests

ret = requests.get(``'http://127.0.0.1:8888/index?pid=c2539948caa7b7fe0d00fcd9d75b7574|1474341577.4938722|0'``)

print``(ret.text)

这是比较粗超的API认证机制,可以初步了解。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这