1

我正在开发一个独立的应用程序来测试使用 Selenium Webdriver 的网站。该应用程序将使用 JavaFX 或 Swing UI 来允许用户加载测试套件文件并选择要运行的测试以及在哪个浏览器中运行它们。UI 还将捕获测试使用的数据,例如用户名和密码。

我计划使用 JUnitCore 运行选定的测试类,但我需要将数据从 UI 传递到测试类。对于大多数数据,我可以使用 System.setProperty(prop, value) 来做到这一点。但是,我还需要将网站的管理员密码和其他密码传递给测试

将密码传递给测试的最佳方法是什么?

使用 System.setProperty 存储密码时会有哪些安全问题?我是否应该加密数据并将其存储在文件中并让测试读取文件并解密数据?这显然会增加设置每个测试所需的处理量

4

1 回答 1

0
  • 如果运行 UI 的用户知道密码,那么我并没有真正看到您的安全问题。你在为谁辩护?
  • 如果运行 UI 的用户不知道密码(并且密码应该存储在测试用例本身中),那么你就陷入困境 - 加密很好,但你必须存储密码以某种方式解密......无尽的循环,没有安全的空间。即使存储是安全的,弱点肯定是传输到浏览器(无论如何都将作为封装在 JSON 中的纯字符串完成)和自动输入到浏览器本身。说真的,如果您不信任运行测试的机器,请不要存储密码。

但是,对于第一种情况(当用户必须在 UI 中输入密码时),为了最大限度地减少威胁的可能性并为了最大的方便,我会这样做:

  1. 创建一个单例PasswordHolder
  2. aPasswordHolder会记住 a 中的密码(由 给他们JPasswordFieldMap<String, char[]>Map<String, Password>其中 key 是某个密码标识符,而 value 是密码本身
  3. 一旦通过getPassword()方法访问密码,其内容将被取消

一个快速的示例实现(为了进一步改进,我希望我不会忘记包含任何重要的东西......但它可能会发生)。我认为它有点不言自明:

public class PasswordHolder {

    private static PasswordHolder instance = null; 
    private final Map<String, Password> map = new HashMap<String, Password>();

    private PasswordHolder() {
        // nothing to do
    }

    public static PasswordHolder getInstance() {
        if (instance == null) {
            instance = new PasswordHolder();
        }
        return instance;
    }

    public void addPassword(String name, char[] pass) {
        if (map.containsKey(name)) {
            // throw some sort of Exception("Duplicate password name, man.")
        }
        map.put(name, new Password(pass));
    }

    public Password getPassword(String name) {
        return map.get(name);
    }

}

作为最方便的事情,我写Password了一个CharSequence所以是有用的sendKeys(CharSequence keys)。不幸的是,sendKeys()使用toString()了,所以无论如何你都必须从密码中创建一个字符串(这被认为是一种不好的做法)。

public class Password implements CharSequence {

    private final char[] pass;
    private final BitSet nulled;

    Password(char[] pass) {
        this.pass = pass;
        nulled = new BitSet(pass.length);
    }

    private void nullify(int start, int end) {
        for (int i = start; i < end; i++) {
            pass[i] = '\0';
        }
        nulled.set(start, end);
    }

    @Override
    public int length() {
        return pass.length;
    }

    @Override
    public char charAt(int index) {
        if (nulled.get(index)) {
            // throw some Exception("That character has already been read!")
        }
        char ret = pass[index];
        pass[index] = '\0';
        nulled.set(index);
        return ret;
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        if (nulled.get(start, end).cardinality() > 0) {
            // throw some Exception("Some of the characters has already been read!")
        }
        Password subPass = new Password(Arrays.copyOfRange(pass, start, end)); 
        nullify(start, end);
        return subPass;
    }

    @Override
    public String toString() {
        if (nulled.cardinality() > 0) {
            // throw some Exception("Some of the characters has already been read!")
        }
        String str = new String(pass);
        nullify(0, pass.length);
        return str;
    }

}
于 2012-05-31T11:58:59.337 回答