您的位置:首页 > Web前端 > BootStrap

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

2017-01-16 00:00 1031 查看

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

现在我们开始实现登录功能,这个可以说是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 实现登录、注册功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

您可能感兴趣的文章:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息