让我首先说,我的职业不是开发人员,这只是我出于兴趣和太多空闲时间而学习做的事情。我是一个初学者,我需要把它排除在外,以防我因为问这样一个简单的问题而受到抨击。
我正在尝试制作一款"选择你自己的冒险"网络游戏,加入登录功能进行练习。我使用的是Eclipse Mars,运行在Tomcat 8.0上。我在MySql数据库中创建了一个名为PLAYER的表,其中包含字段id、用户名和密码。到目前为止,我已经创建了以下文件:index.html(其中包含登录表单)、menu.html(成功登录后的登录页)和login.java(一个处理数据库连接和用户身份验证的servlet)。
以下是index.html:的一部分
<form method="post" action="Login">
<div class="form_layout">
<label>User name:</label>
<input type="text" id="uname" style="width:100%"/>
<label>Password:</label>
<input type="password" id="pword" style="width:100%"/>
<input type="submit" id="login_btn" value="LOGIN" />
</div>
</form>
以下是所有Login.java:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.*;
@WebServlet("/Login")
public class Login extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("uname");
String password = request.getParameter("pword");
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost/game"+"?verifyServerCertificate=false"+"&useSSL=true";
String user = "root";
String pass = "password";
String sql = "SELECT username, password FROM player WHERE username = ? AND password = ?";
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
boolean login = false;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, user, pass);
statement = connection.prepareStatement(sql);
statement.setString(1, username);
statement.setString(2, password);
resultSet = statement.executeQuery();
login = resultSet.next();
} catch (Exception e) {
throw new ServletException("Login failed", e);
} finally {
if (resultSet != null) try { resultSet.close(); } catch (SQLException ignore) {}
if (statement != null) try { statement.close(); } catch (SQLException ignore) {}
if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
}
if (login) {
request.getSession().setAttribute("username", username);
response.sendRedirect("menu.html");
} else {
request.setAttribute("message", "Unknown username/password, try again");
request.getRequestDispatcher("index.html").forward(request, response);
}
}
}
每次我尝试登录时,我总是被重定向到index.html,无论我输入的凭据是否正确。我试着改变这个:
else {
request.setAttribute("message", "Unknown username/password, try again");
request.getRequestDispatcher("index.html").forward(request, response);
}
到此:
else {
request.setAttribute("message", "Unknown username/password, try again");
request.getRequestDispatcher("menu.html").forward(request, response);
}
查看重定向是否有效,并发现它绕过if语句,直接转到else。我猜"login"没有返回true,这就是为什么它不会按照我想要的方式重定向。现在看代码,我真的不知道我做错了什么。我在互联网上搜索了答案,但没有找到任何能帮我解决这个问题的方法。
任何形式的帮助都将不胜感激。谢谢
(这不是你问题的直接答案,但我没有足够的声誉来评论)
自行登录是一种安全风险。用户可以输入/menu.html url,并且无需登录即可看到页面("deeplink")。这里的另一个问题是普通密码的存储。最好保存一个散列。
Tomcat提供了一种登录机制:https://tomcat.apache.org/tomcat-8.0-doc/realm-howto.html
在web.xml中,您可以定义保护区域,这些区域只能由经过身份验证的用户访问。对于身份验证,您可以使用JDBCRealm,它在数据库中执行用户查找。
解决了这个问题。查询是正确的,但ResultSet返回为空,因为由于某种原因,无法读取输入name="pword"中的值(当我试图将其值打印到控制台时返回null),因此在数据库中找不到匹配项。我认为这与输入是键入密码有关(这很奇怪,因为它应该这样工作)。我所做的是将输入类型更改为文本,这很有效,只是可以看到表单上密码字段中的字符。把它改回inputtype=password,这以某种方式解决了我的问题。不知道为什么会发生这种情况,但重定向现在正在工作。感谢所有提供帮助的人!
我发现了另一件事:表单中的输入元素没有名称。servlet试图通过它们的id从请求中获取它们,但在请求中提交的是输入元素的名称。
过时的(错误的)想法:
我想现在我发现了错误:您正在将查询中的字符串与sql中的"="进行比较,这是LIKE。。。
String sql = "SELECT username, password FROM player WHERE username LIKE ? AND password LIKE ?";