欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-23 21:57:34
...

课程概要:

  • 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()) > 10 * 60 * 1000) {
            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; // 业务参数
...