java - 如何加密/解密来自 JPasswordField Java 的密码
问题描述
这是我的问题,我正在开发一个用户可以创建帐户的系统,用户启动一个程序,他点击注册按钮。出现一个新页面,他必须输入他的信息(用户名,密码)。然后他的信息被存储到本地数据库中。问题是当用户创建他的帐户时,他的信息存储在数据库中,但密码是字符串,所以每个人都可以看到密码是什么。我想先将密码散列到我的 java 程序中,然后将其存储到数据库中。但我不明白怎么做,因为我使用“Windows Builder”来做界面,所以用户在 JPasswordField 中输入他的密码。我不知道如何获取用户编写的密码,对其进行哈希处理并将其发送到数据库。
现在我有一个程序可以存储我需要的信息,我有一个程序可以将一个单词散列成不同类型的散列。我还使用了我认为对密码更好的盐方法,它们都不会具有相同的哈希码。
存储信息的代码:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JPasswordField;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.awt.event.ActionEvent;
public class Register extends JFrame {
private JPanel contentPane;
private JTextField txtUsername;
private JPasswordField pwdPassword;
private JPasswordField pwdConfpassword;
private JButton btnSubmit;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Register frame = new Register();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Register() {
super("Register");
conn = DatabaseConnection.connection();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JLabel lblUsername = new JLabel("Username");
lblUsername.setBounds(96, 68, 71, 14);
contentPane.add(lblUsername);
JLabel lblPassword = new JLabel("Password");
lblPassword.setBounds(96, 93, 80, 14);
contentPane.add(lblPassword);
JLabel lblconfPassword = new JLabel("Confirm password");
lblconfPassword.setBounds(97, 122, 91, 14);
contentPane.add(lblconfPassword);
txtUsername = new JTextField();
txtUsername.setBounds(204, 65, 86, 20);
contentPane.add(txtUsername);
txtUsername.setColumns(10);
pwdPassword = new JPasswordField();
pwdPassword.setBounds(201, 90, 89, 20);
contentPane.add(pwdPassword);
pwdConfpassword = new JPasswordField();
pwdConfpassword.setBounds(211, 119, 79, 20);
contentPane.add(pwdConfpassword);
btnSubmit = new JButton("Submit");
btnSubmit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
stmt = conn.createStatement();
String RegUsername = txtUsername.getText();
String RegPassword = pwdPassword.getText();
String sql = "INSERT INTO account(Username, Password) VALUES('"+RegUsername+"', '"+RegPassword+"')";
stmt.executeUpdate(sql);
JOptionPane.showMessageDialog(null,"Account created");
}catch(Exception e1) {
JOptionPane.showMessageDialog(null,e1);
}
}
});
btnSubmit.setBounds(78, 202, 89, 23);
contentPane.add(btnSubmit);
}
哈希密码的代码:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class hash {
public static void main(String[] args) throws Exception {
String Password = "Maria";
String algorithm = "MD5";
byte[] salt = createSalt();
System.out.println("test : " +generateHash(Password, algorithm, salt));
}
private static String generateHash(String Password, String algorithm, byte[] salt) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance(algorithm);
digest.reset();
digest.update(salt);
byte[] hash = digest.digest(Password.getBytes());
return bytesToStringHex(hash);
}
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToStringHex(byte[] bytes) {
char [] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length;j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>>4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static byte[] createSalt() {
byte[] bytes = new byte[20];
SecureRandom random = new SecureRandom();
random.nextBytes(bytes);
return bytes;
}
}
我的目标是用户可以注册并且他的密码存储在数据库中,但是密码是遵循某种类型的哈希的哈希,他也可以使用他的帐户登录,这样密码就可以被解密并与加密的密码进行比较。
真诚的,莫尔卡
解决方案
首先,您无法访问 generateHash,因为它是私有的。您需要将其更改为公开。然后你可以将它挂接到 actionPerformed 方法中。然后只需将结果保存在数据库的密码行中。
其次,永远不要使用 MD5 对密码进行哈希处理。您想使用 bcrypt 或其他安全算法。这是一个如何做到这一点的例子。 https://www.stubbornjava.com/posts/hashing-passwords-in-java-with-bcrypt
最后,你似乎不知道自己在做什么(无意冒犯)。如果适用于现实世界,我强烈建议不要实施任何与安全相关的代码。很容易犯错,而且会造成灾难性的后果。如果它是针对现实世界的,请让更资深的人为您编写它,同时您也可以模仿他们。如果它不是为了现实世界,那么在我给你的例子的帮助下,尽情享受。
推荐阅读
- javascript - 反应全局计数器变量更新脱离上下文
- bash - 如何删除名称附加到其父文件夹名称末尾的子目录
- c++ - C++ 中没有名为“元组”的模板
- javascript - 在 lodash 链接“_.chain()”中返回父对象
- javascript - addEventListener 仅对直接子级
- bootstrap-5 - Bootstraps 5.0 汉堡菜单
- bootstrap-4 - 如果浏览器自动下载内容,则不显示 PDF
- c# - 尝试将 base64String 转换为 IFormFile 会在 C# 中引发 SystemInvalidOperation 异常
- keycloak - 通过 Keycloak 使用远程 IdP 进行第二次登录失败,“用户名或密码无效”
- sql-server - 如何使用 ODBC 连接从 sql server 运行 SSIS 包?