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插件FusionCharts实现的3D帕累托图效果示例【附demo源码】
Mar 25 jQuery
jQuery中的deferred使用方法
Mar 27 jQuery
jquery实现图片轮播器
May 23 jQuery
jQuery实现动态删除LI的方法
May 30 jQuery
jQuery复合事件用法示例
Jun 10 jQuery
基于jquery实现多选下拉列表
Aug 02 jQuery
jQuery条件分页 代替离线查询(附代码)
Aug 17 jQuery
jQuery实现的简单图片轮播效果完整示例
Feb 08 jQuery
jQuery发请求传输中文参数乱码问题的解决方案
May 22 jQuery
jQuery ajax仿Google自动提示SearchSuggess功能示例
Mar 28 jQuery
详解jQuery设置内容和属性
Apr 11 jQuery
js/jQuery实现全选效果
Jun 17 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文件
2007/01/04 PHP
教你如何用php实现LOL数据远程获取
2014/06/10 PHP
php实现的双向队列类实例
2014/09/24 PHP
php上传大文件设置方法
2016/04/14 PHP
PHP二维数组去重算法
2016/12/17 PHP
在PHP中输出JS语句以及乱码问题的解决方案
2019/02/13 PHP
学习ExtJS(二) Button常用方法
2009/10/07 Javascript
jquery实现通用的内容渐显Tab选项卡效果
2015/09/07 Javascript
基于JavaScript实现一定时间后去执行一个函数
2015/12/14 Javascript
AngularJS实现在ng-Options加上index的解决方法
2016/11/03 Javascript
Vue.js 2.0 移动端拍照压缩图片上传预览功能
2017/03/06 Javascript
js+canvas实现滑动拼图验证码功能
2018/03/26 Javascript
一个简单的node.js界面实现方法
2018/06/01 Javascript
浅谈Vue初学之props的驼峰命名
2018/07/19 Javascript
微信小程序实现单选选项卡切换效果
2020/06/19 Javascript
微信小程序云开发 搭建一个管理小程序
2019/05/17 Javascript
JS实现压缩上传图片base64长度功能
2019/12/03 Javascript
Python实现全角半角字符互转的方法
2016/11/28 Python
Python2实现的图片文本识别功能详解
2018/07/11 Python
python实现泊松图像融合
2018/07/26 Python
解决python通过cx_Oracle模块连接Oracle乱码的问题
2018/10/18 Python
详解python uiautomator2 watcher的使用方法
2019/09/09 Python
Python基于DB-API操作MySQL数据库过程解析
2020/04/23 Python
Python通过队列来实现进程间通信的示例
2020/10/14 Python
eDreams意大利:南欧领先的在线旅行社
2018/11/23 全球购物
成人毕业生自我鉴定
2013/10/18 职场文书
大队干部竞选演讲稿
2014/04/28 职场文书
团队精神的演讲稿
2014/05/14 职场文书
药剂专业毕业生求职信
2014/06/24 职场文书
教师个人读书活动总结
2014/07/08 职场文书
餐饮周年庆活动方案
2014/08/14 职场文书
党员四风问题个人对照检查材料
2014/10/26 职场文书
英文邀请函
2015/02/02 职场文书
超市督导岗位职责
2015/04/10 职场文书
创业计划书之闲置物品置换中心
2019/12/25 职场文书
MySQL 使用SQL语句修改表名的实现
2021/04/07 MySQL