天天看点

API接口安全机制设计学习笔记

课程概要:

  • API网关接口实现
  • 接口安全的业务需求
  • 基于API网关实现安全机制

1 API网关接口实现

1.1 API网关概念

API网关是一个轻量的 java http 接口组件,可以无缝的将普通的 Serive 方法转换成 http 接口,并从以下几点来达到提高开发效率与保证接口质量的目的。

1.去掉mvc控制器,将http请求直接无缝接入Java 服务接口

2.统一出/入参格式

3.统一异常规范

4.自动检测服务接口规范

1.2 API网关与普通Http接口实现流程对比

普通 Http 接口实现流程

API接口安全机制设计学习笔记

API网关接口实现流程

API接口安全机制设计学习笔记

1.3 网关实现流程与技术

详细流程图如下:

API接口安全机制设计学习笔记

请求参数:

String method; // f方法名称

json parameter; // 业务参数

long timestamp; // 请求时间戳

实现技术:

1.java servlet

2.spring IOC

3.Json 转换工具的使用

2 接口安全的业务需求

2.1 接口安全级别分组

1.白名单组

   无需登录认证,无需鉴权,如网站首页

2.黑名单组

   和用户私密信息(userId)相关的,需进行安全认证的接口,如提交订单,操作与用户ID相关的功能

   通常开放平台,默认是 Autho 2.0 协议标准实现

3.黑白名单组

   根据需求设置认证,展示的结果不一样,如商品详情页,如果有登录,则显示和用户相关的信息如评论、收藏、会员价格等

2.2 基于Token安全机制认证需求

1.登陆鉴权

   Token 可以识别用户登录是否登录,在 PC端开发时,直接使用一个token,然后存放至cookie里面;

2.防止业务参数篡改

   确保请求的业务参数不被修改

3.保护用户敏感信息

   UserId、 密码 , 不使用明文在网络直接传输,使用token 代替

4.防签名伪造

   token签名后,要防止token签名被伪造,否则相当于API直接暴露给不法分子,网站处于裸奔状态

   一是要防止单个用户的伪造,另一个是要防止大规模的伪造

2.3 Token 认证机制整体架构

整体架构分为Token生成与认证两部分:

  1. Token生成指在登陆成功之后生成 Token 和密钥,并其与用户隐私信息、客户端信息一起存储至Token表,同时返回Token 与Secret 至客户端。
  2. Token认证指客户端请求黑名单接口时,认证中心基于Token生成签名
    API接口安全机制设计学习笔记

签名规则:

1.已指定顺序拼接字符串 secret+method+param+token+timestamp+secret

2.使用MD5进行加密,在转化成大写

签名的目的:

1.防篡改

   因为param参数在一开始就被进行MD5签名了,若param被修改的话,这时候生成的签名和客户端的签名值肯定是不一致的

2.防伪造

   Secret 是被放在客户端里面的,如果请求中路由被拦截(除非用HTTPS协议),此时请求可能被伪造,但是拿不到secret 的话,是生成不了正确的签名的

3.防重复使用签名

   基于时间戳实现,允许与服务端10分钟误差

服务端签名验证的具体流程:

API接口安全机制设计学习笔记

3 基于API网关实现安全机制

签名认证与API网关的整体认证流程如下:

API接口安全机制设计学习笔记

主要包括两个流程:

1、Token生成

登录成功后插,生成token与secret 保存至数据库

2、Token 认证相关解决方案:

1.接口如何标识黑白名单?

使用一个是否需要登录的标志的来区分:

@Target({ ElementType.METHOD})
@Retention(RententionPolicy.RUNTIME)
Public @interface APIMapping {
   // String value();
    boolean userLogin = false; // 默认为白名单
}
// 使用
@APIMapping(userLogin = true)
           

2.签名具体验证流程?

private ApiRequest signCheck(ApiRequest request) throws ApiException {
        Token token = tokenService.getToken(request.getAccessToken());
        if (token == null) {
            throw new ApiException("验证失败:指定'Token'不存在");
        }
        if (token.getExpiresTime().before(new Date())) {
            throw new ApiException("验证失败:指定'Token'已失效");
        }
        // 生成签名
        String methodName = request.getMethodName();
        String accessToken = token.getAccessToken();
        String secret = token.getSecret();
        String params = request.getParams();
        String timestamp = request.getTimestamp();
        String sign = Md5Util.MD5(secret + methodName + params + token + timestamp + secret);
        if (!sign.toUpperCase().equals(request.getSign())) {
            throw new ApiException("验证失败:签名非法");
        }

        // 时间验证
        if (Math.abs(Long.valueOf(timestamp) - System.currentTimeMillis()) >  *  * ) {
            throw new ApiException("验证失败:签名失效");
        }
        request.setLogin(true);
        request.setMemberId(token.getMemberId());
        return request;
    }
           

3.用户ID等信息如何传递给业务实现接口?

1) 一般方法

// 将UserId存储在ThreadLocal里面,通过 context 获取

Context.getInstallcell().getUserId();

2) HttpRequest request;

3) 借鉴HttpRequest 封装一个 APIRequest

private String userId; // 用户ID
private String accessToken; // Token
private String sign; // 签名
private String eCode; // 设备码
private String timestamp; // 时间戳
private String clientIp; // 客户端IP
private boolean isLogin; // 是否登录
private String params; // 业务参数
...
           

继续阅读