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

时间:2019-03-30
本文章向大家介绍Spring shiro + bootstrap + jquery.validate 实现登录、注册功能,主要包括Spring shiro + bootstrap + jquery.validate 实现登录、注册功能使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

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

现在我们开始实现登录功能,这个可以说是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啦!


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

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

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