Servlet接收HTML表单空输入致数据库主键重复问题求助
问题:HTML表单输入限制失效,空值存入数据库引发主键重复错误
我通过HTML表单收集用户输入,使用Servlet将数据插入数据库。虽然在HTML代码中设置了输入格式限制,但空输入仍能被提交,第二次提交空字段时出现以下错误:
错误信息
Duplicate entry '' for key 'users.PRIMARY'
这表明用户名被以空字符串的形式存入了数据库,而用户名是主键,重复的空字符串触发了主键冲突。
原HTML表单代码
<form action="userreg" method="post"> Username : <input type="text" name="username" pattern=".{3,}" title ="must contains more then 3 letters"><br/><br/> Password : <input type="password" name="password" placeholder="password must be 8 char long one upper, lower case letter must" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" title="Must have 8 chars one lowercase , uppercase"><br/><br/> FirstName: <input type="text" pattern=".{3,}" title="this field cant be empty" name="firstname"><br/><br/> Last Name: <input type="text" pattern=".{3,}" title="this field cant be empty" name="lastname"><br/><br/> Address : <input type="text" pattern=".{3,}" name="address"><br/><br/> Phone No : <input type="text" pattern=".{3,}" name="phone"><br/><br/> Email Id : <input type="text" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" name="mailid" placeholder="xyz@gmail.com" title="please enter valid mail"><br/><br/> <input type="submit" value=" I AGREE FOR ALL TERMS & CONDITIONS ! REGISTER ME "> </form>
原Servlet代码片段
try { Connection con = DBConnection.getCon(); PreparedStatement ps = con .prepareStatement("insert into " + IUserContants.TABLE_USERS + " values(?,?,?,?,?,?,?,?)"); ps.setString(1, uName); ps.setString(2, pWord); ps.setString(3, fName); ps.setString(4, lName); ps.setString(5, addr); ps.setString(6, phNo); ps.setString(7, mailId); ps.setInt(8, 2); int k = ps.executeUpdate(); if (k==1) { RequestDispatcher rd = req.getRequestDispatcher("Sample.html"); rd.include(req, res); pw.println("<h3 class='tab'>User Registered Successfully</h3>"); } else { RequestDispatcher rd = req.getRequestDispatcher("Sample.html"); pw.println("<h3 class='tab'>Registration failed !, please enter valid details</h3>"); rd.include(req, res); pw.println("Sorry for interruption! Register again"); } } catch (Exception e) { e.printStackTrace(); }
问题原因
- 前端验证不彻底:HTML的
pattern属性仅做格式校验,但未设置required属性,用户可以直接提交空输入;且前端验证可被绕过(如禁用JavaScript、手动构造请求)。 - 后端无输入校验:Servlet直接将请求参数插入数据库,未对空值或不符合格式的数据做拦截,导致无效数据进入数据库。
- 数据库约束不足:用户名作为主键,未设置
NOT NULL约束,允许空字符串存入。
解决方案
1. 前端强化验证:添加required属性
给所有必填输入框添加required属性,确保浏览器在提交前拦截空输入,配合pattern完成前端基础校验:
<form action="userreg" method="post"> Username : <input type="text" name="username" pattern=".{3,}" title="必须包含至少3个字符" required><br/><br/> Password : <input type="password" name="password" placeholder="密码需8位以上,包含大小写字母和数字" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" title="密码必须8位以上,包含一个小写字母、一个大写字母" required><br/><br/> FirstName: <input type="text" pattern=".{3,}" title="此字段不能为空,至少3个字符" name="firstname" required><br/><br/> Last Name: <input type="text" pattern=".{3,}" title="此字段不能为空,至少3个字符" name="lastname" required><br/><br/> Address : <input type="text" pattern=".{3,}" name="address" required><br/><br/> Phone No : <input type="text" pattern=".{3,}" name="phone" required><br/><br/> Email Id : <input type="text" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" name="mailid" placeholder="xyz@gmail.com" title="请输入有效的邮箱地址" required><br/><br/> <input type="submit" value=" 我同意所有条款!注册账号 "> </form>
2. 后端添加输入校验(核心)
前端验证无法完全信任,必须在Servlet层添加校验逻辑,拦截无效数据后再执行数据库操作:
// 先获取并修剪请求参数 String uName = req.getParameter("username") != null ? req.getParameter("username").trim() : ""; String pWord = req.getParameter("password") != null ? req.getParameter("password").trim() : ""; String fName = req.getParameter("firstname") != null ? req.getParameter("firstname").trim() : ""; String lName = req.getParameter("lastname") != null ? req.getParameter("lastname").trim() : ""; String addr = req.getParameter("address") != null ? req.getParameter("address").trim() : ""; String phNo = req.getParameter("phone") != null ? req.getParameter("phone").trim() : ""; String mailId = req.getParameter("mailid") != null ? req.getParameter("mailid").trim() : ""; // 输入合法性校验 boolean isValid = true; String errorMsg = ""; if(uName.isEmpty() || uName.length() < 3){ errorMsg += "用户名不能为空,且至少3个字符<br/>"; isValid = false; } if(pWord.isEmpty() || !pWord.matches("(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,}")){ errorMsg += "密码不能为空,需8位以上且包含大小写字母和数字<br/>"; isValid = false; } if(fName.isEmpty() || fName.length() < 3){ errorMsg += "名字不能为空,且至少3个字符<br/>"; isValid = false; } if(lName.isEmpty() || lName.length() < 3){ errorMsg += "姓氏不能为空,且至少3个字符<br/>"; isValid = false; } if(addr.isEmpty() || addr.length() < 3){ errorMsg += "地址不能为空,且至少3个字符<br/>"; isValid = false; } if(phNo.isEmpty() || phNo.length() < 3){ errorMsg += "手机号不能为空,且至少3个字符<br/>"; isValid = false; } if(mailId.isEmpty() || !mailId.matches("[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$")){ errorMsg += "请输入有效的邮箱地址<br/>"; isValid = false; } // 校验不通过,返回错误提示 if(!isValid){ RequestDispatcher rd = req.getRequestDispatcher("Sample.html"); pw.println("<h3 class='tab'>注册失败!</h3>"); pw.println("<p>" + errorMsg + "</p>"); rd.include(req, res); pw.println("请重新填写注册信息"); return; } // 校验通过,执行数据库插入 try { Connection con = DBConnection.getCon(); PreparedStatement ps = con.prepareStatement("insert into " + IUserContants.TABLE_USERS + " values(?,?,?,?,?,?,?,?)"); ps.setString(1, uName); ps.setString(2, pWord); ps.setString(3, fName); ps.setString(4, lName); ps.setString(5, addr); ps.setString(6, phNo); ps.setString(7, mailId); ps.setInt(8, 2); int k = ps.executeUpdate(); if (k == 1) { RequestDispatcher rd = req.getRequestDispatcher("Sample.html"); rd.include(req, res); pw.println("<h3 class='tab'>用户注册成功</h3>"); } else { RequestDispatcher rd = req.getRequestDispatcher("Sample.html"); pw.println("<h3 class='tab'>注册失败!请检查输入信息</h3>"); rd.include(req, res); pw.println("请重新尝试注册"); } } catch (Exception e) { e.printStackTrace(); // 捕获主键重复等数据库异常,返回友好提示 RequestDispatcher rd = req.getRequestDispatcher("Sample.html"); pw.println("<h3 class='tab'>注册失败!用户名已存在或系统异常</h3>"); rd.include(req, res); }
3. 数据库层面加固
修改用户表结构,给用户名字段添加NOT NULL约束,从数据库层面防止空值插入:
ALTER TABLE users MODIFY COLUMN username VARCHAR(50) NOT NULL PRIMARY KEY;
内容的提问来源于stack exchange,提问作者Prince Bhati
相关产品推荐
相关产品推荐

