话说:
各位读者,晚上好!今天总结下登录的前端验证和后端代码,虽说是作为前端发布的,但是重心还是在后端。
包含功能:
1.前端Ajax验证;非空验证、验证码验证;
2.根据是否记住?存放用户于cookie中;存放Session中;
3.JSP页面显示
目录
1.前端效果展示
2.前端验证
3.后端代码
4.JSP页面代码
5.总结
难度系数:★★☆☆☆
建议用时:1H
1.前端效果展示
2.前端验证
1)页面代码
2)验证代码
1)页面代码
<form id="loginForm" action="userLogin" method="post" novalidate="novalidate" onsubmit="return checkLoginForm()">
<table>
<tbody>
<tr>
<td></td>
<td>
<span id="loginInfo" style="color:red;font-size:15px;font-weight:bolder;"><%=loginMsg %></span>
</td>
</tr>
<tr>
<th>
用户名/E-mail:
</th>
<td>
<input type="text" id="userName" name="userName" value="<%=userName%>"class="text" maxlength="20">
<span id="userNameInfo"></span>
</td>
</tr>
<tr>
<th>
密 码:
</th>
<td>
<input type="password" id="password" name="password" value="<%=password%>" class="text" maxlength="20" autocomplete="off">
<span id="passwordInfo" style="color:red;font-size:15px;font-weight:bolder;"></span>
</td>
</tr>
<tr>
<th>
验证码:
</th>
<td>
<span class="fieldSet">
<input type="text" id="code" name="code" class="text captcha" maxlength="4" autocomplete="off" style="width:105px;">
<img id="captchaImage" class="captchaImage" src="vertifyCode" onclick="this.src='vertifyCode?'+new Date()" title="点击更换验证码" style="height:30px;">
</span>
<span id="codeInfo"></span>
</td>
</tr>
<tr>
<th>
</th>
<td>
<label>
<input type="checkbox" id="remember" name="remember" value="1" style="width: 20px;height:20px;">记住我
</label>
<label>
<a >找回密码</a>
</label>
</td>
</tr>
<tr>
<th>
</th>
<td>
<input type="submit" class="submit" value="登 录">
</td>
</tr>
<tr class="register">
<th>
</th>
<td>
<dl>
<dt>还没有注册账号?</dt>
<dd>
立即注册即可体验在线购物!
<a href="register.jsp">立即注册</a>
</dd>
</dl>
</td>
</tr>
</tbody></table>
</form>
2)验证代码
<!-- 引入jQuery-->
<script src="js/jquery-1.8.3.js"></script>
<!--用户名Ajax验证 -->
<script type="text/javaScript">
$(function() {
$("#userName").focus();
$("#userName").blur(function() {
var userName = $(this).val().trim();
console.log("用户名:"+userName);
//登录 用户名Ajax验证
$.ajax({
url:"loginForm",
type:"get",
dataType:"json",
async:true,
data:{"userName":userName},
success:function(data) {
console.log("后台传过来的data:"+data);
console.log("登录名请求后台成功!");
if(data == null) {
$("#userNameInfo").html("×");
$("#userNameInfo").css({"color":"red","font-size":"25px","font-weight":"bolder"});
}else{
$("#userNameInfo").html("√");
$("#userNameInfo").css({"color":"green","font-size":"22px","font-weight":"bolder"});
}
},
error:function() {
console.log("登录请求后台失败!");
}
});
})
//密码位数验证
$("#password").blur(function() {
var password = $(this).val().trim();
console.log("密码长度:"+password.length);
if(password.length<6){
$("#passwordInfo").html("密码位数有误");
//$(this).focus();
}else{
$("#passwordInfo").html("");
}
});
//前台验证验证码
$("#code").keyup(function() {
var code = $(this).val().trim();
//因为要用到转换为小写函数,这个属于DO对象的,转换麻烦,直接用JS方法取值
var code2 = document.getElementById("code").value.toLowerCast();
var remember = $("#remember").val().trim();
console.log("键盘动了...");
console.log("转小写后的验证码:"+code2);
console.log("是否记住《《《《《《《《《《:"+remember);
//1.Ajax 请求后台拿到验证码
$.ajax({
url:"getRegisterCode",
type:"get",
dataType:"json",
async:true,
data:{"code":code},
success:function(data) {
console.log("登录请求后台成功啦!"+data);
//思路是:如果用户输入错误,直接清空;如果正确,直接√
if(code2.length>4) {
$("#codeInfo").html("验证码有误");
$("#codeInfo").css({"color":"red","font-size":"15px","font-weight":"bolder"});
//$("#code").val("").focus();
}else if(code2.length==4){
if(code2 == data){
$("#codeInfo").html("√");
$("#codeInfo").css({"color":"green","font-size":"25px","font-weight":"bolder"});
}else{
$("#codeInfo").html("验证码有误");
$("#codeInfo").css({"color":"red","font-size":"15px","font-weight":"bolder"});
}
}else{
//这里判断有点多余,但是也无可厚非,用户可能回删数据
if(code2 == data) {
$("#codeInfo").html("√");
$("#codeInfo").css({"color":"green","font-size":"25px","font-weight":"bolder"});
}else{
$("#codeInfo").html("验证码有误");
$("#codeInfo").css({"color":"red","font-size":"15px","font-weight":"bolder"});
}
}
},
error:function() {
console.log("登录请求后台失败!");
}
})
});
//是否记住?
$("#remember").click(function() {
console.log("进来了!");
var remember =$(this).val().trim();
console.log("根据选择判断是否记住???????????????"+remember);
})
});
//onsubmit事件验证
function checkLoginForm(){
var flag = false;
//提交验证
$(function() {
var userName = $("#userName").val().trim();
var password = $("#password").val().trim();
var code = $("#code").val().trim();
var remember = $("#remember").val().trim();
console.log("用户名"+userName);
console.log("是否记住?>>>>>>>>>>>>>>>>"+remember);
if(userName == "") {
console.log("用户名不能为空。。");
$("#loginInfo").html("请填写用户名");
$("#userName").focus();
return false;
}else{
$("#loginInfo").html("");
if(password == "") {
$("#loginInfo").html("请填写密码");
$("#password").focus();
return false;
}else{
$("#loginInfo").html("");
if(code =="") {
$("#loginInfo").html("请填写验证码");
$("#code").focus();
return false;
}else{
$("#loginInfo").html("");
flag = true;
return false;//这里return什么不重要
}
}
}
})
return flag;//这里才是控制表单提交与否的关键所在! 因为执行完$(function(){})之后,此方法需要返回值 onsubmit = "return checkLoginForm()"
}
</script>
温馨提示:验证码长度可以直接用input的属性maxlength控制,而不用在前端代码中判断。
3.后端代码
1)Pojo
2)Dao
3)UserMapper.xml
4)Controller层
我们要优化的问题是:注册用户会Ajax验证用户名;登录Ajax也会验证用户名;登录后还要进行判断操作,这3种方式都用1个SQL语句搞定,而不用写2个。
Mybatis的动态SQL,非常方便。因为前端的注册userName和登录userName都是blur()事件,这个时候password都是null(String password)。
1)Pojo
这里面当然也有:【记住我?】 这个属性。
public class User {
private int userId;
private String userName;
private String password;
private String rePassword;
private String email;
private String name;
private String sex;
private Date birth;
private String address;
private String code;
private Date registerTime;
private Date loginTime;
private int remember;//记住我?checkbox
public User() {}
其他省略......
}
2)Dao
public interface UserDao {
//注册用户名Ajax验证 登录Ajax验证 及登录都用这个方法
User getUserByUserName(User user);
}
3)UserMapper.xml
<!-- 3.用户名是否存在 -->
<select id="getUserByUserName" parameterType="com.hmc.pojo.User" resultType="com.hmc.pojo.User">
select * from user where userName = #{userName}
<if test="password != null">
and
password = #{password}
</if>
</select>
注意,用到 where或者 c:if等,参数要封装在一个对象里面,否则找不到。
这里是动态SQL的核心。
4)Controller层
Service层就省略,调一下Dao方法即可。
这里要搞定的事情是:
1.取得后台验证码,并回调给前台做判断;
2.查数据,存Cookie,存Session,页面跳转
@Controller
public class StoreCustomerController {
@Autowired
private UserService userService;
@Autowired
private VertifyCodeServlet vertifyCodeServlet;
//6.登录用户名Ajax验证
@RequestMapping("loginForm")
@ResponseBody
public String vertifyLoginUserName(User user) {
User user2 = userService.getUserByUserName(user);
System.out.println("根据用户名查到的用户为:"+user2);
if(user2 != null) {
System.out.println("转换后的用户json不为空:格式为:"+new Gson().toJson(user2));
return new Gson().toJson(user2);//当然的导包进去喽~
}else {
System.out.println("转换后的用户json为空:格式为:"+new Gson().toJson(user2));//null
return new Gson().toJson(user2);
}
}
//7.用户登陆操作
@RequestMapping("userLogin")
public String userLogin(User user,Model model,HttpServletResponse resp,HttpServletRequest req) {
int remember = user.getRemember();
System.out.println("用户名是否记住? "+remember);
//1.判断用户名和密码是否正确?正确在进行以下操作
User user2 = userService.getUserByUserName(user);
System.out.println("动态Sql 得到的用户为:"+user2);
if(user2 == null) {
model.addAttribute("loginMsg", "用户名或密码不正确");//因为是重定向,所以存不了值,怎么办?
Cookie cookie = new Cookie("loginMsg", "用户名或密码不正确");
cookie.setMaxAge(4);//4s就够啦,下次登录就会消失
resp.addCookie(cookie);
//返回登录接界面,并给错误信息提示
return "redirect:login.jsp";
}else {
//2.根据用户是否勾选记住我?选择是否存cookie
if(remember == 1) {
//如果用户勾选记住我?就先默认存储60S
Cookie cookieUserName = new Cookie("userName", user2.getUserName());
Cookie cookiePassword = new Cookie("password", user2.getPassword());
cookieUserName.setMaxAge(60);
cookiePassword.setMaxAge(60);
resp.addCookie(cookieUserName);
resp.addCookie(cookiePassword);
}
//不论勾选记住否,都要存到session里面
req.getSession().setAttribute("user", user2);
//跳转页面
return "index";
}
}
}
--------------------------------------------------------------------------------
4.JSP页面代码
这个主要是从cookie里面拿数据:用户信息和登录错误信息
<%
//如果用户保存了cookie,取出来
Cookie[] cookies = request.getCookies();
String userName = "";
String password = "";
String loginMsg = "";
if(cookies != null) {
for(int i=0;i<cookies.length;i++) {
//取出用户名和密码
if("userName".equals(cookies[i].getName())) {
userName = cookies[i].getValue();
}
if("password".equals(cookies[i].getName())) {
password = cookies[i].getValue();
}
//取出用户名和密码不正确时的提示信息
if("loginMsg".equals(cookies[i].getName())) {
loginMsg = cookies[i].getValue();
}
}
}
%>
页面这么取值:
value="<%=userName%>"
value="<%=password%>"
5.总结
1.input框中maxlength属性作用蛮大的。比如,用这个属性后,前端验证就不用判断code.length>4的情况了,因为不可能输入4位!
直接在表单里面做了控制!
之前我是这么处理的:
if(code.length>4){
$("#code").val("").focus();这样的效果就是强制清空输入内容了,感觉还是有点强制!
}
2.后端怎么知道前端是否记住用户名呢?怎么判定选择还是未选择的状态呢?
在前端,地球人都知道,type=“checkbox” 如果选择,那么用前端技术直接判断其属性
$("#remember").checked == true;
判断即可,但是后端怎么判断呢?
<input type="checkbox" name="remember" value="1">
value的值给还是不给?不给后端根据name获取到的是啥情况?
给了比如value=“1” 那么选择或者不选择,框架中,封装后对象怎么判断选择还是没选择?这个和你封装的对象参数类型有关。比如,我们是否记住?对应user对象的一个属性remember 是int类型的,那么value=“1” 如果用户勾选,那么后台获取的就是这个value值;若未勾选,就是remember实体类属性对应的默认值。比如:int 默认未勾选就是0; String 未勾选默认就是null…
3.问题背景:无论注册用户名Ajax验证、登录用户名Ajax验证、登录后整个用户判断;
都需要用到同一个SQL语句,所以写成动态的,而不是写2个SQL。
.<select id="getUserByUserName" parameterType="com.hmc.pojo.User" resultType="com.hmc.pojo.User">
select * from user where userName = #{userName}
<if test="password != null || password != ''">
and
password = #{password}
</if>
</select>
这段代码有什么问题?在c:if test=""里面,是不能用|| 或者 && 只能用 and or
不行你试一试?另外,password没有,就null,当然满足 != ""所以会满足条件,所以就差不到。不是|| 或&& 用错!而是条件错了!
<!-- 3.用户名是否存在 -->
<select id="getUserByUserName" parameterType="com.hmc.pojo.User" resultType="com.hmc.pojo.User">
select * from user where userName = #{userName}
<if test="password != null">
and
password = #{password}
</if>
</select>
4.autocomplete=“off” inpu属性
input 的属性autocomplete 默认为on其含义代表是否让浏览器自动记录之前输入的值
很多时候,需要对客户的资料进行保密,防止浏览器软件或者恶意插件获取到可以在input中加入autocomplete=“off” 来关闭记录
5.Cookie、Session还是蛮神奇的。Cookie在创建添加的时候,用到的是response对象,前端取值遍历的时候,用到的是request对象,Session用request对象。
这个要深刻理解。用户发起请求,是否存Cookie,用户选择,用户一旦选择,那么服务器在处理请求的时候,会给用户地址带一个信息(Cookie),添加Cookie是服务器端在响应的时候做的处理,所以response.addCookie()要这么用;
下次用户再次请求,便携带上次服务器给它传递的cookie信息,这个时候,前端是否显示,自然request就能够拿到这些信息了。所有在得到cookie的时候,用request.getCookies()得到一个Coookies[];同理,Session会话是用户请求主动建立的,每次添加用request.getSession().addAttribute()即可。
6.我在处理用户名或密码错误的时候,因为要重定向,所以没发用model.addAttribute()带参;但是又不能用session,因为下次访问login.jsp,错误提示不能一直在吧?所以用的是cookie,生命周期短点,有点小残忍。
好了!开饭吧!一会再会!