互联网并发与安全系列教程(09) -基于AccessToken方式实现API设计

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 互联网并发与安全系列教程(09) -基于AccessToken方式实现API设计

现在有一个需求:A公司与B公司进行合作,B公司需要调用A公司开放的外网接口获取数据,

如何保证外网开放接口的安全性?

常用解决办法:

  1. 使用令牌方式
  2. 使用加签名方式,防止篡改数据
  3. 使用Https加密传输
  4. 搭建OAuth2.0认证授权
  5. 搭建网关实现黑名单和白名单

下面来讲解使用令牌的方式搭建API开放平台:

基于AccessToken方式实现API设计

原理:为每个合作机构创建对应的appid、app_secret,生成对应的access_token(有效期2小时),在调用外网开放接口的时候,必须传递有效的access_token。简单的说就是我们平时开发中说的“授权”(“授权”这个东西涉及到收费的问题,坑~)。

数据库表设计:

SQL DDML:

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;
字段描述:
字段名 解析
App_Name 表示机构名称
App_ID 应用id
App_Secret 应用密钥 (可更改)
Is_flag 是否可用 (是否对某个机构开放)
access_token 上一次access_token
代码

获取AccessToken:

// 创建获取getAccessToken
@RestController
@RequestMapping(value = "/auth")
public class AuthController extends BaseApiService {
  @Autowired
  private BaseRedisService baseRedisService;
  private long timeToken = 60 * 60 * 2;
  @Autowired
  private AppMapper appMapper;
  // 使用appId+appSecret 生成AccessToke
  @RequestMapping("/getAccessToken")
  public ResponseBase getAccessToken(AppEntity appEntity) {
    AppEntity appResult = appMapper.findApp(appEntity);
    if (appResult == null) {
      return setResultError("没有对应机构的认证信息");
    }
    int isFlag = appResult.getIsFlag();
    if (isFlag == 1) {
      return setResultError("您现在没有权限生成对应的AccessToken");
    }
    // ### 获取新的accessToken 之前删除之前老的accessToken
    // 从redis中删除之前的accessToken
    String accessToken = appResult.getAccessToken();
    baseRedisService.delKey(accessToken);
    // 生成的新的accessToken
    String newAccessToken = newAccessToken(appResult.getAppId());
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("accessToken", newAccessToken);
    return setResultSuccessData(jsonObject);
  }
  private String newAccessToken(String appId) {
    // 使用appid+appsecret 生成对应的AccessToken 保存两个小时
    String accessToken = TokenUtils.getAccessToken();
    // 保证在同一个事物redis 事物中
    // 生成最新的token key为accessToken value 为 appid
    baseRedisService.setString(accessToken, appId, timeToken);
    // 表中保存当前accessToken
    appMapper.updateAccessToken(accessToken, appId);
    return accessToken;
  }
}

编写拦截器拦截请求,验证AccessToken:

//验证AccessToken 是否正确
@Component
public class AccessTokenInterceptor extends BaseApiService implements HandlerInterceptor {
  @Autowired
  private BaseRedisService baseRedisService;
  /**
   * 进入controller层之前拦截请求
   * 
   * @param httpServletRequest
   * @param httpServletResponse
   * @param o
   * @return
   * @throws Exception
   */
  public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o)
      throws Exception {
    System.out.println("---------------------开始进入请求地址拦截----------------------------");
    String accessToken = httpServletRequest.getParameter("accessToken");
    // 判断accessToken是否空
    if (StringUtils.isEmpty(accessToken)) {
      // 参数Token accessToken
      resultError(" this is parameter accessToken null ", httpServletResponse);
      return false;
    }
    String appId = (String) baseRedisService.getString(accessToken);
    if (StringUtils.isEmpty(appId)) {
      // accessToken 已经失效!
      resultError(" this is  accessToken Invalid ", httpServletResponse);
      return false;
    }
    // 正常执行业务逻辑...
    return true;
  }
  public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
      ModelAndView modelAndView) throws Exception {
    System.out.println("--------------处理请求完成后视图渲染之前的处理操作---------------");
  }
  public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
      Object o, Exception e) throws Exception {
    System.out.println("---------------视图渲染之后的操作-------------------------0");
  }
  // 返回错误提示
  public void resultError(String errorMsg, HttpServletResponse httpServletResponse) throws IOException {
    PrintWriter printWriter = httpServletResponse.getWriter();
    printWriter.write(new JSONObject().toJSONString(setResultError(errorMsg)));
  }
}


目录
相关文章
|
3月前
|
人工智能 数据可视化 测试技术
Postman 性能测试教程:快速上手 API 压测
本文介绍API上线后因高频调用导致服务器告警,通过Postman与Apifox进行压力测试排查性能瓶颈。对比两款工具在批量请求、断言验证、可视化报告等方面的优劣,探讨API性能优化策略及行业未来发展方向。
Postman 性能测试教程:快速上手 API 压测
|
3月前
|
消息中间件 JSON Java
高效的并发管理:房间预订 API 的乐观锁和消息队列
本文探讨了在高并发场景下酒店预订系统的挑战,重点分析了乐观锁定和消息队列两种策略。通过代码示例展示了如何使用 Spring Boot 和 RabbitMQ 实现异步流程,以及如何通过乐观锁和 ReentrantLock 避免超卖问题,从而确保系统在多用户同时请求时的稳定性与数据一致性。
101 0
高效的并发管理:房间预订 API 的乐观锁和消息队列
|
5月前
|
JSON 监控 API
在线网络PING接口检测服务器连通状态免费API教程
接口盒子提供免费PING检测API,可测试域名或IP的连通性与响应速度,支持指定地域节点,适用于服务器运维和网络监控。
|
2月前
|
存储 监控 安全
132_API部署:FastAPI与现代安全架构深度解析与LLM服务化最佳实践
在大语言模型(LLM)部署的最后一公里,API接口的设计与安全性直接决定了模型服务的可用性、稳定性与用户信任度。随着2025年LLM应用的爆炸式增长,如何构建高性能、高安全性的REST API成为开发者面临的核心挑战。FastAPI作为Python生态中最受青睐的Web框架之一,凭借其卓越的性能、强大的类型安全支持和完善的文档生成能力,已成为LLM服务化部署的首选方案。
|
3月前
|
人工智能 API 开发者
图文教程:阿里云百炼API-KEY获取方法,亲测全流程
本文详细介绍了如何获取阿里云百炼API-KEY,包含完整流程与截图指引。需先开通百炼平台及大模型服务,再通过控制台创建并复制API-KEY。目前平台提供千万tokens免费额度,适合开发者快速上手使用。
2273 5
|
4月前
|
安全 算法 API
银行卡三要素API实践指南:实现交易安全闭环
在数字化金融时代,身份真实性成为安全防线关键。银行卡三要素核验通过验证卡号、姓名与身份证一致性,提升身份识别准确率,广泛应用于金融、支付等领域。本文详解其技术原理、架构设计与工程实践,助力构建安全合规的身份认证体系。
411 1
|
5月前
|
存储 JSON API
文本存储免费API接口教程
接口盒子提供免费文本存储服务,支持1000条记录,每条最多5000字符,适用于公告、日志、配置等场景,支持修改与读取。
|
2月前
|
缓存 监控 前端开发
顺企网 API 开发实战:搜索 / 详情接口从 0 到 1 落地(附 Elasticsearch 优化 + 错误速查)
企业API开发常陷参数、缓存、错误处理三大坑?本指南拆解顺企网双接口全流程,涵盖搜索优化、签名验证、限流应对,附可复用代码与错误速查表,助你2小时高效搞定开发,提升响应速度与稳定性。
|
2月前
|
JSON 算法 API
Python采集淘宝商品评论API接口及JSON数据返回全程指南
Python采集淘宝商品评论API接口及JSON数据返回全程指南
|
3月前
|
数据可视化 测试技术 API
从接口性能到稳定性:这些API调试工具,让你的开发过程事半功倍
在软件开发中,接口调试与测试对接口性能、稳定性、准确性及团队协作至关重要。随着开发节奏加快,传统方式已难满足需求,专业API工具成为首选。本文介绍了Apifox、Postman、YApi、SoapUI、JMeter、Swagger等主流工具,对比其功能与适用场景,并推荐Apifox作为集成度高、支持中文、可视化强的一体化解决方案,助力提升API开发与测试效率。