登录时验证 BCrypt Hash 密码
Verify BCrypt Hash password when Login
我正在使用 net beans IDE 来创建我的登录表单和 servlet。当密码存储在数据库中时,我使用 BCrypt 哈希方法来保护密码并且成功。但是当我要登录时,它总是说 "Invalid Credentials"
我该如何解决这个问题
这是我的CompanyLoging.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body style="background-color: #666666;">
<%
Cookie[] cookies=request.getCookies();
String email = "", password = "",rememberVal="";
if (cookies != null) {
for (Cookie cookie : cookies) {
if(cookie.getName().equals("cookuser")) {
email = cookie.getValue();
}
if(cookie.getName().equals("cookpass")){
password = cookie.getValue();
}
if(cookie.getName().equals("cookrem")){
rememberVal = cookie.getValue();
}
}
}
%>
<div class="limiter">
<div class="container-login100">
<div class="wrap-login100">
<form class="login100-form validate-form" action="CompanyLogin" method="post">
<span class="login100-form-title p-b-43">
Login to continue
</span>
<div class="wrap-input100 validate-input" data-validate = "Valid email is required: ex@abc.xyz">
<input class="input100" type="text" name="email" >
<span class="focus-input100"></span>
<span class="label-input100">Email</span>
</div>
<div class="wrap-input100 validate-input" data-validate="Password is required">
<input class="input100" type="password" name="pass" autocomplete="off">
<span class="focus-input100"></span>
<span class="label-input100">Password</span>
</div>
<div class="flex-sb-m w-full p-t-3 p-b-32">
<div class="contact100-form-checkbox">
<label>Remember me?</label>
<input type="checkbox" name="remember_me" value="1" <%="1".equals(rememberVal.trim()) %>>
</div>
<div>
<a href="#" class="txt1">
Forgot Password?
</a>
</div>
</div>
<div class="container-login100-form-btn">
<button class="login100-form-btn">
Login
</button>
</div>
<div class="text-center p-t-46 p-b-20">
<span class="login100-form-btn2">
or <a href="CompanyReg.jsp">sign up</a>
</span>
</div>
</form>
<div class="login100-more" style="background-image: url('resources/Company/CompanyLogin/images/bg-01.jpg');">
</div>
</div>
</div>
</div>
</body>
</html>
这是我的CompanyLog.java
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String email = request.getParameter("email");
String password = request.getParameter("pass");
String hashPass = BCrypt.hashpw(password, BCrypt.gensalt(12));
try
{
connection = Connector.ConnectDb();
PreparedStatement pst = connection.prepareStatement("SELECT * FROM Company WHERE Email= '"+email+"' AND Password='"+hashPass+"'");
ResultSet rs = pst.executeQuery();
if (rs.next())
{
if(request.getParameter("remember_me") != null)
{
String remember = request.getParameter("remember_me");
Cookie cemail = new Cookie("cookuser", email.trim());
Cookie cPassword = new Cookie("cookpass", password.trim());
Cookie cRemember = new Cookie("cookrem", remember.trim());
cemail.setMaxAge(60 * 60 * 24 * 15);//15 days
cPassword.setMaxAge(60 * 60 * 24 * 15);
cRemember.setMaxAge(60 * 60 * 24 * 15);
response.addCookie(cemail);
response.addCookie(cPassword);
response.addCookie(cRemember);
}
HttpSession httpSession = request.getSession();
httpSession.setAttribute("sessuser", email.trim());
RequestDispatcher requestDispatcher = request.getRequestDispatcher("CompanyDashboard.jsp");
requestDispatcher.forward(request, response);
}
else
{
PrintWriter out=response.getWriter();
out.println("<script type=\"text/javascript\">");
out.println("alert('Invalid Credentials');");
out.println("location='CompanyLogin.jsp';");
out.println("</script>");
}
}
catch (IOException | SQLException | ServletException e)
{
PrintWriter out=response.getWriter();
out.println("Error : " + e);
}
}
这是我的数据库的样子
您没有发布应用程序的注册部分,但我怀疑问题是由您的登录部分中的以下行引起的:
String hashPass = BCrypt.hashpw(password, BCrypt.gensalt(12));
它为 new salt 创建密码哈希。当然,这与在您的注册部分创建的密码哈希不匹配(并存储在您数据库的 Password
字段中),因为即使密码匹配,盐也不同。因此,您不必创建新的盐,而必须使用已经存储在您的数据库中的盐:
String hashPass = BCrypt.hashpw(password, storedSalt);
原则上,salt 可以从存储的 BCrypt-hash 中重建(如果您对此感兴趣,BCrypt
-hash 的格式在 How can bcrypt have built-in salts? and here 中有详细解释)。
但是,有一个更简单的方法(这也是预期的方法):您可以使用 BCrypt#checkpw
-方法:
boolean isAuthenticated = BCrypt.checkpw(candidatePassword, passwordHash);
这里,candidatePassword
是要检查的密码。 passwordHash
是 BCrypt
-哈希(存储在数据库的 Password
- 字段中)。如果密码匹配方法 returns true.
如果您使用这种方法,您必须相应地调整您的数据库访问,例如类似(尚未测试!):
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String email = request.getParameter("email");
String password = request.getParameter("pass");
try {
connection = Connector.ConnectDb();
PreparedStatement pst = connection.prepareStatement("SELECT * FROM Company WHERE Email= '"+email+"'");
ResultSet rs = pst.executeQuery();
while (rs.next()) {
if (BCrypt.checkpw(password, rs.getString("Password"))) {
...
我正在使用 net beans IDE 来创建我的登录表单和 servlet。当密码存储在数据库中时,我使用 BCrypt 哈希方法来保护密码并且成功。但是当我要登录时,它总是说 "Invalid Credentials"
我该如何解决这个问题
这是我的CompanyLoging.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body style="background-color: #666666;">
<%
Cookie[] cookies=request.getCookies();
String email = "", password = "",rememberVal="";
if (cookies != null) {
for (Cookie cookie : cookies) {
if(cookie.getName().equals("cookuser")) {
email = cookie.getValue();
}
if(cookie.getName().equals("cookpass")){
password = cookie.getValue();
}
if(cookie.getName().equals("cookrem")){
rememberVal = cookie.getValue();
}
}
}
%>
<div class="limiter">
<div class="container-login100">
<div class="wrap-login100">
<form class="login100-form validate-form" action="CompanyLogin" method="post">
<span class="login100-form-title p-b-43">
Login to continue
</span>
<div class="wrap-input100 validate-input" data-validate = "Valid email is required: ex@abc.xyz">
<input class="input100" type="text" name="email" >
<span class="focus-input100"></span>
<span class="label-input100">Email</span>
</div>
<div class="wrap-input100 validate-input" data-validate="Password is required">
<input class="input100" type="password" name="pass" autocomplete="off">
<span class="focus-input100"></span>
<span class="label-input100">Password</span>
</div>
<div class="flex-sb-m w-full p-t-3 p-b-32">
<div class="contact100-form-checkbox">
<label>Remember me?</label>
<input type="checkbox" name="remember_me" value="1" <%="1".equals(rememberVal.trim()) %>>
</div>
<div>
<a href="#" class="txt1">
Forgot Password?
</a>
</div>
</div>
<div class="container-login100-form-btn">
<button class="login100-form-btn">
Login
</button>
</div>
<div class="text-center p-t-46 p-b-20">
<span class="login100-form-btn2">
or <a href="CompanyReg.jsp">sign up</a>
</span>
</div>
</form>
<div class="login100-more" style="background-image: url('resources/Company/CompanyLogin/images/bg-01.jpg');">
</div>
</div>
</div>
</div>
</body>
</html>
这是我的CompanyLog.java
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String email = request.getParameter("email");
String password = request.getParameter("pass");
String hashPass = BCrypt.hashpw(password, BCrypt.gensalt(12));
try
{
connection = Connector.ConnectDb();
PreparedStatement pst = connection.prepareStatement("SELECT * FROM Company WHERE Email= '"+email+"' AND Password='"+hashPass+"'");
ResultSet rs = pst.executeQuery();
if (rs.next())
{
if(request.getParameter("remember_me") != null)
{
String remember = request.getParameter("remember_me");
Cookie cemail = new Cookie("cookuser", email.trim());
Cookie cPassword = new Cookie("cookpass", password.trim());
Cookie cRemember = new Cookie("cookrem", remember.trim());
cemail.setMaxAge(60 * 60 * 24 * 15);//15 days
cPassword.setMaxAge(60 * 60 * 24 * 15);
cRemember.setMaxAge(60 * 60 * 24 * 15);
response.addCookie(cemail);
response.addCookie(cPassword);
response.addCookie(cRemember);
}
HttpSession httpSession = request.getSession();
httpSession.setAttribute("sessuser", email.trim());
RequestDispatcher requestDispatcher = request.getRequestDispatcher("CompanyDashboard.jsp");
requestDispatcher.forward(request, response);
}
else
{
PrintWriter out=response.getWriter();
out.println("<script type=\"text/javascript\">");
out.println("alert('Invalid Credentials');");
out.println("location='CompanyLogin.jsp';");
out.println("</script>");
}
}
catch (IOException | SQLException | ServletException e)
{
PrintWriter out=response.getWriter();
out.println("Error : " + e);
}
}
这是我的数据库的样子
您没有发布应用程序的注册部分,但我怀疑问题是由您的登录部分中的以下行引起的:
String hashPass = BCrypt.hashpw(password, BCrypt.gensalt(12));
它为 new salt 创建密码哈希。当然,这与在您的注册部分创建的密码哈希不匹配(并存储在您数据库的 Password
字段中),因为即使密码匹配,盐也不同。因此,您不必创建新的盐,而必须使用已经存储在您的数据库中的盐:
String hashPass = BCrypt.hashpw(password, storedSalt);
原则上,salt 可以从存储的 BCrypt-hash 中重建(如果您对此感兴趣,BCrypt
-hash 的格式在 How can bcrypt have built-in salts? and here 中有详细解释)。
但是,有一个更简单的方法(这也是预期的方法):您可以使用 BCrypt#checkpw
-方法:
boolean isAuthenticated = BCrypt.checkpw(candidatePassword, passwordHash);
这里,candidatePassword
是要检查的密码。 passwordHash
是 BCrypt
-哈希(存储在数据库的 Password
- 字段中)。如果密码匹配方法 returns true.
如果您使用这种方法,您必须相应地调整您的数据库访问,例如类似(尚未测试!):
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String email = request.getParameter("email");
String password = request.getParameter("pass");
try {
connection = Connector.ConnectDb();
PreparedStatement pst = connection.prepareStatement("SELECT * FROM Company WHERE Email= '"+email+"'");
ResultSet rs = pst.executeQuery();
while (rs.next()) {
if (BCrypt.checkpw(password, rs.getString("Password"))) {
...