前言
WEB组队大作业要求用JSP实现后台访问修改数据库,用了老师的课件和网上查找得来的资料。
代码
login.jsp:
<body>
<div id="backgroundpic"></div>
<div id="logInWrap">
<div id="logInContain">
<h1>登录</h1>
<form action="loginCheck.jsp" method="POST" name="formLogin">
<input type="text" placeholder="昵称/邮箱" name="name">
<input type="password" placeholder="密码" name="password">
<input type="button" value="登录" onclick="doCheck_logIn()">
</form>
<p>还没有帐号?<a href="signup.jsp">前往注册</a></p>
<%
String flag = request.getParameter("errNo");
try{
if(flag!=null)
out.println("<span id='loginMsg'>用户名不存在或密码错误</span>");
}catch(Exception e){
e.printStackTrace();
}
%>
</div>
<span id="logInBack"><a href="Index.html">返回</a></span>
</div>
</body>
loginCheck.jsp:
<%@page language="java" import="java.util.*,java.sql.*" contentType="text/html; charset=utf-8"%>
<% request.setCharacterEncoding("utf-8");
String msg="";
String pwd="", name="";//数据库中保存的密码和用户名
String conStr = "jdbc:mysql://172.18.187.10:53306/blog_15336202"
+ "?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8";
String userName = request.getParameter("name"); //从登录页面post过来的用户名和密码
String userPwd = request.getParameter("password");
try {
Class.forName("com.mysql.jdbc.Driver"); // 查找数据库驱动类
Connection con=DriverManager.getConnection(conStr, "user", "123");
Statement stmt=con.createStatement(); //创建MySQL语句的对象
ResultSet rs=stmt.executeQuery("select * from users where (name = '" + userName + "' or email = '" + userName + "') and password = '" + userPwd + "'");//执行查询,返回结果集
if(rs.next()) { //把游标(cursor)移至第一个或下一个记录
response.sendRedirect("loGinsuccess.jsp?username=" + userName); //密码正确跳转loGinsuccess.jsp
}else{
response.sendRedirect("login.jsp?errNo");//密码不对返回到登陆
}
rs.close(); stmt.close(); con.close();
}
catch(Exception e){
msg = e.getMessage();
}
%>
loGinsuccess.jsp:
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<%request.setCharacterEncoding("utf-8");%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录成功界面</title>
</head>
<body>
<h1>登录成功!!!</h1>
</body>
</html>
signup.jsp:
<%@page language="java" import="java.util.*,java.sql.*" contentType="text/html; charset=utf-8"%>
<% request.setCharacterEncoding("utf-8");
String msg = "";
String connectString = "jdbc:mysql://172.18.187.10:53306/blog_15336202" + "?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8";
String user="user"; String pwd="123";
String username = request.getParameter("name");
String password = request.getParameter("password");
String email = request.getParameter("email");
if (request.getMethod().equalsIgnoreCase("post")){
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(connectString,user, pwd);
Statement stmt = con.createStatement();
try {
String fmt="insert into users(name,password,email) values('%s', '%s', '%s')";
String sql = String.format(fmt,username,password, email);
int cnt = stmt.executeUpdate(sql);
if (cnt > 0)
msg = "注册成功!";
stmt.close(); con.close();
}
catch (Exception e) {
msg = e.getMessage();
}
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>注册</title>
<script src="js/loginAndRegister.js"></script>
</head>
<body>
<div id="backgroundpic"></div>
<div id="signUpWrap">
<div id="signUpContain">
<h1>注册</h1>
<form action="signup.jsp" method="post" name="formRegister">
<input type="text" placeholder="昵称" name="name" id="username">
<input type="text" placeholder="邮箱" name="email" id="email">
<input type="password" placeholder="密码" name="password" id="password">
<input type="password" placeholder="确认密码" name="password2" id="password2">
<input type="button" value="注册" onclick="doCheck_Register()">
</form>
<p>已有帐号?<a href="login.jsp">前往登录</a></p>
<span id="registerMsg"><%=msg%><span>
</div>
<span id="signUpBack"><a href="Index.html">返回</a></span>
</div>
</body>
</html>
注册和登录检查函数:
//注册检查函数:验证是否输入完全,两次输入的密码是否相同。
function doCheck_Register() {
var inPut = document.querySelectorAll("div#signUpContain form input");
let flag = 0;
for (let i = 0; i < inPut.length - 1; ++i) {
if (inPut[i].value == "") {
alert("请输入 " + inPut[i].placeholder);
document.querySelectorAll("div#signUpContain form input")[i].focus();
flag++;
break;
}
}
var pass1 = document.querySelector("div#signUpContain form input#password");
var pass2 = document.querySelector("div#signUpContain form input#password2");
if(flag == 0) {
if (pass1.value != pass2.value) {
alert("两次密码不相同!")
document.querySelector("div#signUpContain form input#password2").focus();
flag++;
}
}
if (flag == 0) {
formRegister.submit();
}
return false;
}
//登录检查函数:验证是否输入,否则提示输入。
function doCheck_logIn() {
var inPut = document.querySelectorAll("div#logInContain form input");
let flag = 0;
for (let i = 0; i < inPut.length - 1; ++i) {
if (inPut[i].value == "") {
alert("请输入 " + inPut[i].placeholder);
document.querySelectorAll("div#logInContain form input")[i].focus();
flag++;
break;
}
}
if (flag == 0) {
formLogin.submit();
}
return false;
}
更新-2019.6.21
随着大作业的不断迭代修改,注册的功能被一点点修改和优化,这一次修改主要包括:
- 输入昵称邮箱等信息后提示是否可注册,
无需刷新
页面 - 分离注册判断jsp程序和页面代码,提高可读性
效果如图:
想法
实际上之前就一直想实现这样的局部刷新
效果,看起来比刷新页面才知道用户名是否唯一要酷炫多了,但是可能是没有怎么用过AJAX
所以一直有一种畏惧心理,直到某天晚上我实在是想要实现这个“实时”提示的酷炫小功能,遂决定克服恐惧。
实现思路
思路其实很清晰,之前没用AJAX时,是通过提交表单的方式,将当前输入通过POST提交给本jsp程序,然后通过查询数据库确定输入值是否已存在,功能都有,不足就是需要刷新页面。
而AJAX
就是解决这种异步刷新需求的。
通过AJAX请求,一旦输入值发生变动,可以通过js函数创建http请求
,将输入值提交到registerCheck.jsp后台程序
,后台程序完成上述检查工作再发送响应正文
,响应正文根据不同情况设置为各种提示消息,最后回到js函数中,收到http响应正文,将正文提示消息在html文档中合适位置显示出来,就完成输入提示了。并且整个过程是异步进行
的,只会对局部
进行刷新,提高整个网页浏览的流畅性。
关键和遇到的问题
关键
写代码的时候直接把后台的检查程序单独列出来
,这样比原来全都混在一起要清晰多了,后期也更容易修改。
也就是说,实际上输入信息之后,信息的值会被提交到一个jsp程序里,这个jsp程序完成数据库检查唯一性的工作,然后通过AJAX发送响应回到当前的注册页面里。整个工作对用户是“透明的”
,这样一来就提高了用户浏览网页的流畅度了,不会一直刷新刷新。
问题
代码写好之后,输入英文数字字符是ok的,但是当输入单引号的时候会出现问题,原因就是MySQL注入
的问题了。
由于registerCheck.jsp检查程序里查询数据库的语句是简单的"select * from users where name='" + value + "'"
,当输入中包含单引号这种会影响后台数据库查询语句时,就会出现预料之外
的问题。
解决这个问题的方法及时在前端提交输入值的时候,先做一个判断,将单引号字符去掉:
if (id == "username" || id == "email") {
inPut_value = inPut_value.split("'").join("");
}
不过,虽然解决了输入单引号的问题,但是考虑到其他MySQL注入问题
,诸如输入“or”、“and”等数据库查询语句字符的时候,也会出现意想不到的问题,这个问题我还没有解决…因为涉及到JAVA程序的编写,日后再来完善!
完整代码
前端输入页面signup.jsp
{% fold %}
<%@page language="java" import="java.util.*,java.sql.*" contentType="text/html; charset=utf-8"%>
<% request.setCharacterEncoding("utf-8");
String userId = request.getParameter("userId");
String msg = "";
String query = "";
String sql = "";
String sql2 = "";
String connectString = "jdbc:mysql://172.18.187.10:3306/blog_15336202" + "?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8";
String user="user"; String pwd="123";
String username = request.getParameter("name");
String password = request.getParameter("password");
String sex = "保密";
String birthday = "";
String phone = "";
String hobby = "";
String hometown = "";
String email = request.getParameter("email");
String job = "";
String school = "";
String company = "";
String sign = "";
String resume = "";
if (request.getMethod().equalsIgnoreCase("post")){
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(connectString, user, pwd);
Statement stmt = con.createStatement();
query = request.getParameter("query");
//TODO 解决MySQL注入问题
sql="select*from users where name='" + username +"'"; //查询数据库中是否有相同用户名
sql2="select*from users where email='" + email + "'"; //查询数据库中是否有相同邮箱
ResultSet rs=stmt.executeQuery(sql);
if (!rs.next()) { //没有相同用户名,继续判断邮箱是否相同
try {
ResultSet rss = stmt.executeQuery(sql2);
if (!rss.next()) { //没有相同邮箱,注册成功
String fmt="insert into users(name, password, sex, birthday, phone, hobby, hometown, email, job, school, company, sign, resume) values('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')";
sql = String.format(fmt, username, password, sex, birthday, phone, hobby,hometown, email, job, school, company, sign, resume);
int cnt = stmt.executeUpdate(sql);
if (cnt > 0) {
msg = "注册成功啦!";
// 设置 name 和 url cookie
Cookie newuser = new Cookie("user", username);
userId = username;
// 设置cookie过期时间为一周。
newuser.setMaxAge(7*60*60*24);
// 在响应头部添加cookie
response.addCookie(newuser);
response.sendRedirect("index.jsp");
}
}
else { //用户名相同,但是邮箱已注册
msg = "啊呀!这个邮箱被人注册了!";
}
stmt.close(); con.close();
}
catch (Exception e) {
msg = e.getMessage();
}
}
else { //用户名已注册
msg = "啊哦!这个名字已经被别人抢先一步了!";
}
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>注册</title>
<script src="js/loginAndRegister.js"></script>
<style>
* {
font-family: Brush Script MT, STKaiti, YouYuan, sans-serif;
}
a {
text-decoration: none;
}
body {
font-size: 15px;
}
input {
font-family: 微软雅黑;
}
div#backgroundpic {
position: absolute;
z-index: -100;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background: url("images/wholehomepic.jpeg")no-repeat;
background-size: cover;
opacity: 0.5;
}
div#signUpContain {
text-align: center
}
div#signUpContain form {
width: 300px;
margin: 0 auto;
/* text-align: center */
}
div#signUpContain form input {
display: block;
width: 300px;
line-height: 35px;
text-indent: 1em;
margin: 30px 0;
border-radius: 5px;
}
div#signUpContain form input:last-child {
text-indent: 0;
width: 300px;
outline: none;
border: 1px solid lightgray;
background-color: gray;
line-height: 35px;
color: white;
font-size: 18px;
font-weight: bold;
}
span#registerMsg {
font-family: 宋体;
color: red;
font-weight: bold;
}
@media only screen and (max-width: 600px) {
div#signUpContain form input {
width: 250px;
margin: 20px auto;
line-height: 35px;
}
div#signUpContain form input#confirm {
width: 250px;
}
}
div#signUpContain form>div {
position: relative;
}
div#signUpContain form span {
line-height: 10px;
left: 10px;
top: 45px;
position: absolute;
}
</style>
</head>
<body>
<div id="backgroundpic"></div>
<div id="signUpWrap">
<div id="signUpContain">
<h1>注册</h1>
<form action="signup.jsp" method="post" name="formRegister">
<div>
<input type="text" placeholder="昵称" name="name" id="username" oninput="register_check(id)">
<span class="username"></span>
<%-- 显示提示消息 --%>
</div>
<div>
<input type="text" placeholder="邮箱" name="email" id="email" oninput="register_check(id)">
<span class="email"></span>
<%-- 显示提示消息 --%>
</div>
<div>
<input type="password" placeholder="密码" name="password" id="password" onchange="register_check(id)">
<span class="password"></span>
<%-- 显示提示消息 --%>
</div>
<div>
<input type="password" placeholder="确认密码" name="password2" id="password2" onchange="register_check(id)">
<span class="password2"></span>
<%-- 显示提示消息 --%>
</div>
<input type="button" value="注册" onclick="doCheck_Register()" id="confirm">
</form>
<p>已有帐号?<a href="login.jsp">前往登录</a></p>
<span id="registerMsg"><%=msg%><span>
<span id="result"></span>
</div>
</div>
</body>
<script>
//===============注册界面输入框检测函数===============
function register_check(id) {
// 创建http请求
var inPut_value = document.getElementById(id).value;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
// 当http请求的状态变化时执行
if (xmlhttp.readyState == 4) { // 4-已收到http响应数据
if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status == 304) {
var inPut = document.getElementById(id);
var span_result = document.getElementsByClassName(id)[0];
inPut_value = inPut.value;
// 200~299-OK 304-unmodified
// alert(xmlhttp.responseText);
// http响应的正文
span_result.innerHTML = xmlhttp.responseText;
} else {
alert("error");
}
};
}; //打开http请求(open)的参数:get|post,url,是否异步发送
// 提交输入值前进行判断,解决MySQL注入单引号问题,不过未完全解决MySQL注入的问题,TODO
if (id == "username" || id == "email")
inPut_value = inPut_value.split("'").join("");
xmlhttp.open("get", "registerCheck.jsp?id=" + id + "&value=" + inPut_value, true);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send(null);
//发送http请求。get只能用null作为参数
}
//===============END注册界面输入框检测函数===============
</script>
</html>
{% endfold %}
后端检查程序registerCheck.jsp
{% fold %}
<%@page language="java" import="java.util.*,java.sql.*" contentType="text/html; charset=utf-8"%>
<% request.setCharacterEncoding("utf-8");
String param = request.getParameter("id");
String value = request.getParameter("value");
String conStr = "jdbc:mysql://172.18.187.10:3306/blog_15336202"
+ "?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8";
Class.forName("com.mysql.jdbc.Driver"); // 查找数据库驱动类
Connection con=DriverManager.getConnection(conStr, "user", "123");
Statement stmt=con.createStatement(); //创建MySQL语句的对象
if (value.equals("")) {
out.print("输入点东西嘛~这么小气╭(╯^╰)╮");
}
else {
if (param.equals("username")) {
ResultSet rs=stmt.executeQuery("select * from users where name='" + value + "'");
if (!rs.next()) {
out.print("该昵称可以使用o(∩_∩)o");
}
else {
out.print("该昵称已被注册了哦o_O");
}
rs.close();
}
else if (param.equals("email")) {
ResultSet rs=stmt.executeQuery("select * from users where email='" + value + "'");
if (!rs.next()) {
out.print("这个邮箱可以使用呢o(∩_∩)o");
}
else {
out.print("阿叻~这个邮箱被人注册了哦");
}
rs.close();
}
}
stmt.close(); con.close();
%>
{% endfold %}