文章目录

  • 前言
  • 想法
  • 需要考虑的点
  • show the code
  • postman
  • 参考文章

前言

  hello,好久没有写博客了。该博客写于2020正月初九,天寒地冻,本博主的手都有点僵硬,最近身体也不适,但是只要有空就得学习。正所谓:梦想在前方,那就风雨兼程吧~

想法

为啥要实现一个对外安全的接口呢?

本人也接过公司的其他项目组的对外接口,在安全这一块做到还可以,那我也要试着进行实现。

需要考虑的点

  1. 数据加密(如果直接传输比如通过 http 协议,那么用户传输的数据可以被任何人获取)
  2. 数据加签(现在很多服务在内网中都需要经过很多服务跳转,所以这里的加签可以防止内网中数据被篡改)
  3. 时间戳机制(可以使用时间戳机制,在每次请求中加入当前的时间,服务器端会拿到当前时间和消息中的时间相减,看看是否在一个固定的时间范围内比如 5 分钟内;这样恶意请求的数据包是无法更改里面时间的,所以 5 分钟后就视为非法请求了)
  4. AppId 机制(在调用的接口中需要提供 appid + 密钥,服务器端会进行相关的验证)
  5. 限流机制(如果此 appid 进行过很多非法操作,或者说专门有一个中黑系统,经过分析之后直接将此 appid 列入黑名单,所有请求直接返回错误码)

show the code

pom.xml

     <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.0.6</version></dependency>

控制器

验签:md5加密,参数连在一起,加上appid=默认dajitui,header添加createTime时间戳在30分钟内

@RestController
public class TestController {/*** md5加密,参数连在一起,加上appid=默认dajitui,header添加createTime时间戳在30分钟内* @param student*/@GetMapping("/rpc/test")public String a(Student student){System.out.println("student:"+student);return "123";}@PostMapping("/rpc/test1")public String a1(@RequestBody Student1 student1){System.out.println("list:"+student1);return "123";}}

拦截器

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebAppConfig implements WebMvcConfigurer {//实现拦截器 要拦截的路径以及不拦截的路径@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册自定义拦截器,添加拦截路径和排除拦截路径registry.addInterceptor(new MyInterceptor()).addPathPatterns("/rpc/**").excludePathPatterns("/loginPage", "/login");}
}
package com.example.demo;import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.example.demo.entity.Student1;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(request.getRequestURI());String sign = request.getHeader("sign");if (valid(sign)) {throw new IllegalAccessException("验签非法");}StringBuilder builder = new StringBuilder();if ("POST".equals(request.getMethod())) {//System.out.println("post参数:" + new String(IoUtil.readBytes(request.getInputStream(), false)));String parameter = new String(IoUtil.readBytes(request.getInputStream(), false));builder.append(parameter);} else {String time = request.getHeader("createTime");if (valid(time)) {throw new IllegalAccessException("时间戳为空");}long second = DateUtil.between(new Date(), DateUtil.parse(time), DateUnit.MINUTE);if (!(second <= 30 && DateUtil.compare(new Date(), DateUtil.parse(time)) > 0)) {throw new IllegalAccessException("非法时间戳");}Map<String, String[]> map = request.getParameterMap();System.out.println(JSON.toJSONString(map));if (map == null || map.size() == 0) {return false;}builder.append("{");map.forEach((k, v) -> {builder.append(k);if (v.length == 1) {builder.append(v[0]);} else {new ArrayList<>(Arrays.asList(v)).forEach(builder::append);}builder.append(",");});builder.delete(builder.length() - 1, builder.length());builder.append("}");}System.out.println(builder.toString() + " " + SecureUtil.md5(builder.toString()));//Todo 这里只是对参数进行md5加密,可以再加上appid的配置,对应的密钥进行加密。if (SecureUtil.md5(builder.toString()).equals(sign)) {return true;}return false;}public static void main(String[] args) {/*Student student = new Student();student.setAge(20);student.setName("123");System.out.println(JSON.toJSONString(student.toString()));*/Student1 student1 = new Student1();student1.setList(Arrays.asList("1", "2"));System.out.println(student1.toString());System.out.println(SecureUtil.md5(student1.toString()));/*StringBuilder builder = new StringBuilder();builder.append("1234567");builder.append("89");builder.delete(builder.length()-1, builder.length());System.out.println(builder);*/}private boolean valid(String value) {return StrUtil.isBlank(value);}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

Todo 这里只是对参数进行md5加密,可以再加上appid的配置,对应的密钥进行加密。

注意点

  1)其中sign是客户端对参数拼接完然后根据一定规则进行加密,appId可以对应一些密钥,特有的,保证签名的唯一。(这个加密还需要后期进行改进哦~~~

  2)要区分post,get去获取值。在post那里还有个坑,就是使用request.getRead(),如果参数是@RequestBody的话,会报错。因为这个方法只能调一次!!!

  3)IoUtil.readBytes(request.getInputStream(), false);这里要带false,不然会关闭request流

  4)参数的拼接,之前我们公司使用TreetSet将对象进行add进去。后面我看了下还是需要使用对象的toString()方法,来统一格式!!!而且获取参数那里要使用对象,这样才能重写toString来规范格式。

示范

@NoArgsConstructor
@Data
public class Student  {private String name;private int age;private User user;public Student(String name) {this.name = name;System.out.println("构造学生类");}@Overridepublic String toString() {boolean hadFirst=false;StringBuilder builder = new StringBuilder();builder.append("{");if (name != null) {builder.append("name").append(name);hadFirst=true;}if (age > 0) {if(hadFirst) {builder.append(",");}builder.append("age").append(age);}if (user != null) {if(hadFirst) {builder.append(",");}builder.append("user").append(user);}builder.append("}");return builder.toString();}}
@Data
public class Student1 {private List<String> list;@Overridepublic String toString() {StringBuilder builder = new StringBuilder();builder.append("{");if (list != null) {builder.append("\"list\":[");list.forEach(e-> builder.append("\"").append(e).append("\"").append(","));}builder.delete(builder.length() - 1, builder.length());builder.append("]}");return builder.toString();}}

postman

get请求

post请求

参考文章

如何设计一个安全的对外接口?

动手实现对外安全的接口(写于天寒地冻的正月初九)相关推荐

  1. 将B/S程序打包成exe,C#对外提供http接口,CefSharp 修改浏览器默认白色背景

    简介 公司有个项目,需要将我们https的B/S程序集成到的http的B/S程序中,还要保持本身功能完整,由于https程序中需要调用电脑的麦克风和摄像头,这就难受了.最后商量决定将https程序制作 ...

  2. java 模块分离部署_GitHub - yangjiu/Mis: 模块接口服务,如何在一个模块内维护其对外暴露的接口(包括打包发布),而不是把接口和接口实现分离到两个不同的模块?...

    MIS 模块接口服务(Module Interface Service) MIS主要解决的问题是如何在一个模块内维护其对外暴露的接口(包括打包发布),而不是把接口和接口实现分离到两个不同的模块. Us ...

  3. zookeeper集群,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的。...

    zookeeper集群,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的.

  4. java8接口写静态方法_Java 8接口更改–静态方法,默认方法

    java8接口写静态方法 Java 8 interface changes include static methods and default methods in interfaces. Prio ...

  5. 追书神器的api接口写的微信小程序

    @这是我基于追书神器的api接口写的微信小程序 这是我小程序的二维码

  6. faiss 向量库使用;指定自定义id;对外serving http接口

    下载:mac或liunx使用 参考:https://blog.csdn.net/weixin_42357472/article/details/109243957 使用参考 https://zhuan ...

  7. 我潜入清华神秘实验室,用脑机接口写了两句诗

    来源:本文经AI新媒体量子位(公众号ID:qbitai)授权转载,转载请联系出处 本文约2190字,建议阅读5分钟. 本文讲述了我被赋予了"超能力"之后发生的故事. 从没想过,我也 ...

  8. Spring开篇介绍-如果没有Spring如何对外暴露一个接口

    引言 目前我在互联网行业已经工作5年以上了,回想起刚毕业时刚刚接触Spring框架,做了一个专利管理系统,后续工作中负责过交易型业务,贷前和贷后业务,支付业务等.现在主要深耕营销活动领域,不管是自己开 ...

  9. 利用工具及api接口写博文

    使用工具写博客 像windows live writer,zoundry blog writer,等,比较好用. 不过要知道对应的设置方式. cnblogs采用的是 Metaweblog API 做为 ...

  10. nginx做负载均衡,解决多机器多gpu卡服务对外暴露一个接口问题

    思路:多个gpu 服务接口-->ngxin做负载均衡-->对外暴露一个. 以一机两卡为例,其中gunicorn部署一卡多进程服务参考这篇文章 一.制作nginx负载均衡镜像 1.制作Doc ...

最新文章

  1. set_origin_pose算子说明
  2. .NET 数据访问中间件 HyperDAL v1.1 FAQ
  3. python编程软件v-Python编程狮
  4. python文件读取 ,json文件的存储
  5. python算法与数据结构-选择排序算法(33)
  6. Maven项目依赖管理工具
  7. python学习day32 黏包 struct模块
  8. npm和angular_如何开发,使用和发布Angular库到NPM
  9. 关于分布式集群的几个问题
  10. java http get 图片_http协议get方法获取图片并保存到本地
  11. Sql Server 的基本增删改查语句
  12. bt 下载工具 deluge 配置 优化 使用
  13. excel 设置隔行变色功能
  14. 积分无法积,用估值后再使用连续函数介值定理_20160430
  15. 谷歌浏览器播放视频只有声音没有画面解决方法
  16. 优秀课程案例:使用Scratch制作坦克大战增强版!
  17. 美通社企业新闻汇总 | 2019.2.26 | 华为企业业务首登MWC发布数字平台;爱茉莉与屈臣氏达成战略合作...
  18. Swig在windows下的使用流程
  19. overleaf 插入图片_Overleaf手册(三)--图片
  20. 【自建NAS】Ubuntu Server 配置 WIFI 连接

热门文章

  1. 阿里巴巴初创时的十八罗汉,离开阿里之后都有什么故事?
  2. C++基础知识(7)
  3. SCI收录的文献类型与认证的文献类型
  4. Android系统权限和root权限
  5. There are 1 missing blocks. The following files may be corrupted:
  6. css 设置鼠标经过的时候鼠标变成手状假装是个链接
  7. PIC单片机提示 No valid installed HI-TECH compiler drivers
  8. 【视频MV】laislabonita美丽的海岛*女歌星Alizee(艾莉婕)
  9. CentOS简单上手——第四篇
  10. 2021软科中国计算机专业排名