简体   繁体   中英

Using JDBC to implement username and password check for a gui, but

我正在使用JDBC来检查数据库中的用户名和密码,以授予我gui的登录访问权限,但是当我尝试测试JDBC是否正在运行时,如果输入了错误的用户名和密码,则无法阻止访问。

Here is some advice:

Do NOT store passwords in the database. Store an MD5 hash of it, then have your Java code or Mysql function convert the user's password input text to an MD5 hash, and then compare that with what's stored in your person table.

Example using Java to do the hashing:

person table:

+----+------------+----------------------------------+
| id | username   | pwhash                           |
+----+------------+----------------------------------+
|  1 | bob        | 9ae4f6963062ba8c77db69aa1f821310 | 
|  2 | ryan       | 3f6af9632621a8ce7d00aa122e2d1310 | 
+----+------------+----------------------------------+

Java code:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

....

String username = ... // from UI input
String plaintext_password = ... // from UI input

String pwhash_from_passwd = makePwHash(username, plaintext_password);

String pwhash_from_db = ...   // SELECT pwhash FROM person WHERE userName=?

if (pwhash_from_db.equals(pw_hash_from_passwd)) {
    // user is authenticated
} else {
    // invalid username or password
}

...



protected static String makePwHash(String username, String plaintext_password) {
    MessageDigest mdigest=null;
    try {
        mdigest = MessageDigest.getInstance("MD5");
        String dbs = username + plaintext_password;
        byte mdbytes[] = mdigest.digest(dbs.getBytes());
        return toHexString(mdbytes);
    } catch (NoSuchAlgorithmException e) { }
    return null;
}



private static final char[] toHex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

/**
 * convert an array of bytes to an hexadecimal string
 * @return a string (length = 2 * b.length)
 * @param b bytes array to convert to a hexadecimal string
 */
public static String toHexString(byte b[]) {
    int pos = 0;
    char[] c = new char[b.length*2];
    for (int i=0; i< b.length; i++) {
        c[pos++] = toHex[(b[i] >> 4) & 0x0F];
        c[pos++] = toHex[b[i] & 0x0f];
    }
    return new String(c);
}

Your method will return true if you enter a non existing user and an empty password. So in that case it is not blocking access. To avoid this you need to validate that the user exists also.

Here is an example. You might not want to do it exactly like this but you should get the idea.

if (rs.next() && password.equals(rs.getString("password"))) {
    // do something
    return true;
} else {
    //do something
}

Also when you call the checkLogin method from the ActionListener you are not checking the return value so you are not really validating anything. You could do something like this

if (usernamecheck.checkLogin(jtfUsername.getText(), jtfPassword.getText())) {
    // User validated
} else {
    // Not validated
}

当提供密码=“”时我可以看到一个问题,并且在这种情况下将找不到记录,以下代码将返回true

if (orPass.equals(password))  // when password =""

This is not good JDBC code. I hope you aren't planning to use this code in production.

Here are just a few of the many things that are wrong with it:

  • Hard coded driver, URL, and credentials. Should be set up in connection pool, external to the app.
  • Empty catch block.
  • Doesn't close Connection, Statement, or ResultSet.
  • No application should have root access to a database. You should create an application ID and GRANT only those permissions needed to accomplish the task.

A few side observations:

1: The comment below isn't correct, the function doesn't (or shouldn't) launch the application. It should only validate the username and password and return true/false. Launching the application should be in its own function (a function should do one thing).

// launch the application

public static boolean checkLogin(String username, String password)

2: you should use a try/catch/finally block to get a connection, preparedStatement, and resultSet. then close them (checking for null first) in reverse order in the finally block, usually all in the same function.

3: Connection pools (dataSource) should be used and the dataSource for the application should be implemented once for the duration of the running application. Using the pool, the connection should be obtained, used, and closed (returned to the pool) as fast as possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM