本节书摘来异步社区《java编码指南:编写安全可靠程序的75条建议》一书中的第1章,第1.21节,作者:【美】fred long(弗雷德•朗), dhruv mohindra(德鲁•莫欣达), robert c.seacord(罗伯特 c.西科德), dean f.sutherland(迪恩 f.萨瑟兰), david svoboda(大卫•斯沃博达),更多章节内容可以访问云栖社区“异步社区”公众号查看。
回调提供一种注册方法的手段,在其感兴趣的事件发生时将会被调用(或回调。java在很多地方都使用了回调, 如applet技术、响应servlet的生命周期事件、awt和swing框架中的事件通知(如按钮单击事件),以及异步的读写操作等。甚至在线程的运行机制runnable.run()中,新起一个线程时,自动执行对应的run()方法都使用到了回调技术。
在java中,回调函数通常是使用接口来实现。下面是回调的一般结构:
public interface callback {
void callmethod();
}
class userlookupcallback implements callback {
private int uid;
private string name;
public userlookupcallback(int uid) {
this.uid = uid;
}
public string getname() {
return name;
public void callmethod() {
try (inputstream fis = new fileinputstream("/etc/passwd")) {
// look up uid & assign to name
} catch (ioexception x) {
name = null;
}
final class callbackaction {
private callback callback;
public callbackaction(callback callback) {
this.callback = callback;
public void perform() {
accesscontroller.doprivileged(new privilegedaction() {
public void run() {
callback.callmethod();
return null;
}
});
}<code>`</code>
这段代码可以被客户端安全地使用,如下所示:
class maliciouscallback implements callback {
// code here gets executed with elevated privileges
// client code
public static void main(string[] args) {
callback callback = new maliciouscallback();
callbackaction action = new callbackaction(callback);
action.perform(); // executes malicious code
合规解决方案(回调自己调用doprivileged块)
根据oracle公司的安全编码指南[scg 2010]:
按照惯例,privilegedaction的实例和privilegedexceptionaction的实例可以提供给不可信代码,但不能以调用者提供的动作调用doprivileged。
下面的合规解决方案将doprivileged()的调用从callbackaction代码中移到了它自己的回调里。
final class userlookupcallback implements callback {
// ...
// remaining code is unchanged<code>`</code>
通过回调暴露敏感方法可能导致特权误用和任意代码执行。