这周没写代码,竟然在做这件事!
大家好,我是鱼皮。
这周,我的老弟小阿巴最近找到了份寒假实习,岗位是 Java 后端开发工程师。
入职第一天,他在导师的帮助下熟悉了公司的办公系统、搭好了开发环境。但当他兴致冲冲地准备熟悉业务大显身手的时候,一个同事满面笑意地对他说:小伙子,先别急着做需求,现在有个艰巨的任务要交给你。。。
小阿巴非常开心,心想:天将降大任于是人也!
同事接着说:公司最近在对所有项目的代码质量进行评分,包括代码规范分(代码格式化、缩进、圈复杂度等)和代码安全分(检查你的代码中有没有漏洞)。现在需要你这边帮忙把项目 A 提升到满分。
小阿巴:可是我才来第一天,还不熟悉项目呢?而且为什么这么艰巨的任务要交给我,不是项目 A 的负责人来做呢?
同事:没关系的,我们有现成的代码分析工具,会自动扫描出漏洞并且给你修改建议,你就按他说的做就好了。你来的时候项目 A 的负责人刚刚离职,这不巧了么这不是?
听到这,小阿巴有种不好的预感:扫描出漏洞?离职?马萨卡。。。
小阿巴打开代码分析工具,扫描了一遍项目 A,果不其然,映入眼帘的是满屏的漏洞。
漏洞名称 | 异常文件 |
---|---|
安全问题 - 硬编码密码 | application.yml |
安全问题 - SQL 注入 | userMapper.xml |
安全问题 - XSS | Test.java |
小阿巴大惊:好家伙,原来是前人挖坑我来填!
那还能怎么办呢?一个个修复呗!毕竟办法总比 bug 多。
其中有一条漏洞让小阿巴犯难了:禁止将密码直接填写到项目的配置文件中。
配置文件如图:
小阿巴心想:奇怪了,我之前做 Spring Boot 项目一直都是这么写的,从来没有人告诉我这样做是错的呀 ?!再说了,密码不写到配置文件里,写到哪里呢?
于是他找到了我,我解释到:我们在自己做项目的时候,为了方便 直接把密码写在 application.yml 等配置文件中,是没有任何问题的。但是在团队开发中(尤其是大公司),如果我们把密码直接写在配置文件里并提交到代码仓库中、并且把代码仓库内部公开,那么其他协作者就可以直接看到明文的密码了,这是非常不安全的!
小阿巴:原来是这样,有代码库权限的同学,也未必要给他们查看密码。那应该把密码写在哪里呢?
鱼皮:密码是极度敏感的信息,比较常见的做法是保存到独立的 密码管理平台 或者是 有严格权限控制的配置中心,由运维、开发 owner 等角色来管理。然后我们的项目可以通过 API 调用的方式从这些地方动态获取到密码,再来初始化数据库、Redis 等客户端连接。
大致流程如下:
小阿巴:原来如此,但是 Spring Boot 项目不是只有在启动时才会读取 application.yml 来初始化客户端连接 Bean 么?我怎么控制它从密码管理平台拉取密码后,再去创建 Bean 呢?
鱼皮:阿巴阿巴,你这是被框架束缚住了呀!虽然 Spring Boot 能帮你自动创建 Bean,但别忘了我们是可以自己定义 Bean 的,就像下面这段伪代码:
小阿巴:对哦,把这茬忘了!我这就去改。
鱼皮:且慢!我们做需求时并不是说找到一个方案就一拍脑袋决定了,还要思考一下有没有其他的方法,选择一个相对最优解。
比如你用的是 Spring Cloud 的话,应该接触过上面提到的 “配置中心”,Spring Cloud 在启动时会优先读取 bootstrap.yml 的配置(比如连接配置中心)来从远程加载其他配置(比如密码),可能也不需要你自己去创建 Bean 了。
鱼皮:话说你还能想到其他方法不?
小阿巴:阿巴阿巴。。。
鱼皮:刚刚讲到的这个方法存在的问题是,我们要修改加载 Bean 的方式,也就是说必须要改动代码。对于之前不了解这个项目、或者不熟悉 Spring Boot 运行机制的新人来说,这是一个风险很高的方法,一旦数据库连不上,几乎整个项目就 “瘫了”,估计你就要跑路了。
小阿巴:好嘛,难道还有能不改代码的方法?
鱼皮:当然嘿嘿,咱们来一手移花接木!先问你个问题:咱们的项目从开发到运行,要经历哪几个阶段呢?
小阿巴:这个简单,开发 => 编译构建 => 运行。
鱼皮:不错,那既然 Spring Boot 会自动读取 application.yml 文件,咱们就不把这个文件提交到代码仓库中(.gitignore 忽略),而是在后续阶段把配置文件 “扔进去”,不就可以了么?
比如:
1)构建阶段:在使用流水线构建项目时,把配置文件从远程配置中心拉取下来,放到项目目录下,一起打到 jar 包里。
2)运行阶段:启动项目时,通过 shell 脚本把配置文件从远程拉取下来,放到项目目录下,在运行 jar 包时指定读取该配置文件。
鱼皮:上述方案的具体实现也非常简单。Spring Boot 其实不仅能读取 resources 目录下的 application.yml 配置文件,还能在打完 jar 包后,找到和 jar 包同目录的配置文件,基于它来运行!
下面是 Spring Boot 加载配置文件的优先级(先读取上面的):
jar 包目录配置文件:config/application.yml 和 application.yml 项目类路径目录的配置文件:如 config/application.yml 和 application.yml 项目代码目录中的配置文件:如 resouces/application.yml
其实方法还有很多,选择你认为最合适的一种吧~
小阿巴:学到了,我觉得还是不改代码的方式更稳一些,这就去做。
几天后。。。
小阿巴:我成功地把代码质量分提高到了 100%,谢谢鱼皮,之前完全没考虑过要做这种工作哈哈。
鱼皮:那导师又给你分配了什么工作呀?
小阿巴:他给我 点了个赞 ,让我再去提升另一个项目的代码质量分。。
欢迎学编程的朋友们加入我的 编程知识星球 ,我会 1 对 1 解决你的问题,并且直播带大家开发完整项目(第三期项目进行中)。可以加微信 yupi1085,备注【加入星球】和自己的情况领取优惠加入星球,不备注不通过,非诚勿扰谢谢。
往期推荐