Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用MySQL验证用户身份的最佳方法(接受其他建议)?_Java_Mysql_Jsp_Servlets - Fatal编程技术网

Java 使用MySQL验证用户身份的最佳方法(接受其他建议)?

Java 使用MySQL验证用户身份的最佳方法(接受其他建议)?,java,mysql,jsp,servlets,Java,Mysql,Jsp,Servlets,我正在创建一个基于web的登录系统,为此我使用MySQL作为后端,使用JSP和Servlet作为功能,还使用一个名为jasypt 1.8的库来加密密码,以便以后将其存储在MySQL上 我的问题是:以下代码(安全相关、最佳实践等)是否有任何错误: 我不知道将用户从数据库中取出,然后将其与提供的密码进行比较是否正确(即,我认为最好的方法是使用用户名和密码从数据库中取出信息,而不仅仅是前者)。不幸的是,我无法做到这一点,因为我无法生成密钥,因为库中没有能够生成密钥的方法(而且我还无法在文档中找到生成密

我正在创建一个基于web的登录系统,为此我使用MySQL作为后端,使用JSP和Servlet作为功能,还使用一个名为jasypt 1.8的库来加密密码,以便以后将其存储在MySQL上

我的问题是:以下代码(安全相关、最佳实践等)是否有任何错误:

我不知道将用户从数据库中取出,然后将其与提供的密码进行比较是否正确(即,我认为最好的方法是使用用户名和密码从数据库中取出信息,而不仅仅是前者)。不幸的是,我无法做到这一点,因为我无法生成密钥,因为库中没有能够生成密钥的方法(而且我还无法在文档中找到生成密钥的算法)

我这样做是因为我使用的库有一个内置的随机salt生成器,它将自己存储在加密后创建的字符串中(如果重要的话,使用sha-256…),并且checkPassword()方法是唯一能够生成与数据库中存储的密钥完全相同的密钥的方法(已通过加密过程)

无论如何,如果你有创建登录系统的经验,或者知道很多安全最佳实践,如果你觉得我的解决方案不合适,我希望你能告诉我你对此类问题的经验


感谢您抽出时间。

Jasypt确实让您能够轻松地进行此类密码检查,因此检查密码的代码非常好

我想说的主要一点是,在这种方法中有两种情况

  • 获取sql连接
  • 在控制台上打印连接消息
  • 获取用户
  • 检查它是否不为空
  • 使用内部StrongPasswordEncryptor检查密码
这意味着所有的东西都是用这种方法硬编码的

为了让情况变得更好,我会:

  • 使用日志记录系统
  • 将连接的配置分离到其他位置(属性文件…)
  • 最终使用一个连接池(这里有一个
  • 不要有enpty catch块,抛出异常,或者至少记录它,这样您就知道发生了什么
  • 此外,如果您想更改密码,您应该将密码加密机制设置在此方法之外
无论如何,只有一些东西使它更模块化

现在在生产系统中,大多数人更喜欢使用这样的框架,这样他们就可以轻松地更改身份验证机制,也可以轻松地配置角色和组


瞧。希望这个答案能让人明白一点。

考虑到用户名在系统中是唯一的,您读取用户信息和比较密码散列的解决方案是可以的,它是广泛使用的解决方案。只要整个处理在服务器端完成,就不涉及安全风险

但是,如果您想在实际应用中使用这样的代码,您不应该每次创建连接,而是考虑使用连接池,例如Apache CuMon DCP,这又简化了开发; 还使用名为jasypt 1.8的库加密密码


你不能加密密码。你应该对密码进行单向散列,然后比较散列。你不能提供任何可以合法解释为让其他人知道用户密码的方法。否则你将失去交易的合法不可抵赖性,这将严重到让你破产。你需要听取法律建议关于这一点,我真的很认真。

回答很好,在阅读本文之前,我从来没有想过要使用连接池,立即实施,而且我肯定要使它更加模块化。这只是我为自己做的一个概念证明,所以我可以得到一些关于需要重做什么的反馈,还有一个问题:什么时候假设我需要将连接的配置分离到一个属性文件中,您指的是为此使用一个新类?或者使用某种文本文件,我将从中读取数据?再次感谢您的反馈。除了上面的建议之外,我建议您在查询中只选择密码字段,因为它是e只有一个您使用。这样您就可以避免传输未使用的数据和较低的带宽使用。@user815922是的,一个文本文件。Jasypt有几个例子。很抱歉,我猜我误解了加密的概念,Jasypt的库实际上是对每个密码进行单向散列(大约有5000次SHA-256方法的迭代)之后,它被存储在MySQL数据库中,然后方法checkPassword()(也来自Jasypt的库)检查存储在已经单向散列的密码中的salt,生成密码,并将其与数据库中的密码进行比较,以检查它们是否相等,请告诉我我是否做错了。
 protected boolean verifyUser(String user, String pass) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {

    StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor();

    Connection conn = null;
    String userName = "****";
    String password = "****";
    String url = "jdbc:mysql://localhost:3306/DB";
    ResultSet rs = null;
    try {
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        conn = DriverManager.getConnection(url, userName, password);
        System.out.println("Database connection established");

        PreparedStatement stmt = null;

        stmt = conn.prepareStatement("SELECT * FROM DB.LOGINS WHERE USER = ?");
        stmt.setString(1, user);
        rs = stmt.executeQuery();
        if(!rs.next()){
            return false;                
        }

        if(passwordEncryptor.checkPassword(pass, rs.getString("Password"))){
            return true;
        }
        conn.close();
    } catch (Exception e) {

    }
    return false;
}