Spring shiro + bootstrap + jquery.validate 实现登录、注册功能


Posted in jQuery onJune 02, 2017

之前的文章中我们已经搭建好框架,并且设计好了,数据库。

现在我们开始实现登录功能,这个可以说是Web应用最最最普遍的功能了。

先来说说我们登录的逻辑:

输入用户名、密码(validate进行前端验证)——ajax调用后台action方法——根据用户名调用业务层到数据层查询数据库信息——查询的密码跟用户输入的密码比对——shiro登录身份验证——将用户信息存入session——响应前端——前端跳转

这个是我要告诉大家的姿势,还有很多很多的姿势。下面我们来看具体的代码。

首先前端验证,这里使用了jquery.validate来进行验证,jquery.validate的使用很简单,这里我们说说存js的方式:

$().ready(function() { 
 /**登录验证**/ 
 $("#login_form").validate({ 
  rules: { 
   loginAccount: "required", 
   loginPass: { 
    required: true, 
    minlength: 5 
   }, 
  }, 
  messages: { 
   loginAccount: "请输入姓名", 
   loginPass: { 
    required: "请输入密码", 
    minlength: jQuery.format("密码不能小于{0}个字 符") 
   }, 
  }, 
  submitHandler:function(form){ 
   $.ajax({ 
    dataType : "json", 
    url : "sysuser/login.action", 
    type : "post", 
    data : $("#login_form").serialize(), 
    success : function(data) { 
     $.alert(data.message); 
     if(data.success){ 
      window.location.href = 'page/main.action'; 
     } 
    }, 
    error : function (e){ 
     var d = e.responseJSON; 
     if(d){ 
      $.alert(d.message); 
     } 
    } 
   }); 
   return false; //阻止form提交 
  } 
 }); 
 /**注册验证**/ 
 $("#register_form").validate({ 
  rules: { 
   loginAccount:{ 
    required:true, 
    remote: { 
     url: "sysuser/getUserNameCount.action", 
     type: "post", 
     dataType: "json", 
     data: { 
      loginAccount: function () { 
       return $("#register_account").val(); 
      } 
     }, 
     dataFilter: function (data) {
//判断控制器返回的内容 
      data = jQuery.parseJSON(data); 
      return data.success; 
     } 
    } 
   }, 
   loginPass: { 
    required: true, 
    minlength: 5, 
    maxlength:20 
   }, 
   rloginPass: { 
    equalTo: "#register_password" 
   }, 
   userEmail: { 
    required: true, 
    email: true, 
    remote: { 
     url: "sysuser/getEMailCount.action", 
     type: "post", 
     dataType: "json", 
     data: { 
      email: function () { 
       return $("#register_email").val(); 
      } 
     }, 
     dataFilter: function (data) {

//判断控制器返回的内容 
      data = jQuery.parseJSON(data); 
      return data.success; 
     } 
    } 
   } 
  }, 
  messages: { 
   loginAccount:{ 
    required: "请输入姓名", 
    remote: "用户名已存在" 
   }, 
   loginPass: { 
    required: "请输入密码", 
    minlength: jQuery.format("密码不能小于{0}个字 符"), 
    maxlength: jQuery.format("密码不能大于{0}个字 符"), 
   }, 
   rloginPass: { 
    required: "请输入确认密码", 
    equalTo: "两次密码不一样" 
   }, 
   userEmail: { 
    required: "请输入邮箱", 
    email: "请输入有效邮箱", 
    remote: "邮箱已存在" 
   } 
  }, 
  submitHandler:function(form){ 
   $.ajax({ 
    dataType : "json", 
    url : "sysuser/register.action", 
    type : "post", 
    data : $("#register_form").serialize(), 
    success : function(data) { 
     $.alert(data.message); 
     if(data.success){ 
      window.location.href = 'page/main.action'; 
     } 
    }, 
    error : function (e){ 
     var d = e.responseJSON; 
     if(d){ 
      $.alert(d.message); 
     } 
    } 
   }); 
   return false; //阻止form提交 
  } 
 }); 
 /**隐藏显示登录注册**/ 
 $("#register_btn").click(function() { 
  $("#register_form").css("display", "block"); 
  $("#login_form").css("display", "none"); 
 }); 
 $("#back_btn").click(function() { 
  $("#register_form").css("display", "none"); 
  $("#login_form").css("display", "block"); 
 }); 
});

html页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 
<c:set var="contextPath" value="${pageContext.request.contextPath}"></c:set> 
<!DOCTYPE html> 
<html lang="en"> 
<head> 
<meta charset="utf-8"> 
<meta http-equiv="X-UA-Compatible" content="IE=edge"> 
<meta name="viewport" content="width=device-width, initial-scale=1"> 
<meta name="description" content=""> 
<meta name="author" content=""> 
<title>主页</title> 
<!-- Bootstrap core CSS --> 
<link href="${contextPath }/static/bootstrap/css/bootstrap.min.css" rel="external nofollow" rel="stylesheet"> 
<link href="${contextPath }/static/bootstrap/css/font-awesome.min.css" rel="external nofollow" rel="stylesheet"> 
<link href="${contextPath }/static/alert/jquery-confirm.min.css" rel="external nofollow" rel="stylesheet"> 
<style type="text/css"> 
body { 
 background: url(${contextPath }/static/img/login/bg.jpg) no-repeat; 
 background-size: cover; 
 font-size: 16px; 
} 
.form { 
 background: rgba(255, 255, 255, 0.2); 
 width: 400px; 
 margin: 100px auto; 
} 
#login_form { 
 display: block; 
} 
#register_form { 
 display: none; 
} 
.fa { 
 display: inline-block; 
 top: 27px; 
 left: 6px; 
 position: relative; 
 color: #ccc; 
} 
input[type="text"], input[type="password"] { 
 padding-left: 26px; 
} 
.checkbox { 
 padding-left: 21px; 
} 
</style> 
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> 
<!--[if lt IE 9]> 
  <script src="${contextPath }/static/bootstrap/html5shiv/html5shiv.js"></script> 
  <script src="${contextPath }/static/bootstrap/respond/respond.min.js"></script> 
 <![endif]--> 
</head> 
<body> 
 <div class="container"> 
  <div class="form row"> 
   <form class="form-horizontal col-sm-offset-3 col-md-offset-3" id="login_form"> 
    <h3 class="form-title">登录</h3> 
    <div class="col-sm-9 col-md-9"> 
     <div class="form-group"> 
      <i class="fa fa-user fa-lg"></i> <input 
       class="form-control required" type="text" placeholder="请输入账号" 
       name="loginAccount" autofocus="autofocus" maxlength="20" /> 
     </div> 
     <div class="form-group"> 
      <i class="fa fa-lock fa-lg"></i> <input 
       class="form-control required" type="password" 
       placeholder="请输入密码" name="loginPass" maxlength="8" /> 
     </div> 
     <div class="form-group"> 
      <label class="checkbox"> <input type="checkbox" 
       name="rememberMe" value="1" /> 记住我 
      </label> 
      <hr /> 
      <a href="javascript:;" rel="external nofollow" id="register_btn" class="">注册?</a> 
     </div> 
     <div class="form-group"> 
      <input type="submit" class="btn btn-success pull-right" value="登录 " /> 
     </div> 
    </div> 
   </form> 
  </div> 
  <div class="form row"> 
   <form class="form-horizontal col-sm-offset-3 col-md-offset-3" id="register_form"> 
    <h3 class="form-title">注册</h3> 
    <div class="col-sm-9 col-md-9"> 
     <div class="form-group"> 
      <i class="fa fa-user fa-lg"></i> <input 
       class="form-control required" type="text" placeholder="请输入账号" 
       name="loginAccount" autofocus="autofocus" id="register_account" /> 
     </div> 
     <div class="form-group"> 
      <i class="fa fa-lock fa-lg"></i> <input 
       class="form-control required" type="password" 
       placeholder="请输入密码" id="register_password" name="loginPass" /> 
     </div> 
     <div class="form-group"> 
      <i class="fa fa-check fa-lg"></i> <input 
       class="form-control required" type="password" 
       placeholder="请输入确认密码" name="rloginPass" /> 
     </div> 
     <div class="form-group"> 
      <i class="fa fa-envelope fa-lg"></i> <input 
       class="form-control eamil" type="text" placeholder="Email" 
       name="userEmail" id="register_email"/> 
     </div> 
     <div class="form-group"> 
      <input type="submit" class="btn btn-success pull-right" 
       value="注册" /> <input type="submit" 
       class="btn btn-info pull-left" id="back_btn" value="返回" /> 
     </div> 
    </div> 
   </form> 
  </div> 
 </div> 
 <script type="text/javascript" src="${contextPath }/static/jquery/jquery.min.js"></script> 
 <script type="text/javascript" src="${contextPath }/static/bootstrap/js/bootstrap.min.js"></script> 
 <script type="text/javascript" src="${contextPath }/static/alert/jquery-confirm.min.js" ></script> 
 <script type="text/javascript" src="${contextPath }/static/jquery/jquery.validate.min.js" ></script> 
 <script type="text/javascript" src="${contextPath }/static/login/login.js" ></script> 
</body> 
</html>

$("#login_form").validate({...})方法中,login_form为你要验证的form的id;rules为要验证的字段;messages为要提示的内容,如果不填写,则会提示默认信息;submitHandler为点击提交(submit)按钮后的回调方法,这里面最后的return false是为了阻止form表单的提交,因为我这里要用ajax的方式提交;在注册中的loginAccount字段有一个属性remote这个是为了做ajax验证的,在没有提交表单之前,我们就验证用户输入的用户名是否在系统中已经存在。

我们在编程总,发现总是会有那么几个方法在相同的代码层总用到,比如在控制层中获取用户session,或者输出响应信息等;在dao层中调用Hibernate的save方法,update方法,delete方法等。所以我们应该在框架搭建的初期去建立一些通用的工具类或者是Base方法,下面我们新建BaseController方法,并且让后面的控制器都来继承它。

import java.io.IOException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 
import org.springframework.web.bind.annotation.ModelAttribute; 
import com.fasterxml.jackson.core.JsonEncoding; 
import com.fasterxml.jackson.core.JsonFactory; 
import com.fasterxml.jackson.core.JsonGenerator; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import yfkj.gz.task.entity.SysUser; 
import yfkj.gz.task.util.Result; 
/** 
 * 父类控制器 
 * @author 胡汉三 
 * @date 2017年1月9日 下午5:23:52 
 */ 
@SuppressWarnings("deprecation") 
public class BaseController{ 
 public static final String USER_SESSION = "USER_SESSION"; 
 protected static ObjectMapper mapper = new ObjectMapper(); 
 protected static JsonFactory factory = mapper.getJsonFactory(); 
 protected static Result result = new Result(); 
 protected HttpServletRequest request; 
 protected HttpServletResponse response; 
 protected HttpSession session; 
 @ModelAttribute 
 public void setReqAndRes(HttpServletRequest request, HttpServletResponse response){ 
  this.request = request; 
  this.response = response; 
  this.session = request.getSession(); 
 } 
 /**将json字符串输出**/ 
 protected void writeJSON(String json) throws IOException { 
  response.setContentType("text/html;charset=utf-8"); 
  response.getWriter().write(json); 
 } 
 /**将对象转成json输出**/ 
 protected void writeJSON(Object obj) throws IOException { 
  response.setContentType("text/html;charset=utf-8"); 
  JsonGenerator responseJsonGenerator = factory.createJsonGenerator(response.getOutputStream(), JsonEncoding.UTF8); 
  responseJsonGenerator.writeObject(obj); 
 } 
 /** 
  * 获得session用户对象 
  * @return 
  */ 
 protected SysUser getUser(){ 
  Object userObj = session.getAttribute(USER_SESSION); 
  if(userObj == null){ 
   return null; 
  } 
  return (SysUser)userObj; 
 } 
}

用户的控制器SysUserController:

package yfkj.gz.task.controller; 
import java.io.IOException; 
import java.util.Date; 
import java.util.List; 
import javax.annotation.Resource; 
import org.apache.shiro.SecurityUtils; 
import org.apache.shiro.authc.UsernamePasswordToken; 
import org.apache.shiro.crypto.hash.Sha256Hash; 
import org.apache.shiro.subject.Subject; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import yfkj.gz.task.entity.SysRole; 
import yfkj.gz.task.entity.SysUser; 
import yfkj.gz.task.service.ISysRoleService; 
import yfkj.gz.task.service.ISysUserService; 
import yfkj.gz.task.util.DateUtil; 
import yfkj.gz.task.util.StringUtils; 
import yfkj.gz.support.BTView; 
import yfkj.gz.support.controller.BaseController; 
/** 
 * 用户控制器 
 * @author 胡汉三 
 * @date 2017年1月16日 下午2:31:39 
 */ 
@Controller 
@RequestMapping("/sysuser") 
public class SysUserController extends BaseController{ 
 @Resource 
 private ISysUserService userService; 
 @Resource 
 private ISysRoleService roleService; 
 /** 
  * 分页查询用户 
  * @param response 
  * @param user 
  * @param btView 
  * @throws IOException 
  */ 
 @RequestMapping(value = "/findUser", method = { RequestMethod.POST, RequestMethod.GET }) 
 public void findUser(SysUser user,BTView<SysUser> btView) throws IOException{ 
  List<SysUser> list = userService.findSysUserPage(btView, null); 
  btView.setRows(list); 
  super.writeJSON(btView); 
 } 
 /** 
  * 用户登录 
  * @param response 
  * @param user 
  * @throws IOException 
  */ 
 @RequestMapping(value = "/login", method = { RequestMethod.POST, RequestMethod.GET }) 
 public void login(SysUser user,boolean rememberMe) throws IOException{ 
  //用户登录 
  SysUser userInfo = userService.getByProerties(new String[]{"loginAccount"}, new String[]{user.getLoginAccount()},null); 
  if(userInfo==null){ 
   result.setMessage("用户名错误"); 
   super.writeJSON(result); 
   return; 
  } 
  if(!userInfo.getLoginPass().equals(new Sha256Hash(user.getLoginPass()).toHex())){ 
   result.setMessage("密码错误"); 
   super.writeJSON(result); 
   return; 
  } 
  //存入session 
  Subject subject = SecurityUtils.getSubject(); 
  //记得传入明文密码 
  subject.login(new UsernamePasswordToken(userInfo.getLoginAccount(), user.getLoginPass(), rememberMe)); 
  session.setAttribute(USER_SESSION, userInfo); 
  result.setMessage("登录成功"); 
  result.setSuccess(true); 
  super.writeJSON(result); 
 } 
 /** 
  * 用户注册 
  * @param response 
  * @param user 
  * @throws IOException 
  */ 
 @RequestMapping(value = "/register", method = { RequestMethod.POST, RequestMethod.GET }) 
 public void register(SysUser user) throws IOException{ 
  Long count = userService.getCountByProerties(new String[]{"loginAccount"}, new String[]{user.getLoginAccount()}); 
  if(count>0){ 
   result.setMessage("账号已存在"); 
   super.writeJSON(result); 
   return; 
  } 
  Long countEmail = userService.getCountByProerties(new String[]{"userEmail"}, new String[]{user.getUserEmail()}); 
  if(countEmail>0){ 
   result.setMessage("邮箱已存在"); 
   super.writeJSON(result); 
   return; 
  } 
  try{ 
   //注册时间 
   user.setRegisterTime(DateUtil.getDateTime(new Date())); 
   //Sha256Hash加密 
   user.setLoginPass(new Sha256Hash(user.getLoginPass()).toHex()); 
   //默认为注册用户 
   SysRole role = roleService.getByProerties(new String[]{"roleKey"},new String[]{"ROLE_USER"},null); 
   user.getRoles().add(role); 
   userService.save(user); 
   //存入session 
   Subject subject = SecurityUtils.getSubject(); 
   subject.login(new UsernamePasswordToken(user.getLoginAccount(), user.getLoginPass())); 
   session.setAttribute(USER_SESSION, user); 
   result.setMessage("注册成功"); 
   result.setSuccess(true); 
  }catch(Exception e){ 
   result.setMessage("注册失败"); 
  } 
  super.writeJSON(result); 
 } 
 /** 
  * 判断用户账号是否已存在 
  * @param response 
  * @param user 
  * @throws IOException 
  */ 
 @RequestMapping(value = "/getUserNameCount", method = { RequestMethod.POST, RequestMethod.GET }) 
 public void getUserNameCount(String loginAccount) throws IOException{ 
  result.setSuccess(false); 
  if(StringUtils.isBlank(loginAccount)){ 
   result.setMessage("账号不能为空"); 
   super.writeJSON(result); 
   return; 
  } 
  Long count = userService.getCountByProerties(new String[]{"loginAccount"}, new String[]{loginAccount}); 
  if(count>0){ 
   result.setMessage("账号已存在"); 
  }else{ 
   result.setSuccess(true); 
   result.setMessage("该账号可用"); 
  } 
  super.writeJSON(result); 
 } 
 /** 
  * 判断用户邮箱是否已存在 
  * @param response 
  * @param email 
  * @throws IOException 
  */ 
 @RequestMapping(value = "/getEMailCount", method = { RequestMethod.POST, RequestMethod.GET }) 
 public void getEMailCount(String email) throws IOException{ 
  result.setSuccess(false); 
  if(StringUtils.isBlank(email)){ 
   result.setMessage("邮箱不能为空"); 
   super.writeJSON(result); 
   return; 
  } 
  Long count = userService.getCountByProerties(new String[]{"userEmail"}, new String[]{email}); 
  if(count>0){ 
   result.setMessage("邮箱已存在"); 
  }else{ 
   result.setSuccess(true); 
   result.setMessage("该邮箱可用"); 
  } 
  super.writeJSON(result); 
 } 
 // 登出 
 @RequestMapping("/logout") 
 public void logout() throws IOException { 
  //退出权限验证 
  SecurityUtils.getSubject().logout(); 
  //销毁session 
  session.invalidate(); 
  response.sendRedirect(request.getContextPath()+"/login.jsp"); 
 } 
}

至此,登录跟注册就OK啦!

Spring shiro + bootstrap + jquery.validate 实现登录、注册功能
Spring shiro + bootstrap + jquery.validate 实现登录、注册功能

其中还使用到啦jquery-confirm.js,这是一个弹出框的插件:点击查看

源码地址:https://git.oschina.net/gzsjd/task

以上所述是小编给大家介绍的Spring shiro + bootstrap + jquery.validate 实现登录、注册功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

jQuery 相关文章推荐
jQuery实现动态添加、删除按钮及input输入框的方法
Apr 27 jQuery
jQuery获取table表中的td标签(实例讲解)
Jul 28 jQuery
jQuery Layer弹出层传值到父页面的实现代码
Aug 17 jQuery
原生JS与jQuery编写简单选项卡
Oct 30 jQuery
jquery自定义显示消息数量
Dec 19 jQuery
jQuery实现鼠标移到某个对象时弹出显示层功能
Aug 23 jQuery
jquery实现自定义树形表格的方法【自定义树形结构table】
Jul 12 jQuery
基于jQuery实现可编辑的表格
Dec 11 jQuery
jQuery实现颜色打字机的完整代码
Mar 19 jQuery
jQuery中getJSON跨域原理的深入讲解
Sep 02 jQuery
jQuery实现简单评论区功能
Oct 26 jQuery
jquery实现加载更多&quot;转圈圈&quot;效果(示例代码)
Nov 09 jQuery
详解如何在 vue 项目里正确地引用 jquery 和 jquery-ui的插件
Jun 01 #jQuery
jQuery实现web页面樱花坠落的特效
Jun 01 #jQuery
jquery网页加载进度条的实现
Jun 01 #jQuery
jQuery+Ajax实现用户名重名实时检测
Jun 01 #jQuery
jQuery实现动态删除LI的方法
May 30 #jQuery
jQuery异步提交表单实例
May 30 #jQuery
Angular2使用jQuery的方法教程
May 28 #jQuery
You might like
PHP生成二维码的两个方法和实例
2014/07/01 PHP
简单解析PHP程序的运行流程
2016/06/23 PHP
Javascript操作select方法大全[新增、修改、删除、选中、清空、判断存在等]
2008/09/26 Javascript
用JavaScript将从数据库中读取出来的日期型格式化为想要的类型。
2009/08/15 Javascript
JavaScript 事件的一些重要说明
2009/10/25 Javascript
Jquery刷新页面背景图片随机变换的实现方法
2013/03/15 Javascript
JavaScript利用构造函数和原型的方式模拟C#类的功能
2014/03/06 Javascript
JS清除选择内容的方法
2015/01/29 Javascript
javascript模拟C#格式化字符串
2015/08/26 Javascript
Bootstrap树形组件jqTree的简单封装
2016/01/25 Javascript
JavaScript中各种引用类型的常用操作方法小结
2016/05/05 Javascript
JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解
2016/05/31 Javascript
vue2.0+webpack环境的构造过程
2016/11/08 Javascript
深入了解JavaScript的逻辑运算符(与、或)
2016/12/20 Javascript
Vue中添加过渡效果的方法
2017/03/16 Javascript
关于echarts在节点显示动态数据及添加提示文本所遇到的问题
2018/04/20 Javascript
使用vue-router beforEach实现判断用户登录跳转路由筛选功能
2018/06/25 Javascript
React router动态加载组件之适配器模式的应用详解
2018/09/12 Javascript
Vue CLI3搭建的项目中路径相关问题的解决
2018/09/17 Javascript
Vue props 单向数据流的实现
2018/11/06 Javascript
小程序按钮避免多次调用接口和点击方案实现(不用showLoading)
2020/04/15 Javascript
python将人民币转换大写的脚本代码
2013/02/10 Python
Python实现把回车符\r\n转换成\n
2015/04/23 Python
Python的Django框架下管理站点的基本方法
2015/07/17 Python
python 时间戳与格式化时间的转化实现代码
2016/03/23 Python
对python 数据处理中的LabelEncoder 和 OneHotEncoder详解
2018/07/11 Python
python斐波那契数列的计算方法
2018/09/27 Python
四年的个人工作自我评价
2013/12/10 职场文书
大学生作弊检讨书
2014/09/11 职场文书
2014年法院个人工作总结
2014/12/17 职场文书
人事局接收函
2015/01/30 职场文书
毕业设计论文致谢词
2015/05/14 职场文书
神秘岛读书笔记
2015/07/01 职场文书
《总之就是很可爱》新作短篇动画《总之就是很可爱~制服~》将于2022年夏天播出
2022/04/07 日漫
科学家测试在太空中培育人造肉,用于未来太空旅行
2022/04/29 数码科技
详解OpenCV获取高动态范围(HDR)成像
2022/04/29 Python