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实现字体颜色渐变效果的方法
Mar 29 jQuery
jQuery实现简单漂亮的Nav导航菜单效果
Mar 29 jQuery
jQuery Jsonp跨域模拟搜索引擎
Jun 17 jQuery
JQuery选中select组件被选中的值方法
Mar 08 jQuery
jQuery使用动画队列自定义动画操作示例
Jun 16 jQuery
jQuery的Ajax接收java返回数据方法
Aug 11 jQuery
jQuery利用FormData上传文件实现批量上传
Dec 04 jQuery
使用jQuery mobile NuGet让你的网站在移动设备上同样精彩
Jun 18 jQuery
jquery图片预览插件实现方法详解
Jul 18 jQuery
jQuery Datatables 动态列+跨列合并实现代码
Jan 30 jQuery
jquery实现简单拖拽效果
Jul 20 jQuery
jQuery实现移动端扭蛋机抽奖
Nov 08 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
德生BCL3000的电路分析和打磨
2021/03/02 无线电
file_get_contents(&quot;php://input&quot;, &quot;r&quot;)实例介绍
2013/07/01 PHP
php float不四舍五入截取浮点型字符串方法总结
2013/10/28 PHP
php eval函数一句话木马代码
2015/05/21 PHP
PHP获取星期几的常用方法小结
2018/12/18 PHP
Laravel 将数据表的数据导出,并生成seeds种子文件的方法
2019/10/09 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
2020/02/22 PHP
js常用函数 不错
2006/09/08 Javascript
关于juqery radio写法的兼容性问题(新老版本jquery)
2010/06/14 Javascript
jQuery-Tools-overlay 使用介绍
2012/07/14 Javascript
Javascript学习笔记之数组的遍历和 length 属性
2014/11/23 Javascript
Bootstrap组件系列之福利篇几款好用的组件(推荐)
2016/06/23 Javascript
Jquery通过ajax请求NodeJS返回json数据实例
2016/11/08 NodeJs
etmvc+jQuery EasyUI+combobox多值操作实现角色授权实例
2016/11/09 Javascript
js仿微信语音播放实现思路
2016/12/12 Javascript
Ionic + Angular.js实现图片轮播的方法示例
2017/05/21 Javascript
详解Angular系列之变化检测(Change Detection)
2018/02/26 Javascript
详解解决使用axios发送json后台接收不到的问题
2018/06/27 Javascript
Angular项目如何升级至Angular6步骤全纪录
2018/09/03 Javascript
微信小程序封装分享与分销功能过程解析
2019/08/13 Javascript
vue+axios实现post文件下载
2019/09/25 Javascript
JavaScript实现左右滚动电影画布
2020/02/06 Javascript
JavaScript中while循环的基础使用教程
2020/08/11 Javascript
vue使用canvas实现移动端手写签名
2020/09/22 Javascript
Python中的左斜杠、右斜杠(正斜杠和反斜杠)
2016/08/30 Python
Python使用迭代器捕获Generator返回值的方法
2017/04/05 Python
对Python中DataFrame按照行遍历的方法
2018/04/08 Python
基于MSELoss()与CrossEntropyLoss()的区别详解
2020/01/02 Python
Python 实现RSA加解密文本文件
2020/12/30 Python
android面试问题与答案
2016/12/27 面试题
升职自荐信
2013/11/28 职场文书
教师自我反思材料
2014/02/14 职场文书
技术合作协议书范本
2014/04/18 职场文书
学校食堂标语
2014/10/06 职场文书
校车安全管理责任书
2015/05/11 职场文书
导游词之天津古文化街
2019/11/09 职场文书