在学习《软件构造》这门课之前,我其实就对软件的安全性有一定的理解。因为大一年度项目我们组就是完成的一个软件创新创业项目,所以我对于软件的安全性有一定的了解,但只能说浅尝辄止。在学习完《软件构造》这门课之后,我对于软件的安全性有了更好更深入的理解,从原理到实践,系统地学习了有关软件安全性的知识,接下来我会通过文字+代码的形式复习一下学习到的软件安全性的知识。
在很早的时候,大概是lab2的时候就已经开始有了对于软件安全性的要求,也学习了关于软件安全性的知识。还记得在lab1的时候基本都要参考学长学姐的代码,里面的参数有些是public类型的,有的是private类型的,有同学在上课的时候就询问了老师关于public和private的问题,老师说lab1暂时不提,等到lab2的时候就会有所要求。
在lab2中,我们需要实践学习过的关于ADT的知识,其中十分重要的一环就是对安全性的考虑。其中我们在写spec、AF、RI等信息的时候就需要写出对于安全性的考虑和应对措施。在lab2中最常见的就是对数据的类型要求以及防拷贝等方法。
首先是对数据类型的要求。在lab1中,我写的代码中的参数是这样的
public class FriendshipGraph {
public final static int maxNum = 1000;
public ArrayList<Person> people = new ArrayList<Person>();
public int[][] edge = new int[maxNum][maxNum];
public HashMap<Person, Integer> hm = new HashMap<Person, Integer>();
boolean visited[] = new boolean[maxNum];
}
可以看到这些数据全部都是public类型的,而在lab2中有对于lab1中的P3有重新实现的惭怍,而这一次的参数变成了这样
public class FriendshipGraph {
private final Graph<Person> graph = Graph.empty();
// Abstraction function:
// TODO
// 该图由之前的ConcreEdgesGraph来实现
// 由于ConcreEdgesGraph创造的图是有向带权值的图,所以要求加边时要双向加边并将权值统一
//
// Representation invariant:
// TODO
// graph的映射不能为空
// Safety from rep exposure:
// TODO
// graph为private类型
}
可以看到为了防止ADT中的数据产生泄露的可能性,我将参数全部改为了private类型,并且在很多场合使用了immutable类型
public class ChessGame implements Game {
// TODO fields
private ChessBoard board = new ChessBoard();
private String name1;
private String name2;
private ChessPlayer player1;
private ChessPlayer player2;
private final static String white = "white";
private final static String black = "black";
}
第二个很重要的技术就是防拷贝式编程,比如防止用户使用Object类中的toString()方法直接拷贝ADT中的重要信息,以及防止内部参数被外界直接调用导致内部信息被恶意篡改等。
// TODO toString()
@Override
public String toString() {
return "This is a friednship graph!";
}
例如在很多ADT中我都使用了防拷贝式编程。
@Override
public Set<L> vertices() {
// throw new RuntimeException("not implemented");
Set<L> set = new HashSet<L>();
for (int i = 0; i < vertices.size(); i++) {
set.add(vertices.get(i).getLabel());
}
return set;
}
例如给用户提供了调用内部可变数据的方法,但并不能直接将内部可变数据传输给用户,而是应该传输给用户和内部数据内容相同但是并不是内部的可变数据。