代码精进之路
范学雷
Oracle首席软件工程师,Java SE安全组成员,OpenJDK评审成员
立即订阅
6350 人已学习
课程目录
已完结 47 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 你写的每一行代码,都是你的名片
免费
第一模块:代码“规范”篇 (16讲)
01 | 从条件运算符说起,反思什么是好代码
02 | 把错误关在笼子里的五道关卡
03 | 优秀程序员的六个关键特质
04 | 代码规范的价值:复盘苹果公司的GoToFail漏洞
05 | 经验总结:如何给你的代码起好名字?
06 | 代码整理的关键逻辑和最佳案例
07 | 写好注释,真的是小菜一碟吗?
08 | 写好声明的“八项纪律”
09 | 怎么用好Java注解?
10 | 异常处理都有哪些陷阱?
11 | 组织好代码段,让人对它“一见钟情”
12丨组织好代码文件,要有“用户思维”
13 | 接口规范,是协作的合约
14 | 怎么写好用户指南?
15 | 编写规范代码的检查清单
16丨代码“规范”篇用户答疑
第二模块:代码“经济”篇 (14讲)
17 | 为什么需要经济的代码?
18丨思考框架:什么样的代码才是高效的代码?
19 | 怎么避免过度设计?
20 | 简单和直观,是永恒的解决方案
21 | 怎么设计一个简单又直观的接口?
22丨高效率,从超越线程同步开始!
23 | 怎么减少内存使用,减轻内存管理负担?
24 | 黑白灰,理解延迟分配的两面性
25 | 使用有序的代码,调动异步的事件
26 | 有哪些招惹麻烦的性能陷阱?
27 | 怎么编写可持续发展的代码?
28 | 怎么尽量“不写”代码?
29 | 编写经济代码的检查清单
30丨“代码经济篇”答疑汇总
第三模块:代码“安全”篇 (14讲)
31 | 为什么安全的代码这么重要?
32 | 如何评估代码的安全缺陷?
33 | 整数的运算有哪些安全威胁?
34 | 数组和集合,可变量的安全陷阱
35 | 怎么处理敏感信息?
36 | 继承有什么安全缺陷?
37 | 边界,信任的分水岭
38 | 对象序列化的危害有多大?
39 | 怎么控制好代码的权力?
40 | 规范,代码长治久安的基础
41 | 预案,代码的主动风险管理
42 | 纵深,代码安全的深度防御
43 | 编写安全代码的最佳实践清单
44 | “代码安全篇”答疑汇总
加餐 (1讲)
Q&A加餐丨关于代码质量,你关心的那些事儿
结束语 (1讲)
结束语|如何成为一个编程好手?
代码精进之路
登录|注册

36 | 继承有什么安全缺陷?

范学雷 2019-03-27
有时候,为了解决一个问题,我们需要一个解决办法。可是,这个办法本身还会带来更多的问题。新问题的解决带来更新的问题,就这样周而复始,绵延不绝。
比如上一篇文章,我们说到的敏感信息通过异常信息泄露的问题,就是面向对象设计和实现给我们带来的小困扰。再比如前面还有一个案例,说到了共享内存或者缓存技术带来的潜在危害和挑战,这些都是成熟技术发展背后需要做出的小妥协。只是有时候,这些小小的妥协如果没有被安排好和处理好,可能就会带来不成比例的代价。

评审案例

我们一起来看一段节选的 java.io.FilePermission 类的定义。你知道为什么 FilePermission 被定义为 final 类吗?
package java.io;
// <snipped>
/**
* This class represents access to a file or directory. A
* FilePermission consists of a pathname and a set of actions
* valid for that pathname.
* <snipped>
*/
public final class FilePermission
extends Permission implements Serializable {
/**
* Creates a new FilePermission object with the specified actions.
* <i>path</i> is the pathname of a file or directory, and
* <i>actions</i> contains a comma-separated list of the desired
* actions granted on the file or directory. Possible actions are
* "read", "write", "execute", "delete", and "readlink".
* <snipped>
*/
public FilePermission(String path, String actions);
/**
* Returns the "canonical string representation" of the actions.
* That is, this method always returns present actions in the
* following order: read, write, execute, delete, readlink.
* <snipped>
*/
@Override
public String getActions();
/**
* Checks if this FilePermission object "implies" the
* specified permission.
* <snipped>
* @param p the permission to check against.
*
* @return <code>true</code> if the specified permission
* is not <code>null</code> and is implied by this
* object, <code>false</code> otherwise.
*/
@Override
public boolean implies(Permission p);
// <snipped>
}
FilePermission 被声明为 final,也就意味着该类不能被继承,不能被扩展了。我们都知道,在面向对象的设计中,是否具备可扩展性是一个衡量设计优劣的好指标。如果允许扩展的话,那么想要增加一个“link”的操作就会方便很多,只要扩展 FilePermission 类就可以了。 但是对于 FilePermission 这个类,OpenJDK 为什么放弃了可扩展性?

案例分析

如果我们保留 FilePermission 的可扩展性,你来评审一下下面的代码,可以看出这段代码的问题吗?
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《代码精进之路》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(4)

  • 天佑
    嗯,子类会把父类的安全实现改的不安全
    父类扩展新方法时,会给子类添乱,比如子类费劲心机防绕行,父类却悄悄加了个“后门”。。。
    2019-03-27
    2
  • 轻歌赋
    有个问题,案例中hashtable增加了一个entryset后,攻击者如何直接访问对象的entryset呢?
    以web程序为例的话,我想不出用户如何传入可以执行的代码,能过直接让权限检查的调用对象直接执行entryset,也看不出对方如何能够重写我服务端的代码或者继承并且被jvm加载
    老师能给个实际的例子吗

    作者回复: 访问不了对象当然不行。你先找找对象可以访问的场景。 换种场景你可能就熟悉了,比如说浏览器,访问一个页面的用户名密码,怎么不被正在访问的另一个页面窃取?

    2019-03-27
    2
  • LDxy
    代理模式就完全丧失了继承带来的好处

    作者回复: 不使用继承,当然就没有了继承的好处,也没有了继承的坏处。 不同场景的不同选择,离开场景,我们就没有办法识别好与坏。

    2019-08-29
    1
  • hua168
    如果是web程序的话,攻击者是怎么查看我们内部程序?
    如果是API接口的话,这些方法我们不是隐藏起来,不公开,它怎么绕过漏洞攻击?

    作者回复: 没太明白这两个问题。

    无法访问,当然就没问题。 公开接口的问题是,公开了,就可以被使用,使用场景什么样的,我们不知道。 有没有场景,漏洞无法被攻击者利用,当然有的。一个场景没问题,不代表另一个场景就没问题。多用户、多应用、多类库的场景,这些用户之间、应用之间、类库之间,彼此可以不信任,可以参考现代编程语言和操作系统的domain的概念,或者虚拟机、云计算、远程调用等的技术架构。

    2019-03-27
    1
收起评论
4
返回
顶部