前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【阿里最新面试题】能回答这题的肯定能拿高薪哦

【阿里最新面试题】能回答这题的肯定能拿高薪哦

作者头像
用户4919348
发布2022-04-13 16:21:34
2700
发布2022-04-13 16:21:34
举报
文章被收录于专栏:波波烤鸭波波烤鸭

具体问题

  具体的面试题目是如果我们把MySQL数据的账号信息,Redis的账号信息等都写在属性文件中,有信息暴露的风险,要保证账号密码的安全我们可以通过MD5或者3DES等加密方式来处理,那么怎么来实现呢?

解决方案

  其实这个问题的解决思路还是比较清晰,就是在Spring注入DataSource对象或者RedisClient对象之前解密秘钥信息,并且覆盖掉之前的配置信息。

在这里插入图片描述
在这里插入图片描述

然后我们通过案例代码来演示下,加深大家的理解 首先我们在属性文件中配置加密后的信息

代码语言:javascript
复制
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
# 对通过3DES对密码加密
spring.datasource.password=t5Jd2CzFWEw=

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

mybatis.mapper-locations=classpath:mapper/*.xml

  在SpringBoot项目启动的时候在在刷新Spring容器之前执行的,所以我们要做的就是在加载完环境配置信息后,获取到配置的spring.datasource.password=t5Jd2CzFWEw= 这个信息,然后解密并修改覆盖就可以了。

在这里插入图片描述
在这里插入图片描述

  然后在属性文件的逻辑其实是通过发布事件触发对应的监听器来实现的

在这里插入图片描述
在这里插入图片描述

  所以第一个解决方案就是你自定义一个监听器,这个监听器在加载属性文件(ConfigFileApplicationListener)的监听器之后处理,这种方式稍微麻烦点,   还有一种方式就是通过加载属性文件的一个后置处理器来处理,这就以个为例来实现

3DES的工具类

代码语言:javascript
复制
/**
 * 3DES加密算法,主要用于加密用户id,身份证号等敏感信息,防止破解
 */
public class DESedeUtil {

    //秘钥
    public static final String  KEY = "~@#$y1a2n.&@+n@$%*(1)";
    //秘钥长度
    private static final int secretKeyLength = 24;
    //加密算法
    private static final String  ALGORITHM = "DESede";
    //编码
    private static final String CHARSET = "UTF-8";

    /**
     * 转换成十六进制字符串
     * @param key
     * @return
     */
    public static byte[] getHex(String key){
        byte[] secretKeyByte = new byte[24];
        try {
            byte[] hexByte;
            hexByte = new String(DigestUtils.md5Hex(key)).getBytes(CHARSET);
            //秘钥长度固定为24位
            System.arraycopy(hexByte,0,secretKeyByte,0,secretKeyLength);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return secretKeyByte;
    }

    /**
     * 生成密钥,返回加密串
     * @param key 密钥
     * @param encodeStr 将加密的字符串
     * @return
     */
    public static String  encode3DES(String key,String encodeStr){
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(getHex(key), ALGORITHM));
            return Base64.encodeBase64String(cipher.doFinal(encodeStr.getBytes(CHARSET)));
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 生成密钥,解密,并返回字符串
     * @param key 密钥
     * @param decodeStr 需要解密的字符串
     * @return
     */
    public static String decode3DES(String key, String decodeStr){
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(getHex(key),ALGORITHM));
            return new String(cipher.doFinal(new Base64().decode(decodeStr)),CHARSET);
        } catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) {
        String userId = "123456";
        String encode = DESedeUtil.encode3DES(KEY, userId);
        String decode = DESedeUtil.decode3DES(KEY, encode);
        System.out.println("用户id>>>"+userId);
        System.out.println("用户id加密>>>"+encode);
        System.out.println("用户id解密>>>"+decode);
    }

}

声明后置处理器

代码语言:javascript
复制
public class SafetyEncryptProcessor implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        for (PropertySource<?> propertySource : environment.getPropertySources()) {
            System.out.println("propertySource = " + propertySource);
            if(propertySource instanceof OriginTrackedMapPropertySource){
                OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) propertySource;
                for (String propertyName : source.getPropertyNames()) {
                    //System.out.println(propertyName + "=" + source.getProperty(propertyName));
                    if("spring.datasource.password".equals(propertyName)){
                        Map<String,Object> map = new HashMap<>();
                        // 做解密处理
                        String property = (String) source.getProperty(propertyName);
                        String s = DESedeUtil.decode3DES(DESedeUtil.KEY, property);
                        System.out.println("密文:" + property);
                        System.out.println("解密后的:" + s);
                        map.put(propertyName,s);

                        // 注意要添加到前面,覆盖
                        environment.getPropertySources().addFirst(new MapPropertySource(propertyName,map));
                    }
                }
            }
        }
    }
}

然后在META-INF/spring.factories文件中注册

代码语言:javascript
复制
org.springframework.boot.env.EnvironmentPostProcessor=com.bobo.util.SafetyEncryptProcessor

然后启动项目就可以了

在这里插入图片描述
在这里插入图片描述

  到这儿,其实大家就应该清楚了,这个问题考察的其实就SpringBoot的启动原理,如果对于SpringBoot的启动过程很清楚的话,那么对于特定的需求我们要扩展其实都是非常容易的哦

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-03-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 具体问题
  • 解决方案
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档