# 设计开放接口api

# App key和App Secret

App key简称API接口验证序号,是用于验证API接入合法性的。接入哪个网站的API接口,就需要这个网站允许才能够接入,如果简单比喻的话:可以理解成是登陆网站的用户名。 App Secret简称API接口密钥,是跟App Key配套使用的,可以简单理解成是密码。App Key 和 App Secret 配合在一起,通过其他网站的协议要求,就可以接入API接口调用或使用API提供的各种功能和数据。 比如淘宝联盟的API接口,就是淘宝客网站开发的必要接入,淘客程序通过API接口直接对淘宝联盟的数据库调用近亿商品实时数据。做到了轻松维护,自动更新。

app_id, app_key, app_secret , 对于平台来说, 需要给你的 你的开发者账号分配对应的权限:

  1. app_id 是用来标记 你的开发者账号的, 是你的用户id, 这个id 在数据库添加检索, 方便快速查找

2 app_key 和 app_secret 是一对出现的账号, 同一个 app_id 可以对应多个 app_key+app_secret, 这样 平台就可以分配你不一样的权限, 比如 app_key1 + app_secect1 只有只读权限 但是 app_key2+app_secret2 有读写权限.. 这样你就可以把对应的权限 放给不同的开发者. 其中权限的配置都是直接跟app_key 做关联的, app_key 也需要添加数据库检索, 方便快速查找

3 至于为什么 要有app_key + app_secret 这种成对出现的机制呢, 因为 要加密, 通常 在首次验证(类似登录场景) , 你需要用 app_key(标记要申请的权限有哪些) + app_secret(密码, 表示你真的拥有这个权限) 来申请一个token, 就是我们经常用到的 access_token, 之后的数据请求, 就直接提供access_token 就可以验证权限了.

第一点:appid(商户号 不可重置)与app_secret(密钥 可以重置)区别

    如:QQ账号 密码,QQ账号是不变的,QQ密码可以改变的。

第二点:为什么获取accesToken的时候需要appid+app_secret才能获取:

    防止黑客知道你的appid+app_secret模拟请求,如果一旦泄漏的话,直接重置app_secret密钥。

搭建流程需要的接口:

提供申请接口,获取appid和app_secret 提供一个使用appid+app_secret获取accesToken (根据appid和app_secret生成一个2小时临时token放入redis) 提供验证accesToken接口 (商户拿token调用接口信息,根据需求验证token也可放到zuul网关进行统一拦截判断)

AppID:应用的唯一标识AppKey:公匙(相当于账号)AppSecret:私匙(相当于密码)

token:令牌(过期失效)

生成App key和App Secret

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.UUID;
 
/**
 * @author mazhq
 * @Title: AppUtils
 * @Description: 随机产生唯一的app_key和app_secret
 * @date 2019/8/27 16:12
 */
public class AppUtils {
    //生成 app_secret 密钥
    private final static String SERVER_NAME = "mazhq_abc123";
    private final static String[] chars = new String[]{"a", "b", "c", "d", "e", "f",
            "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
            "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
            "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
            "W", "X", "Y", "Z"};
 
    /**
     * @Description: <p>
     * 短8位UUID思想其实借鉴微博短域名的生成方式,但是其重复概率过高,而且每次生成4个,需要随即选取一个。
     * 本算法利用62个可打印字符,通过随机生成32位UUID,由于UUID都为十六进制,所以将UUID分成8组,每4个为一组,然后通过模62操作,结果作为索引取出字符,
     * 这样重复率大大降低。
     * 经测试,在生成一千万个数据也没有出现重复,完全满足大部分需求。
     * </p>
     * @author mazhq
     * @date 2019/8/27 16:16
     */
    public static String getAppId() {
        StringBuffer shortBuffer = new StringBuffer();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        for (int i = 0; i < 8; i++) {
            String str = uuid.substring(i * 4, i * 4 + 4);
            int x = Integer.parseInt(str, 16);
            shortBuffer.append(chars[x % 0x3E]);
        }
        return shortBuffer.toString();
 
    }
 
    /**
     * <p>
     * 通过appId和内置关键词生成APP Secret
     * </P>
     * @author mazhq
     * @date 2019/8/27 16:32
     */
    public static String getAppSecret(String appId) {
        try {
            String[] array = new String[]{appId, SERVER_NAME};
            StringBuffer sb = new StringBuffer();
            // 字符串排序
            Arrays.sort(array);
            for (int i = 0; i < array.length; i++) {
                sb.append(array[i]);
            }
            String str = sb.toString();
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();
 
            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";
            for (int i = 0; i < digest.length; i++) {
                shaHex = Integer.toHexString(digest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            return hexstr.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }
 
    public static void main(String[] args) {
        String appId = getAppId();
        String appSecret = getAppSecret(appId);
        System.out.println("appId: "+appId);
        System.out.println("appSecret: "+appSecret);
    }
}

数据库设计

App_Name          表示机构名称
App_ID            应用id
App_Secret        应用密钥  (可更改) 
Is_flag           是否可用 (是否对某个机构开放)
access_token      上一次access_token


CREATE TABLE `m_app` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `app_name` varchar(255) DEFAULT NULL,
  `app_id` varchar(255) DEFAULT NULL,
  `app_secret` varchar(255) DEFAULT NULL,
  `is_flag` varchar(255) DEFAULT NULL,
  `access_token` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

关于评论

评论前请填好“昵称”、“邮箱”这两栏内容,否则不会收到回复,谢谢!