【问题标题】:Using JDBC to implement username and password check for a gui, but使用 JDBC 实现 gui 的用户名和密码检查,但是
【发布时间】:2013-09-27 17:06:15
【问题描述】:

我正在使用 JDBC 检查数据库中的用户名和密码以授予对我的 gui 的登录访问权限,但是当我尝试测试 JDBC 是否正常工作时,当输入错误的用户名和密码时,它不会阻止访问..

下面是我的代码,我相信它正确连接了数据库,当我按下登录按钮时,它会输出运行检查登录和用户已验证。

class usernamecheck {

    static final String DATABASE_URL = "jdbc:mysql://localhost:3306/mysql";
    static final String USERNAME = "root";
    static final String PASSWORD = "root";

   // launch the application
    public static boolean checkLogin(String username, String password)
            throws SQLException {
        System.out.print("Running Check Login \n");

        Connection connection = null; // manages connection
        PreparedStatement pt = null; // manages prepared statement

        // connect to database usernames and query database
        try {

            // establish connection to database
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            Connection con = DriverManager.getConnection(DATABASE_URL, "root", "root");

            // query database
            pt = con.prepareStatement("select userName,password from mysql.person where userName=?");

            // process query results
            pt.setString(1, username);
            ResultSet rs = pt.executeQuery();
            String orgUname = "", orPass = "";
            while (rs.next()) {
                orgUname = rs.getString("userName");
                orPass = rs.getString("password");
            } //end while
            if (orPass.equals(password)) {
                //do something
                return true;
            } else {
                //do something
            }
        }//end try
        catch (Exception e) {
        } //end catch  
        return false;
    } //end main
}

图形用户界面代码

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.sql.*;


public class Login extends JFrame {

    private JTextField jtfUsername, jtfPassword;
    private JButton backButton, loginButton;
    private JMenuItem jmiLogin, jmiBack, jmiHelp, jmiAbout;

    Login() {
        //create menu bar
        JMenuBar jmb = new JMenuBar();

        //set menu bar to the applet
        setJMenuBar(jmb);

        //add menu "operation" to menu bar
        JMenu optionsMenu = new JMenu("Options");
        optionsMenu.setMnemonic('O');
        jmb.add(optionsMenu);

        //add menu "help"
        JMenu helpMenu = new JMenu("Help");
        helpMenu.setMnemonic('H');
        helpMenu.add(jmiAbout = new JMenuItem("About", 'A'));
        jmb.add(helpMenu);

        //add menu items with mnemonics to menu "options"
        optionsMenu.add(jmiLogin = new JMenuItem("Login", 'L'));
        optionsMenu.addSeparator();
        optionsMenu.add(jmiBack = new JMenuItem("Back", 'B'));

        //panel p1 to holds text fields
        JPanel p1 = new JPanel(new GridLayout(2, 2));
        p1.add(new JLabel("Username"));
        p1.add(jtfUsername = new JTextField(15));
        p1.add(new JLabel("Password"));
        p1.add(jtfPassword = new JPasswordField(15));

        //panel p2 to holds buttons
        JPanel p2 = new JPanel(new FlowLayout());
        p2.add(backButton = new JButton("Back"));
        p2.add(loginButton = new JButton("Login"));

        //Panel with image??????

        //add panels to frame
        JPanel panel = new JPanel(new GridLayout(2, 1));
        panel.add(p1, BorderLayout.CENTER);
        panel.add(p2, BorderLayout.SOUTH);
        add(panel, BorderLayout.CENTER);
        setTitle("Main Page");


        //listners for exit menuitem and button
        jmiBack.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Welcome welcome = new Welcome();
                welcome.setVisible(true);
                welcome.setSize(500, 500);
                welcome.setLocationRelativeTo(null);
                registerInterface regFace = new registerInterface();
                regFace.setVisible(false);
                Login.this.dispose();
                Login.this.setVisible(false);
            }
        });

        backButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Welcome welcome = new Welcome();
                welcome.setVisible(true);
                welcome.setSize(500, 500);
                welcome.setLocationRelativeTo(null);
                registerInterface regFace = new registerInterface();
                regFace.setVisible(false);
                Login.this.dispose();
                Login.this.setVisible(false);
            }
        });

        //listner for about menuitem
        jmiAbout.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null,
                        "This is the login panel"
                        + "\n Assignment for University",
                        "About", JOptionPane.INFORMATION_MESSAGE);
            }
        });

        //action listeners for Login in button and menu item
        loginButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    usernamecheck.checkLogin(jtfUsername.getText(), jtfPassword.getText()); {
                    System.out.println("User is validated");
               }
                } catch (SQLException se) {
                }
                MainMenu mainmenu = new MainMenu();
                mainmenu.setVisible(true);
                mainmenu.setSize(500, 500);
                mainmenu.setLocationRelativeTo(null);
                registerInterface regFace = new registerInterface();
                regFace.setVisible(false);
                Login.this.dispose();
                Login.this.setVisible(false);
            }
        });

        jmiLogin.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                MainMenu mainmenu = new MainMenu();
                mainmenu.setVisible(true);
                mainmenu.setSize(500, 500);
                mainmenu.setLocationRelativeTo(null);
                registerInterface regFace = new registerInterface();
                regFace.setVisible(false);
                Login.this.dispose();
                Login.this.setVisible(false);
            }
        });
    }

    public static void main(String arg[]) {
        Login frame = new Login();
        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
class usernamecheck {

    static final String DATABASE_URL = "jdbc:mysql://localhost:3306/mysql";
    static final String USERNAME = "root";
    static final String PASSWORD = "root";


   // launch the application
    public static boolean checkLogin(String username, String password)
            throws SQLException {
        System.out.print("Running Check Login \n");

        Connection connection = null; // manages connection
        PreparedStatement pt = null; // manages prepared statement
        Statement stmt = null;
        String query="select userName from person where userName = ? and password = ?";


        // connect to database usernames and query database
        try {

            // establish connection to database
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            Connection con = DriverManager.getConnection(DATABASE_URL, "root", "root");

            // query database
            pt = con.prepareStatement("select userName from person where userName = ? and password = ?");
           
            // process query results
            pt.setString(1, username);
            ResultSet rs = pt.executeQuery(query);
            String orgUname = "", orPass = "";
            while (rs.next()) {
                orgUname = rs.getString("userName");
                orPass = rs.getString("password");
            } //end while
            if (orPass.equals(password) && orgUname.equals(username)) {
                //do something
                return false;
            } else {
                //do something
                return true;
            }
        }//end try
        catch (Exception e) {
        } //end catch  
        return true;
    } //end main
}

【问题讨论】:

  • 吞下异常不是一个好习惯。
  • 这段代码看起来像预期的那样工作(除了你可以使用if(rs.next()而不是while)。可能您的问题是如何向用户展示您的 GUI。
  • @LuiggiMendoza 用我的 gui 更新了代码。
  • 这条线if (orPass.equals(password) && orgUname.equals(username)) {是什么,当它们都相等时你返回false,不应该是其他吗??
  • @SachinThapa 我正在切换它们以查看它们是否会改变任何东西,它们一开始是真实的,但我没有看到任何变化..

标签: java mysql jdbc


【解决方案1】:

这里有一些建议:

不要在数据库中存储密码。存储它的 MD5 哈希,然后让您的 Java 代码或 Mysql 函数将用户的密码输入文本转换为 MD5 哈希,然后将其与存储在您的 person 表中的内容进行比较。

使用 Java 进行散列的示例:

person表:

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

Java 代码:

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);
}

【讨论】:

  • 阿门,兄弟。 +1。值得一提的是盐渍。
  • 谢谢你,我可能会在解决当前问题后实施。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    不是好的 JDBC 代码。我希望您不打算在生产中使用此代码。

    这里只是其中的一些问题:

    • 硬编码驱动程序、URL 和凭据。应设置在应用外部的连接池中。
    • 空的 catch 块。
    • 不关闭连接、语句或结果集。
    • 任何应用程序都不应拥有对数据库的 root 访问权限。您应该创建一个应用程序 ID,并仅授予完成任务所需的权限。

    【讨论】:

      【解决方案4】:

      一些侧面观察:

      1:下面的评论不正确,该功能不(或不应该)启动应用程序。它应该只验证用户名和密码并返回真/假。 启动应用程序应该在它自己的函数中(一个函数应该做一件事)。

      //启动应用程序

      public static boolean checkLogin(String username, String password)

      2:您应该使用 try/catch/finally 块来获取连接、preparedStatement 和 resultSet。然后在 finally 块中以相反的顺序关闭它们(首先检查 null),通常都在同一个函数中。

      3:应使用连接池(dataSource),并且应用程序的数据源应在运行应用程序期间实现一次。使用池,应该尽可能快地获取、使用和关闭(返回池)连接。

      【讨论】:

        【解决方案5】:

        如果您输入不存在的用户和空密码,您的方法将返回 true。因此,在这种情况下,它不会阻止访问。为避免这种情况,您需要验证用户是否也存在。

        这是一个例子。您可能不想完全这样做,但您应该明白这一点。

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

        此外,当您从 ActionListener 调用 checkLogin 方法时,您并未检查返回值,因此您并未真正验证任何内容。你可以这样做

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

        【讨论】:

        • 那么在 if 语句中添加 orgUname.equals(username) 可以解决问题吗?
        • 其实那时有人可以用空的用户名和空的密码登录。不好。
        • 您可以检查数据库查询是否确实返回了某些内容。如果返回0行,则用户不存在。
        • 如果你能给我举个例子,那就太好了,我完全迷路了,我打算休息一晚,明天试着完成它。
        • 为这个例子干杯,这样就可以让密码匹配的用户访问?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-11-29
        • 1970-01-01
        • 2015-02-13
        • 1970-01-01
        • 2016-09-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多