博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
webapi应用架构详解
阅读量:6696 次
发布时间:2019-06-25

本文共 4761 字,大约阅读时间需要 15 分钟。

webapi适用场景

常见的应用包括以下四类,PC客户端程序,APP程序,网站程序,H5程序。

这些应用需要的数据,服务可由同一个接口服务程序提供,这样,大大提高了产品多平台设计开发的效率,避免了重复的编码。

什么是webapi

webapi一般采用restful风格。以tornado为例,url路由配置如下:

url = [    (r'/test', testfc.testHandler)]

业务逻辑层,返回数据一般为json格式:

class testHandler(RequestHandler):    def get(self):        self.post()    def post(self):        result={}        if True:            result["code"]="200"            result["status"]="true"            result["result"]="success"        else:            result["code"]="300"            result["status"]="false"            result["result"]="fail"        self.write(json_encode(result))        return

webapi访问方式如下:

http://127.0.0.1:9999/test 返回结果:
{"status": "true", "code": "200", "result": "success"}

webapi架构设计

如何确认一个app能够访问webapi?

使用AppID验证app访问webapi的合法性,AppID为服务端给出的一个ID标志。
我们可以为web/app/winform分别分配一个ID,从而可以确定访问的合法性,和访问的渠道。

如何保证app参数的正确性,没有被篡改?

客户端使用AppID对应的AppSecert,对参数进行签名(MD5/SHA等)
服务端使用同样的方式签名,和客户端签名校验。

如何防止webapi url被截获,重新访问?

客户端访问webapi时带上时间戳参数,服务端对时间戳进行校验,如10分钟内的访问才是有效的。

涉及具体用户的操作时,如何验证用户?

可以使用username,psw参数的方式访问webapi。但是这种方式很不安全。
使用授权token是很好的解决办法。在用户登录成功时,服务端生成一个授权码,对应用户信息。
访问时带上token参数,服务端查询token有效性,和token对应的用户信息。

使用示例

签名代码如下:

#coding:utf-8__author__ = 'jy'import sysreload(sys)sys.setdefaultencoding('utf-8')sys.path.append('..')import datetimeimport timeimport mathimport hashlibimport urllibdef md5encode(source):    m2 = hashlib.md5()    m2.update(source)    return m2.hexdigest()def dataSort(data):    dataKeys=data.keys()    dataKeys.sort()    result=""    for key in dataKeys:        result+=key.strip()        result+=data[key].strip()    return result def dataSecret(data):    secret="af4d2c92-4bb7-11e5-8111-00163e001071"    data=secret+data+secret    return data def getSign(postdata):    try:        #升序排列,合并为字符串        dataSign=dataSort(postdata)        #加密钥        dataSign=dataSecret(dataSign)        #md5编码        dataSign=md5encode(dataSign)        return dataSign    except Exception as error:        pass

验证url参数代码如下:

#coding:utf-8__author__ = 'haoy'import sysreload(sys)sys.setdefaultencoding('utf-8')sys.path.append('..')from tornado.escape import json_decode, json_encodeimport datetimeimport timeimport mathfrom utils.sign import *def valiUrldata(data):    result={}    try:        #判断appKey是否合法        appKey=data.get("appKey","")         if appKey!="21ec85ec-30ca-491b-8bfb-c05e479eadc0":            result["code"]="300"            result["status"]="false"            result["result"]="账号不合法"            return result        #appKey对应的secret        appSecret="af4d2c92-4bb7-11e5-8111-00163e001071"        #检验时间        timeStamp=data.get("timeStamp","0")        timeStamp=int(timeStamp)        nowtime=int(round(time.time()))        if abs(timeStamp-nowtime)>600:            result["code"]="300"            result["status"]="false"            result["result"]="请求时间戳不合法"            return result        #校验签名        clientSign=data.get("sign","")        if clientSign=="":            result["code"]="300"            result["status"]="false"            result["result"]="请求参数签名不能为空"            return result        data.pop("sign")        serverSign=getSign(data)        print serverSign        if clientSign!=serverSign:            result["code"]="300"            result["status"]="false"            result["result"]="请求参数签名不合法"            return result        result["code"]="200"        result["status"]="true"        result["result"]="通过验证"        return result    except Exception as error:        result["code"]="300"        result["status"]="false"        result["result"]="异常:"+error.message        return result

登录代码如下:

import uuidimport redisclass testLoginHandler(BaseHandler):    def get(self):        self.post()    def post(self):        #获取url参数        args=self.request.arguments        data={}        for key in args:            data[key]=self.get_argument(key,"")        #验证url参数        valiResult=valiUrldata(data)        if valiResult["code"]=="300":            self.write(json_encode(valiResult).decode("unicode_escape"))            return        username=self.get_argument("username","")        psw=self.get_argument("psw","")        if username=="shijingjing07" and psw=="123456":            token = uuid.uuid1()            redisPool = redis.ConnectionPool(host='127.0.0.1',password='123456', port=6379, db=0)            cache = redis.Redis(connection_pool=redisPool)            cache.setex(token,username,300)            result["code"] = 200            result["status"] = "true"            result["result"] = token        else:            result["code"] = 300            result["status"] = "false"            result["result"] = "account illegal"        self.write(json_encode(result))

返回结果:

{"status": "true", "code": 200, "result": "5720c334-dbcc-11e6-84f1-00163e001071"}
 
 

转载地址:http://kkvoo.baihongyu.com/

你可能感兴趣的文章
Daily Scrum- 12/23
查看>>
Daily Scrum – 1/12
查看>>
pyinstaller---将py文件打包成exe
查看>>
【Prince2科普】Prince2的七大原则(7)
查看>>
KineticJS教程(4)
查看>>
spring 拦截器简介
查看>>
Git指令操作
查看>>
[洛谷P3376]【模板】网络最大流(ISAP)
查看>>
[LeetCode] Reverse Bits 位操作
查看>>
Word 2003 长篇文档排版技巧(二)
查看>>
[转载]情人节送花和巧克力的不同意义
查看>>
令人沮丧的投票项目
查看>>
采用jq链(end方法和andSelf()方法)
查看>>
C# 多线程程序隐患
查看>>
【万里征程——Windows App开发】绘制图形
查看>>
[APUE]进程关系(下)
查看>>
poj 3070 矩阵快速幂
查看>>
Webstorm和 Eclipise 快捷键,慢慢总结下。
查看>>
【必备】史上最全的浏览器 CSS & JS Hack 手册(转)
查看>>
(二)可变分区存储管理方案中的内存分配
查看>>