• Java—通过sign签名认证实现安全的开放接口API


    技术公众号:后端技术解忧铺
    关注微信公众号:CodingTechWork,一起学习进步。

    引言

      在开发Java API时,有可能需要一些安全认证来保证API的安全性。下面,我们通过timestamp以及sign签名认证来实现基本的安全的开发接口API

    API接口

    curl {ip}:{port}/demo/test/app -X POST -H "Content-Type:application/json" -d '
    {
    	"appId":"app01",
        "key01": "value01",
        "key02": "value02,
        "key03": "value03",
    	"sign": "77f4d9119d43c41491ab8a7c0530a618d6e0823560eb6dd028f62ae56b1ab7bb",
    	"timestamp":165820977
    }'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    timestamp保证唯一性

    通过timestamp校验,保证约定时间内请求的唯一性

    shell生成timestamp

    1. shell中生成秒级timestamp
    echo $(date '+%s')
    
    • 1
    1. shell中生成毫秒级timestamp
    # 通过纳秒除以1000000的方式实现
    echo $[$(date '+%s%N')/1000000]
    
    • 1
    • 2

    java生成timestamp模板

    // 得到秒级
    long currentTimeStamp = System.currentTimeMillis() / 1000;
    
    • 1
    • 2

    sign签名认证

    实现方式

    1. app服务端配置对应appSecret, 例如app123456
    2. 所有请求参数按照字母排序, 配装字符串, 采用key=value并用&链接
    3. 添加签名appSecret, 字符末尾加上appSecret=app123456
    4. 采用SHA-256生产签名
    5. 例:
      appId=app01¶ms=key01=value01;key02=value02;key03=value03&appSecret=app123456

    shell生成sha-256值

    echo -n "appId=app01¶ms=key01=value01;key02=value02;key03=value03&appSecret=app123456" | sha256sum | awk '{print $1}'
    
    • 1

    结果

    77f4d9119d43c41491ab8a7c0530a618d6e0823560eb6dd028f62ae56b1ab7bb
    
    • 1

    java生成sha-256模板

    
    package com.demo.test
    
    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Base64;
    
    import org.apache.commons.lang.StringUtils;
    
    import lombok.extern.slf4j.Slf4j;
    
    @Slf4j
    public class Encrypt {
    
        /**
         * 返回 SHA-256 串
         *
         * @param strText
         * @return
         */
        public static String SHA256(final String strText) {
            return SHA(strText, "SHA-256");
        }
    
        /**
         * 返回 SHA-512 串
         *
         * @param strText
         * @return
         */
        public static String SHA512(final String strText) {
            return SHA(strText, "SHA-512");
        }
    
        public static String MD5(final String strText) {
            return SHA(strText, "MD5");
        }
    
        /**
         * SHA 加密
         *
         * @param strText
         * @return
         */
        private static String SHA(final String strText, final String type) {
            String ret = null;
    
            if (strText != null && strText.length() > 0) {
                try {
                    MessageDigest messageDigest = MessageDigest.getInstance(type);
                    messageDigest.update(strText.getBytes());
                    byte[] buffer = messageDigest.digest();
    
                    StringBuffer sb = new StringBuffer();
                    for (int i = 0; i < buffer.length; i++) {
                        String hex = Integer.toHexString(0xff & buffer[i]);
                        if (hex.length() == 1) {
                            sb.append('0');
                        }
                        sb.append(hex);
                    }
                    ret = sb.toString();
                } catch (NoSuchAlgorithmException e) {
                    log.error("{} encrypt failed.{}", type, e);
                }
            }
            return ret;
        }
    
        /**
         * 手机号脱敏处理
         *
         * @param phone
         * @return
         */
        public static String desensitizedPhone(String phone) {
            if (StringUtils.isNotEmpty(phone)) {
                phone = phone.replaceAll("(\\w{3})\\w*(\\w{4})", "$1****$2");
            }
            return phone;
        }
    
        /**
         * base64加密
         *
         * @param content
         * @return
         */
        public static String base64Encoder(String content) {
            try {
                String base64encodedString = Base64.getEncoder().encodeToString(content.getBytes("utf-8"));
                return base64encodedString;
            } catch (UnsupportedEncodingException e) {
                log.error("base64Encoder failed", e);
            }
            return null;
        }
        /**
         * base64解密
         *
         * @param content
         * @return
         */
        public static String base64Decoder(String content) {
            try {
                // 解码
                byte[] base64decodedBytes = Base64.getDecoder().decode(content);
                return new String(base64decodedBytes, "utf-8");
            } catch (UnsupportedEncodingException e) {
                log.error("base64Decoder failed", e);
            }
            return null;
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
  • 相关阅读:
    Socks5代理与网络安全:保护隐私、绕过限制与爬虫应用
    C语言集合运算
    企业刚开始上云选择什么配置的云服务器比较合适?
    Java-枚举类型
    简单三招,就能将ppt翻译成英文,快来学习
    桃花峪滑雪场租赁系统 JAVA开源项目 毕业设计
    键入网址到网页显示,期间发生了什么?
    Redis总结:缓存雪崩、缓存击穿、缓存穿透与缓存预热、缓存降级
    Jenkins详细配置
    技术分享 oracle中fm的作用
  • 原文地址:https://blog.csdn.net/Andya_net/article/details/126291554