以下是使用过滤器的Java代码,如果用户名和密码也正确,则每次都会显示错误页面。请帮助我,我对这个概念知之甚少。
String sql="select * from reg where username='"+user+"' and pass='"+pwd+"'";
rs=st.executeQuery(sql);
if(rs.next())
{
chain.doFilter(request,response);
}
else
sc.getRequestDispatcher("/error.html").forward(request,response);
答案 0 :(得分:30)
String sql =“select * from reg where username ='”+ user +“'and pass ='”+ pwd +“'”;
这是一种非常糟糕的做法。这种方法要求用户名和密码都通过请求传递普通香草。而且,你有一个SQL注入攻击漏洞。
利用会话,在JSP / Servlet中你有HttpSession
。实际上也没有必要在使用Filter
的每个请求上反复点击数据库。这是不必要的昂贵。只需使用User
将Servlet
置于会话中,然后使用Filter
检查每次请求的存在情况。
从/login.jsp
开始:
<form action="login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit"> ${error}
</form>
然后,创建一个LoginServlet
,该url-pattern
映射到/login
的{{1}},并doPost()
实现如下:
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Put user in session.
response.sendRedirect("/secured/home.jsp"); // Go to some start page.
} else {
request.setAttribute("error", "Unknown login, try again"); // Set error msg for ${error}
request.getRequestDispatcher("/login.jsp").forward(request, response); // Go back to login page.
}
然后,创建一个映射在LoginFilter
url-pattern
上的/secured/*
(您可以选择自己的/protected/*
,例如/restricted/*
,/users/*
,{{ 1}}等等,但这必须至少涵盖所有安全页面,你还需要将JSP放在WebContent中的相应文件夹中)并实现doFilter()
如下:
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String loginURI = request.getContextPath() + "/login.jsp";
boolean loggedIn = session != null && session.getAttribute("user") != null;
boolean loginRequest = request.getRequestURI().equals(loginURI);
if (loggedIn || loginRequest) {
chain.doFilter(request, response); // User is logged in, just continue request.
} else {
response.sendRedirect(loginURI); // Not logged in, show login page.
}
那应该是它。希望这可以帮助。
要了解UserDAO
的外观,您可能会发现this article很有用。它还介绍了如何使用PreparedStatement
保存您的Web应用程序免受SQL注入攻击。
答案 1 :(得分:3)
使用预先准备好的声明,您的代码是SQL injection的公开邀请。
Connection con = getMyConnection();
try {
//no string concatenation, we use ? instead:
PreparedStatement ps = con.prepareStatement("select * from reg where username=? and pass=?");
try {
//actual value for parameters are set here:
ps.setString(1, user);
ps.setString(2, pwd);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
chain.doFilter(request,response);
} else {
sc.getRequestDispatcher("/error.html").forward(request,response);
}
} finally {
ps.close();
}
} finally {
con.close();
}
现在提出您的问题,请检查:
答案 2 :(得分:2)
这么多错了......: - /
select * from reg
是不必要的,因为您只想知道是否存在行。如果您使用select 1
,则数据库不必检查行的内容,只能从索引中提供查询结果。如果您希望有很多行,select 1 where exists ...
会更快,因为这样可以让DB在查找至少一行后对查询进行短路。finally
块中的语句和结果集。这意味着不保证始终处置它们(例如,如果有SQLException
抛出)导致资源和连接泄漏。答案 3 :(得分:1)
首先,你真的应该为此使用参数化查询。如果用户输入'";DROP TABLE reg;
作为用户名,您将遇到大麻烦。
另外,您确定用户名和密码是否正确?资本化怎么样?