首先讲一下使用API网关的原因:

我想很多公司都因API或开放API的安全性感到苦恼吧,大部分公司都会自己的API进行加密处理,或token验证,可这就能防范,其他人抓取接口进行非法操作了吗?答案是肯定的,不能。他人可能不能破解你的加密方式,或token验证方式,但他不管这些,他就是专门搞破坏,进行重放攻击,频繁的发送请求,造成服务器的负荷。还有一些公司的API根本没有做加密验证和token,就相当于裸奔的服务器,任何人只要抓取接口就就可以调用API,这非常危险。这些都是我们要使用API网关,API网关可以防止这些漏洞。

阿里云API网关能干什么:

它基本上能干有关我们遇到所有问题。所有我们很有必要集成阿里云API网关。

OK我们开始进入正题,如何配置API的

我相信看到这篇文章的童鞋,应该都是看过阿里云网关的接入文档的。难点应该是对于签名这块,我会在文章的末尾放出demo,(Java和android版本的 PS:ios我不会))

我将阿里云API接入文档整理了一下,大致分为3个模块

一:配置API

二:管理API

三:调用API

我主要讲的模块是如何调用API,当然其他两个模块我也会简单的描述一下。

一:配置API

1.前端配置

2.后端配置

先画张图来解释一下什么是前端配置什么是后端配置

具体配置细节去看官方文档:https://help.aliyun.com/document_detail/48805.html?spm=5176.doc48777.6.546.490Zm0

二.管理API

如何对已经配置好的API进行管理呢,我一句两句也讲不清楚直接看官方文档吧:https://help.aliyun.com/document_detail/29480.html?spm=5176.doc48805.6.574.P7fymx

三.调用API,这是我今天重点讲的模块

步骤:

1.创建APP

如何创建APP

首先登陆阿里云,找到控制台API网关,点击应用管理,点击右上角创建APP,然后填写APP信息,点击确定。

2.授权

首先,查看创建的APPID

然后找到API对这个APP进行授权,如果API属于自己,直接找到API进行授权,

PS:如果你是第三方需要把,APPID告诉API持有者公司,告知给予授权(一般都会有开发文档的)

3.调用API

调用示例:

官方文档调用示例:https://help.aliyun.com/document_detail/29490.html?spm=5176.doc29480.6.554.7HhxYr

我整理过后的示例:

使用的库:

    //网络请求相关compile 'io.reactivex.rxjava2:rxjava:2.0.7'compile 'io.reactivex.rxjava2:rxandroid:2.0.1'compile 'com.squareup.retrofit2:retrofit:2.1.0'compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'compile 'com.squareup.retrofit2:converter-gson:2.1.0'compile 'com.squareup.okhttp3:okhttp:3.5.0'compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'compile 'com.squareup.okio:okio:1.11.0'compile 'com.umeng.analytics:analytics:latest.integration'//签名相关compile('org.bitbucket.b_c:jose4j:0.4.1')compile('commons-io:commons-io:2.5')compile('org.apache.directory.studio:org.apache.commons.codec:1.8')


以下操作代码都是在OKhttp3拦截器里实现的(还没有使用过OKhttp的童鞋建议去Google或百度了解一下)

      1.填写头部信息
          实现方式是拦截器,拦截请求信息,对其进行设置然后继续请求
         
 long mTimestamp = System.currentTimeMillis();Request request = oldrequest.newBuilder().addHeader("Host", "apis.80ct.com").addHeader("Date", CommonUtil.dateFormat(mTimestamp)).addHeader("User-Agent", "Apache-HttpClient/4.1.2 (java 1.6)").addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")请求体类型,请根据实际请求体内容设置。.addHeader("Accept", "application/json")请求响应体类型,部分 API 可以根据指定的响应类型来返回对应数据格式,建议手动指定此请求头,如果不设置,部分 HTTP 客户端会设置默认值 */*,导致签名错误。.addHeader("X-Ca-Request-Mode", "debug")是否开启 Debug 模式,大小写不敏感,不设置默认关闭,一般 API 调试阶段可以打开此设置。.addHeader("X-Ca-Version", "1")//API版本号,为日期形式:YYYY-MM-DD,本版本对应为2016-07-14.addHeader("X-Ca-Signature-Headers", "X-Ca-Request-Mode,X-Ca-Version,X-Ca-Stage,X-Ca-Key,X-Ca-Timestamp")参与签名的自定义请求头,服务端将根据此配置读取请求头进行签名,此处设置不包含 Content-Type、Accept、Content-MD5、Date 请求头,这些请求头已经包含在了基础的签名结构中,详情参照请求签名说明文档。.addHeader("X-Ca-Stage", "RELEASE")请求 API的Stage,目前支持 TEST、PRE、RELEASE 三个 Stage,大小写不敏感,API 提供者可以选择发布到哪个 Stage,只有发布到指定 Stage 后 API 才可以调用,否则会提示 API 找不到或 Invalid Url。.addHeader("X-Ca-Key", HttpConfig.APPKEY)请求的 AppKey,请到 API 网关控制台生成,只有获得 API 授权后才可以调用,通过云市场等渠道购买的 API 默认已经给APP授过权,阿里云所有云产品共用一套 AppKey 体系,删除 ApppKey 请谨慎,避免影响到其他已经开通服务的云产品。.addHeader("X-Ca-Timestamp", mTimestamp + "").addHeader("X-Ca-Nonce", CommonUtil.getRandom() + "")请求唯一标识,15分钟内 AppKey+API+Nonce 不能重复,与时间戳结合使用才能起到防重放作用。.build();

      2. 首先要对请求进行签名
          
//进行签名String clientSign = SignUtil.getSign(request);Log.e(TAG, "intercept clientSign: " + clientSign);
       SignUtil类
package com.sk.openapicallexample_android.http.sign;import com.sk.openapicallexample_android.http.config.HttpConfig;import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;import okhttp3.Headers;
import okhttp3.Request;/*** @Author yemao* @Email yrmao9893@163.com* @Date 2017/5/19* @Des null!*/public class SignUtil {//所有参与签名的header的keyprivate static String CA_PROXY_SIGN_HEADERS = "X-Ca-Signature-Headers";//签名方式private static String SHA256 = "HmacSHA256";//HTTP POSTprivate static final String HTTP_METHOD_POST = "POST";//HTTP PUTprivate static final String HTTP_METHOD_PUT = "PUT";private static String LF = "\n";/**** 将字符串签名* 签名格式 HmacSHA256** @param request okHttp Request* @return 返回签名后的字符串* @throws Exception*/public static String getSign(Request request) {String buildToSign = buildStringToSign(request);String sign = "";try {sign = getSign(buildToSign);} catch (Exception e) {e.printStackTrace();}return sign;}/**** 将字符串签名* 签名格式 HmacSHA256** @param stringToSign 拼接好的字符串* @return 返回签名后的字符串* @throws Exception*/public static String getSign(String stringToSign) throws Exception {Mac hmacSha256 = Mac.getInstance(SHA256);byte[] keyBytes = HttpConfig.SECRET.getBytes("UTF-8");hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, SHA256));return new String(Base64.encodeBase64(hmacSha256.doFinal(stringToSign.getBytes("UTF-8"))), "UTF-8");}/**** 组织等待签名的字符串* 按以下规则排序拼接*  String stringToSign=HTTPMethod + "\n" +Accept + "\n" + Content-MD5 + "\n"Content-Type + "\n" +Date + "\n" +Headers +Url*** @param mMethedType 请求的类型* @param mAccept Accept头的value* @param mContent_Md5  Content-MD5 是指 Body 的 MD5 值,只有当 Body 非 Form 表单时才计算 MD5,* @param mContent_Type Content_Type头的value* @param mDate Date头的value* @param mStringHeaders 参与签名的头* @param mUrl Url 指 Path + Query + Body 中 Form 参数,组织方法:对 Query+Form 参数按照字典对 Key 进行排序后按照如下方法拼接,如果 Query 或 Form 参数为空,则 Url = Path,不需要添加 ?,如果某个参数的 Value 为空只保留 Key 参与签名,等号不需要再加入签名。* @return*/public static String organizationStringToSign(String mMethedType, String mAccept,String mContent_Md5,String mContent_Type,String mDate,String mStringHeaders,String mUrl) {StringBuilder sb = new StringBuilder();sb.append(mMethedType).append(LF);sb.append(mAccept).append(LF);if (mContent_Md5 != null) {sb.append(mContent_Md5);}sb.append(LF);sb.append(mContent_Type).append(LF);sb.append(mDate).append(LF);sb.append(mStringHeaders);sb.append(mUrl);return sb.toString();}public static String buildStringToSign(Request request) {Headers headers = request.headers();String mMethod = request.method();String mAccept = headers.get("Accept");byte[] inputStreamBytes = new byte[]{};String mContent_Md5 = null;try {mContent_Md5 = buildBodyMd5(mMethod, inputStreamBytes);} catch (Exception e) {e.printStackTrace();}String mContent_Type = headers.get("Content-Type");String mDate = headers.get("Date");//HeadersMap<String, String> hedersToSign = buildHeadersToSign(headers);String headersString = buildHeaders(hedersToSign);String mUrl = request.url().url().getPath();if (request.url().query() != null) {mUrl += "?" + request.url().query();}return SignUtil.organizationStringToSign(mMethod, mAccept, mContent_Md5, mContent_Type, mDate, headersString, mUrl);}/*** 组织Headers签名签名字符串** @param headers HTTP请求头* @return Headers签名签名字符串*/private static String buildHeaders(Map<String, String> headers) {StringBuilder sb = new StringBuilder();for (Map.Entry<String, String> e : headers.entrySet()) {if (e.getValue() != null) {sb.append(e.getKey()).append(':').append(e.getValue()).append(LF);}}return sb.toString();}/*** 构建参与签名的HTTP头* <pre>* 传入的Headers必须将默认的ISO-8859-1转换为UTF-8以支持中文* </pre>** @param headers HTTP请求头* @return 所有参与签名计算的HTTP请求头*/private static Map<String, String> buildHeadersToSign(Headers headers) {Map<String, String> headersToSignMap = new TreeMap<>();String headersToSignString = headers.get(CA_PROXY_SIGN_HEADERS);if (headersToSignString != null) {for (String headerKey : headersToSignString.split("\\,")) {headersToSignMap.put(headerKey, headers.get(headerKey));}}return headersToSignMap;}/*** 构建BodyMd5** @param httpMethod       HTTP请求方法* @param inputStreamBytes HTTP请求Body体字节数组* @return Body Md5值* @throws IOException*/private static String buildBodyMd5(String httpMethod, byte[] inputStreamBytes) throws Exception {if (inputStreamBytes == null) {return null;}if (!httpMethod.equalsIgnoreCase(HTTP_METHOD_POST) && !httpMethod.equalsIgnoreCase(HTTP_METHOD_PUT)) {return null;}InputStream inputStream = new ByteArrayInputStream(inputStreamBytes);byte[] bodyBytes = IOUtils.toByteArray(inputStream);if (bodyBytes != null && bodyBytes.length > 0) {return base64AndMD5(bodyBytes).trim();}return null;}/*** 先进行MD5摘要再进行Base64编码获取摘要字符串** @param bytes 待计算字节数组* @return*/public static String base64AndMD5(byte[] bytes) throws Exception {if (bytes == null) {throw new IllegalArgumentException("bytes can not be null");}try {final MessageDigest md = MessageDigest.getInstance("MD5");md.reset();md.update(bytes);final Base64 base64 = new Base64();return new String(base64.encode(md.digest()));} catch (final NoSuchAlgorithmException e) {throw new IllegalArgumentException("unknown algorithm MD5");}}/*** 组织Uri+请求参数的签名字符串* Url 指 Path + Query + Body 中 Form 参数,组织方法:对 Query+Form 参数按照字典对 Key 进行排序后按照如下方法拼接,如果 Query 或 Form 参数为空,则 Url = Path,不需要添加 ?,如果某个参数的 Value 为空只保留 Key 参与签名,等号不需要再加入签名。** @param url       HTTP请求url,不包含Query* @param paramsMap HTTP请求所有参数(Query+Form参数)* @return Uri+请求参数的签名字符串*/private static String buildResource(String url, Map<String, Object> paramsMap) {StringBuilder builder = new StringBuilder();// urlbuilder.append(url);if (paramsMap == null)return builder.toString();// Query+FormTreeMap<String, Object> sortMap = new TreeMap<String, Object>();sortMap.putAll(paramsMap);// 有Query+Form参数if (sortMap.size() > 0) {builder.append('?');builder.append(buildMapToSign(sortMap));}return builder.toString();}/*** 将Map转换为用&及=拼接的字符串*/private static String buildMapToSign(Map<String, Object> paramMap) {StringBuilder builder = new StringBuilder();for (Map.Entry<String, Object> e : paramMap.entrySet()) {if (builder.length() > 0) {builder.append('&');}String key = e.getKey();Object value = e.getValue();if (value != null) {if (value instanceof List) {List list = (List) value;if (list.size() == 0) {builder.append(key);} else {builder.append(key).append("=").append(String.valueOf(list.get(0)));}} else if (value instanceof Object[]) {Object[] objs = (Object[]) value;if (objs.length == 0) {builder.append(key);} else {builder.append(key).append("=").append(String.valueOf(objs[0]));}} else {builder.append(key).append("=").append(String.valueOf(value));}}}return builder.toString();}
}

      3.对签名结果填入头部
request = request.newBuilder().addHeader(X_CA_SIFNATURE_KEY, clientSign).build();
然后贴一个配置类HttpConfig:
public class HttpConfig {//网络请求时间public static int TIME = 30000;//base地址public static String BASE_URL = "http://apis.80ct.com";//http://apitest.1cno.com///这里uuid是表示我们公司API身份验证的标识符你可以忽略public static String UUID = "你自己的uuid";//自己的阿里云APPkeypublic static  String APPKEY="你自己的APPkey";//签名秘钥public static String SECRET = "你自己的app ecret";}

如果安全认证方式为OpenID Connect方式还需要添加两个步骤:
  1.授权接口,获取token
    
    /*** 获取token** @param chain* @return* @throws Exception*/private static String refreshToken(Interceptor.Chain chain) throws IOException {//经过特殊处理的授权接口retrofit2.Call<String> mCall = RetrofitFactory.getInstence().API().authorization1(HttpConfig.UUID);Request request = buildRequestToAddHeads(mCall.request());Response response = chain.proceed(request);//得到响应体ResponseBody responseBody = response.body();//得到缓冲源BufferedSource source = responseBody.source();//请求全部source.request(Long.MAX_VALUE); // Buffer the entire body.Buffer buffer = source.buffer();Charset charset = UTF8;MediaType contentType = responseBody.contentType();if (contentType != null) {charset = contentType.charset(UTF8);}//读取返回数据String bodyString = buffer.clone().readString(charset);//解析返回数据BaseEntity<String> mBaseEntity = null;try {if (bodyString != null) {Gson gson = new Gson();mBaseEntity = gson.fromJson(bodyString, new TypeToken<BaseEntity<String>>() {}.getType());}} catch (Exception e) {e.printStackTrace();}return mBaseEntity == null ? null : mBaseEntity.getData();}

  2.token失效处理,重新获取token
                    Request request = buildRequestToAddHeads(chain.request());Response response = chain.proceed(request);//token失效重新获取tokenif (response.code() == 401) {//当token为空时去获取tokentoken = refreshToken(chain) + "";request = chain.request();request = request.newBuilder().removeHeader(TOKEN_KEY).addHeader(TOKEN_KEY, token.trim().toString()).build();request = buildRequestToAddHeads(request);return chain.proceed(request);

以上就是核心代码了,好了本篇文章的内容就结束了。
github地址:https://git.oschina.net/yrmao/api-connect-call-example.git

阿里云API网关配置详解相关推荐

  1. 浅析阿里云API网关的产品架构和常见应用场景

    自上世纪60年代计算机网络发展开始,API(Application Programming Interface )随之诞生,API即应用程序接口,是实现系统间衔接的桥梁.时至今日,API市场已经形成了 ...

  2. 阿里云Api网关导入Swagger功能简介

    广告位 Api网关通过导入Swagger文件创建和更新Api的功能已经上线了,更多帅气功能会逐步推出 Api网关目标是让您发布应用更加便捷和安全,让您更直观.便捷的管理和调试您的所有Api接口 欢迎试 ...

  3. 阿里云API网关(9)常见问题

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  4. java对接阿里云短信服务详解(验证码,推广短信,通知短信)

    前言 小前提: - java:springboot框架,maven版本管理. - 阿里云:有账号,已经进行实名认证. java对接阿里云短信服务详解(验证码,推广短信,通知短信) 前言 1. 登录阿里 ...

  5. 阿里云API网关使用教程

    API 网关(API Gateway),提供API托管服务,涵盖API发布.管理.运维.售卖的全生命周期管理.辅助用户简单.快速.低成本.低风险的实现微服务聚合.前后端分离.系统集成,向合作伙伴.开发 ...

  6. 阿里云API网关调用示例

    文档 阿里云API网关文档 错误代码表 如何获取错误信息 maven <dependency><groupId>com.aliyun.api.gateway</group ...

  7. 阿里云API网关(11)API的三种安全认证方式

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  8. Linux下配置yum源为阿里云或网易的详解

    一.yum源概述 yum需要一个yum库,也就是yum源.默认情况下,CentOS就有一个yum源.在/etc/yum.repos.d/目录下有一些默认的配置文件(可以将这些文件移到/opt下,或者直 ...

  9. 阿里云API网关(6)用户指南(开放 API )

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

最新文章

  1. ffmpeg + opencv 实现视频播放器(没有声音)
  2. 2019年的人工智能,那些吹过的牛能实现吗?
  3. 自定义控件(一) Activity的构成(PhoneWindow、DecorView)
  4. 在Docker中运行Dubbo应用
  5. vivado中的rtl中电路图无发生成_FPGA零基础学习:数字电路中的组合逻辑
  6. ROS单内网服务器源IP限速\单个下载链接限速
  7. c语言结构体单元测试,C语言结构体单元练习.doc
  8. soapUI中多个TestCase之间传递参数
  9. php文件上传格式限制,如何在PHP中限制文件上传类型的文件大小?
  10. lv55 达成,现金600G
  11. Steps And Uses Of Product Costing
  12. 10个Excel VBA实例教程-刘欢-专题视频课程
  13. 鸟哥私房菜 第十五章、时间服务器: NTP 服务器
  14. CC13X0CC26X0EvaluationBoard
  15. php循环26个英文字母,有趣的真人字母操,形象生动容易学,帮孩子瞬间搞定26个英文字母,效果满分!...
  16. /* 商人过河的问题 假如有三个商人各带一个随从要过河。 只有一条船得需要他们划每次只能坐两个人,条件是任何一岸的随从多于商人时随从就会抢劫商人。 请问这三个商人怎样才能安全过河? */...
  17. 利用Python打造一个语音合成系统,听说你想要御姐音?
  18. 折腾修改SQLCipher静态库的符号表
  19. 锦鲤信小呆翻车!一手好牌打得稀烂背后:靠运气赚来的,终究会凭实力亏掉...
  20. 宝塔的安全防范-服务器防火墙配置经验分享

热门文章

  1. springCloud Api网关搭建
  2. 《95后的指数基金投资课》基础阶段:常见指数与如何投资指数
  3. andrid paly store下载应用路径
  4. 拿到蚂蚁金服 offer, 我不去了
  5. Linux下Moudle工具的介绍与使用
  6. 医院PACS系统源码
  7. 关于netty的中nettyio.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1异常排除
  8. 写论文时遇到的问题及解决办法
  9. VMbox 安装 LInux系统流程
  10. C++汉字转拼音( 转)