你的Springboot项目API接口安全吗?一招签名校验让你睡的安心

前言

现在的项目都采用前后端分类的方式开发了,前后端的通讯方式都通过API进行传输。我们知道,如果是管理后台的开发,可以通过shiro或springSecurity进行权限控制,进而保证API接口的安全性,但是,当我们在进行APP或小程序开发的时候,因为需要用户长期登录等问题,再采用shiro等方式进行安全控制就显得不是那么合理的。

可是,如何让我们的API接口变得安全点?不至于当其他人通过抓包的方式拿到你的userId或一些重要参数的时候,对你的数据进行破坏。

那么,API接口的签名校验,将会是你阻挡这些破坏的一堵墙。

下面,让我们开始API签名校验之旅吧。

基础准备

首先,我们先要了解一下普通的API接口是如何访问的(以POSTMAN为例)。


请求/sign/test接口

下面贴一下代码

@RestController
@RequestMapping(value = "/sign")
public class SignController {

    /**
     * 验签测试
     *
     * @return
     */
    @RequestMapping(value = "/test")
    public String test(String name) {
        return name;
    }

}

代码很简洁,无需多言,我想,在没进行签名校验的时候大多数人的代码都是这样的吧。

正式开始

实现效果

1、前端请求方式

我们需要用到的就是,http请求的 header,将token(令牌) 和 timestamp(时间戳)作为参数,一起发送给我们的后端。然后后端对token和timestamp进行校验,校验通过后,才进行的正式访问。


通过postman设置header

2、后端处理方式

@RestController
@RequestMapping(value = "/sign")
public class SignController {

    /**
     * 验签测试
     *
     * @return
     */
    @SignatureValidation
    @RequestMapping(value = "/test")
    public String test(String name) {
        return name;
    }

}

是的,你没有看错,就多了一个注解(自定义的,不用去百度什么意思了)。

 @SignatureValidation

加上后,看效果


请求被签名拦截了

好了,下面去看怎么实现的吧。

实现原理

1、签名规则

(1)、前后端都要统一一个秘钥(secret),这个秘钥是自己定义的,尽可能复杂点。这个可别泄露哦。
(2)、我们需要准备一个当前时间戳 timeStamp,这个很好获取,要注意的是,这个时间戳最好要精确到毫秒。
(3)、我们要确定自己的加密方式。可以使用MD5进行加密,你想加密几次看心情,让他们猜不出来就行了。
(4)、将秘钥和时间戳拼接字符串,然后通过你们约定的加密方式进行加密,得到TOKEN
伪代码(一次加密为例)

token = MD5(secret+ timeStamp);

思考:如果一个人通过抓包的方式拿到了你的接口(header 中的token 和 timestamp),他如何才能进行破解?

第一:他要知道我们的秘钥(secret),只要你设计的够复杂,靠猜是猜不出来的。
第二:他要知道我们的加密方式,我这里用MD5这种常规加密,你们可以换个加密方式,最好是非对称加密。
第三:他要知道我们的加密次数。
第四:他要知道我们的加密规则

如果不是特别重要的接口或者专门要搞你,大部分会退缩的。当然少部分就会通过反编译你的源码去拿到这些数据,或者意外泄露,那你只能自己去加强相关的防护去呗。混淆文件啦,应用加固啦,用胶带粘住嘴啦,方法很多,自己去慢慢研究。

2、Springboot 实现(大家最喜欢的环节,一步步去复制代码到自己项目中去吧)

1、新建一个文件,定义注解接口

文件位置

package com.xxx.aop;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
 * @author tangn
 * 小程序请求认证
 */
@Retention(value = RetentionPolicy.RUNTIME)
public @interface SignatureValidation {
}

其中,一定要注意包名(根据你放这个文件位置),这个下面会用到。

package com.xxx.aop;

2、使用aspect进行切点拦截(不知道其实现原理,去百度吧)

文件位置(忽略那个HttpAspect)

@Aspect
@Component
public class SignatureValidation {
    /**
     * 时间戳请求最小限制(30s)
    * 设置的越小,安全系数越高,但是要注意一定的容错性
     */
    private static final long MAX_REQUEST = 30 * 1000L;
    /**
     * 秘钥
     */
     private static final long SECRET= "前后端约定的秘钥";

    /**
     * 验签切点(完整的找到设置的文件地址)
     */
    @Pointcut("execution(@com.xxx.aop.SignatureValidation * *(..))")
    private void verifyUserKey() {
    }

    /**
     * 开始验签
     */
    @Before("verifyUserKey()")
    public void doBasicProfiling() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String token = request.getHeader("token");
        String timestamp = request.getHeader("timestamp");
        try {
            Boolean check = checkToken(token, timestamp);
            if (!check) {
              // 自定义异常抛出(开发者自行换成自己的即可)
                throw new MyException(ResultEnums.ERROR, "签名验证错误");
            }
        } catch (Throwable throwable) {
            // 自定义异常抛出(开发者自行换成自己的即可)
            throw new PlbException(ResultEnums.ERROR, "签名验证错误");
        }
    }

    /**
     * 校验token
     *
     * @param token     签名
     * @param timestamp 时间戳
     * @return 校验结果
     */
    private Boolean checkToken(String token, String timestamp) {
        if (StringUtils.isAnyBlank(token, timestamp)) {
            return false;
        }
        long now = System.currentTimeMillis();
        long time = Long.parseLong(timestamp);
        if (now - time > MAX_REQUEST) {
            log.error("时间戳已过期[{}][{}][{}]", now, time, (now - time));
            return false;
        }
        String crypt = MD5Utils.getMD5(SECRET+ timestamp);
        return StringUtils.equals(crypt, token);
    }
}

下面说一下用到的工具类:
MD5Utils
每个项目里面都有吧,没有的话网上一搜就行了。
StringUtils
其实很简单,自己写也行,引入第三方的也行,我是引用的apache的,你们也可试试。
pom.xml 文件

   <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

好了,你又没有看错。这样结束了。这样你就有了自己的签名校验工具类,快拿到你的项目中试试去吧。
然后你以后的API接口,只需要加上这个注解就能进行签名验证了。

 @SignatureValidation

总结

很多时候,我们在开发中都只关心业务,对安全性的问题很可能就忽略了,其实我们只需要对自己的API接口稍微一处理,有可能就会避免一些安全问题。从而避免一些不必要的损失。好吧,就到这里,安心睡觉去吧。

源码

https://gitee.com/bean1995/signature_verification
在 tangn_init_20200314 分支
多说一句:看到很多给楼主评论的(可以去看评论区的讨论),加签是为了让项目多一层防护,具体还要取决于项目的重要程度,如果涉及到资金、秘钥等项目,可以采用更安全的加密方式,或者前端加强校验。android、ios加壳,h5做混淆等。这篇文章主要还是想将非侵入的通过注解方式引入签名,具体怎么个签法,要根据项目来定呦~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266