Spring shiro + bootstrap + jquery.validate 登录、注册

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hzw2312/article/details/54616653

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

现在我们开始实现登录功能,这个可以说是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="stylesheet">
<link href="${contextPath }/static/bootstrap/css/font-awesome.min.css" rel="stylesheet">
<link href="${contextPath }/static/alert/jquery-confirm.min.css" 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:;" 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验证的,在没有提交表单之前,我们就验证用户输入的用户名是否在系统中已经存在。

更多validate的内容请看:http://www.runoob.com/jquery/jquery-plugin-validate.html

我们在编程总,发现总是会有那么几个方法在相同的代码层总用到,比如在控制层中获取用户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





猜你喜欢

转载自blog.csdn.net/hzw2312/article/details/54616653