使用Base64对URL参数编码

作者: 菜菜___ | 来源:发表于2019-01-20 22:47 被阅读29次

    在近期的项目中,我们需要将手机号作为URL中的参数,类似:http://www.***.com/18200001234这种,但是手机号这样明文显示又不太安全,为防止用户恶意篡改URL的参数,于是就选择用Base64进行编码了。

    Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。
    有时候我们在Url传递的参数包含特殊字符“+”,“/”,“=”时,这些字符作为参数是不能正常接收的,或者我们的参数包含了用户的信息比如手机号、用户id等,我们不想明文显示,这时候都可以使用base64编码。

    编码使用到的工具类Base64Utils。它是Spring-core中提供的,在spring-core.jar中的org.springframework.util包下,它下面常用的工具类还有:StringUtils、ObjectUtils、NumberUtils等。

    首先验证手机号参数的规范性:

        /*校验手机号正则表达式*/
        final static Pattern PHONE_PATTERN = Pattern.compile("^1(3[0-9]|4[57]|5[0-35-9]|6[0-9]|7[0-9]|8[0-9]|9[8-9])\\d{8}$");
        public static boolean verifyPhone(String tephone){
            if (tephone == null || "".equals(tephone)) {
                return false;
            }
            Matcher m = PHONE_PATTERN.matcher(tephone);
            return m.matches();
        }
    

    验证通过后对手机号进行编码:

    定义一个和手机号长度11位相同长度的字节数组,数组里的字符可以是a-z、0-9的任意字符,并且使用异或的规则编码,保证URL解析不发生异常采取“url safe”编码方式

        /**
         * 通过手机号获取手机号对应的编码code
         * @param phone
         * @return
         */
        public static String getLinkByPhone(String phone){
            byte []key = {'A','B','C','D','E','F','G','H', 'I', 'J', 'K'};
            byte []temp = new byte[11];
            if(verifyPhone(phone)){
                for (int i = 0; i < phone.length(); i++) {
                    temp[i] = (byte)(key[i] ^ phone.charAt(i));
                }
            }
            return Base64Utils.encodeToUrlSafeString(temp);
        }
    

    然后根据编码的规则定义解码规则:

    同样,定义一个和手机号长度11位相同长度的字节数组,为防止数组越界抛异常我们需要校验参数的合法性

        /**
         * 通过编码后的字符获取对应的手机号
         * @param code
         * @return
         */
        public static String getPhoneByLink(String code){
            byte []temp = new byte[11];
            try {
                byte []key = {'A','B','C','D','E','F','G','H', 'I', 'J', 'K'};
                if(StringUtils.isNotBlank(code)){
                    byte []phoneByte = Base64Utils.decodeFromUrlSafeString(code);
                    if(phoneByte != null && phoneByte.length > 0 && phoneByte.length <= 11 ){
                        for (int i = 0; i < phoneByte.length; i++) {
                            temp[i] = (byte)(key[i] ^ phoneByte[i]);
                        }
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                return new String(temp);
            }
        }
    

    最后运行结果:

        public static void main(String args[]){
            System.out.println("对手机号编码后:"+getLinkByPhone("18200001234"));
            System.out.println("解码后的手机号:"+getPhoneByLink("cHpxdHV2d3l7eX8="));
        }
    
    base64对手机号编码解码结果

    编码字符串最后的"="是补齐,因为base64编码后的字符长度应该是4的倍数,不足的话会使用“=”号补齐,如果不喜欢这个“=”号我们可以过滤掉,如下:

    public static String getLinkByPhone(String phone){
            byte []key = {'A','B','C','D','E','F','G','H', 'I', 'J', 'K'};
            byte []temp = new byte[11];
            if(verifyPhone(phone)){
                for (int i = 0; i < phone.length(); i++) {
                    temp[i] = (byte)(key[i] ^ phone.charAt(i));
                }
            }
            /*去掉最后补齐的=符号*/
            String result = Base64Utils.encodeToUrlSafeString(temp);
            return result.substring(0,result.length()-1);
        }
    

    总结:

    Base64编码是从二进制到字符的转换过程,并不是真正的加密方式,说Base64编码是加密方法,只是因为经过Base64编码之后,让人一眼看上去不知道什么内容而已。
    关于将手机号转换成加密字符串的方式还有很多,这里只是一种方法的记录。

    原文作者技术博客:https://www.jianshu.com/u/ac4daaeecdfe
    95后前端妹子一枚,爱阅读,爱交友,将工作中遇到的问题记录在这里,希望给每一个看到的你能带来一点帮助。
    欢迎留言交流。

    相关文章

      网友评论

        本文标题:使用Base64对URL参数编码

        本文链接:https://www.haomeiwen.com/subject/rpzedqtx.html