资讯专栏INFORMATION COLUMN

APP接口开发token安全之请求校验规则

nanfeiyan / 1829人阅读

摘要:移动应用开发过程中请求服务端采用在计算机身份认证中是令牌临时方式请求方式进行,请求方式下直接暴露在请求路径很容易被别人利用进行篡改进行重复提交等,怎样保证移动端安全成为后台开发者所面临的问题,因为涉及敏感行业数据接口开发过程中安全性成为要求

移动应用开发过程中请求服务端采用token(在计算机身份认证中是令牌(临时))方式请求方式进行,get请求方式下token直接暴露在请求路径很容易被别人利用进行篡改进行重复提交等,怎样保证移动端安全成为后台开发者所面临的问题,,因为涉及敏感行业数据APP接口开发过程中安全性成为要求,在网上看了很多资料最后选择采用token+time+nonce+sign方式在过滤器层进行校验,APP进行拼接加密,后端Filter进行解密校验,优点实现简单,能够很好保证请求过程中APP端到服务器端安全性,因此此种校验方式被很多互联网公司所采用。

一、技术实现原理:

token: token为用户登录时获取的临时令牌
time: APP获取到的当前时间,形式为long类型,time时间可进行匹配APP获取时间和服务器时间差如果大于某个时间则失效(如链接超过60秒失效,具体可参考源码),可防止别人截取数据后修改数据内容进行提交
nonce:APP接口通过UUID等形式获取的随机不重复内容,可以讲nonce存放在session或redis中并设置合适的超时时间,然后下次请求时通过nonce取session或redis中是否存在,如果存在则认为重复提交请求,防止被别人篡改后提交数据
sign: 通过token+time+nonce三个参数加密后的密文(sign加密可使用使用ase,md5等加密方式,需要注意md5加密不可逆,实现过程有所区别),sign主要校验token、time、nonce有没有被别人篡改数据

二、技术实现过程:
     1在过滤层实现SecurityFilter类

 public class SecurityFilter extends Filter {

private static String secretKey = ApplicationConfig.secretKey;
private static String ivParameter = ApplicationConfig.ivParameter ;
// 本文采用ase加密 将加密secretKey及ivParameter 的保存在properties文件中,使用公共接口加载,用户可以选择其他加密方式

@Override
protected void doDestroy() {
    // TODO Auto-generated method stub

}

@Override
protected void doFilter(HttpServletRequest request,
        HttpServletResponse response, FilterChain chain) throws Throwable {
    String requestUri = request.getRequestURI();
    //登录接口则直接不适用
    if(requestUri.indexOf("applogin")>-1){
          chain.doFilter(request, response);
    } else {
        MsgEntity msg = new MsgEntity();
        // 获取request的URL,用于判断该请求是否超时
        String time = request.getParameter("time");
        // 获取请求nonce,用于判断是否用户重复提交
        String nonce = request.getParameter("nonce");
        // 获取token码,实际传入token值
        String token = request.getParameter("token");
        // 获取sign,通过time,nonce,token合并进行加密后密文,需要注意加密顺序,平台必须与APP一致
        String sign = request.getParameter("sign");
        // 判断数据是否存在
        if (StringUtils.isEmpty(time) || StringUtils.isEmpty(nonce)
                || StringUtils.isEmpty(token) || StringUtils.isEmpty(sign)) {
            msg.setMsg("登录失败");
            msg.setState(false);
            HttpRequestUtils.writeResponseJsonString(response, msg);
            return;
        }
        //在实际开发过程中传入数据发现存在%号无法进行解密,需要进行URLDecoder.decode进行解码
        if (sign.indexOf("%") > -1) {
            sign = URLDecoder.decode(sign, "UTF-8");
        }
        // 判断请求是否超过60秒,超过60秒则次请求链接失效,返回登录失败,可根据网络情况适当延长或者缩短时间
        if (difference(time) > 60) {
            msg.setMsg("登录失败");
            msg.setState(false);
            HttpRequestUtils.writeResponseJsonString(response, msg);
            return;
        }
        // 判断是否是重复请求,如果请求nonce存在则登录失败,不存在则将nonce存在redis中或session中并设置合适超时时间
        if (JedisUtils.exists(nonce)) {
            msg.setState(false);
            msg.setMsg("登录失败");
            HttpRequestUtils.writeResponseJsonString(response, msg);
            return;
        } else {
            JedisUtils.set(nonce, "0", 70);
        }
         
        // aes 解密,sign和token + time + nonce进行比较判断数据数据是否存在篡改
        String mingwei = "";
        try {
            mingwei = AesUtils.decrypt(sign);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (!mingwei.equals(token + time + nonce)) {
            msg.setState(false);
            msg.setMsg("登录失败");
            HttpRequestUtils.writeResponseJsonString(response, msg);
            return;
        }
         //如果请求全部验证通过则放行
        chain.doFilter(request, response);
    }
三、使用到的工具方法
//主要用于系统时间-APP发送数据时生成日期得到当前差值(秒)
public int difference(String past) {
    long newTimestamp = new Date().getTime();
    return Math.abs((int) (newTimestamp - Long.parseLong(past)) / 1000);
}
   }
    
        /**
 * aes 解密
 * 
 * @param sSrc
 * @return
 * @throws Exception
 */
public static String decrypt(String sSrc) throws Exception {
    try {
        byte[] raw = secretKey.getBytes("ASCII");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES / CBC / PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);// 先用base64解密
        byte[] original = cipher.doFinal(encrypted1);
        String originalString = new String(original, "UTF-8");
        return originalString;
    } catch (Exception ex) {
        return null;
    }
}

以上为过滤实现token校验规则代码,在开发过程中可以参考此代码进行适当修改进行使用

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/11340.html

相关文章

  • APP接口开发token安全请求校验规则

    摘要:移动应用开发过程中请求服务端采用在计算机身份认证中是令牌临时方式请求方式进行,请求方式下直接暴露在请求路径很容易被别人利用进行篡改进行重复提交等,怎样保证移动端安全成为后台开发者所面临的问题,因为涉及敏感行业数据接口开发过程中安全性成为要求 移动应用开发过程中请求服务端采用token(在计算机身份认证中是令牌(临时))方式请求方式进行,get请求方式下token直接暴露在请求路径很容易...

    ZweiZhao 评论0 收藏0
  • 数据接口(API)开发须知

    摘要:由服务端生成在请求任何接口之前,都必须先请求一个获取服务器生成的的接口,获取之后,才请求其他接口是请求时间型号设备号系统类型加密加密头部存储基本参数加密校验参数必须填必须填以下为选填,可有可无,任由开发者自己定义类型设备号版本型号 传统API与RESTful API 传统API 获取用户信息 get /api/user/read 更新用户信息 post /api/user/u...

    piglei 评论0 收藏0
  • 安全开发笔记

    摘要:登录注册安全风险登录注册的风险点主要有四个暴力破解撞库遍历注册用户批量注册。引入了验证码机制同样引入了额外的安全风险,比如短信验证码的短信炸弹风险图形验证码的可绕过可识别等。 概述 很多技术研发不了解安全,也不重视安全,只有在自己的服务器被黑掉、被挂马、被脱裤才想起关注安全,但是这个时候,技术架构已经成型、代码已经在线上稳定运行,再亡羊补牢,改代码、改策略,往往成本巨大、确收效很低。所...

    Cruise_Chan 评论0 收藏0
  • 支付开发填坑记支付宝

    摘要:原文地址支付支付步骤为获取支付宝的配置信息。将得到的数据请求支付宝客户端进行支付。端将拼接好的字符串拿去请求支付宝客户端即可调起支付宝进行支付。向支付宝申请新订单,获取支付。成功请求回来后,就可以向支付宝发出一次支付请求。 支付宝在所有支付方式中最好开发的了,因为文档比较清晰,而且开发起来也比较简单。因此,支付宝的坑是相对较少的。原文地址 APP支付 APP支付步骤为: 获取支付宝的...

    chanjarster 评论0 收藏0
  • 鹅厂干货 | 腾讯游戏APP协议迭代的那些事

    摘要:本文则主要总结了心悦俱乐部的接入层从文本协议到二进制协议迭代过程中的技术方案,包括协议规范安全性等方面的内容。在心悦的文本协议方案中,采用的是对请求数据进行模式的加密。包括明文的协议包头和密文的二进制流。 欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~。 作者:罗广镇 | 腾讯移动开发工程师 App与后台通信通常有采用json等文本协议或者采用二进制协议,本文则主要总结了心...

    luck 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<