이 글은 로그인 및 등록 기능을 구현하기 위한 Spring shiro + bootstrap + jquery.validate를 주로 소개합니다. 필요한 친구들이 참고하면 좋겠습니다.
이전 글에서는 이미 프레임워크를 구축하고 데이터베이스를 설계했습니다.
이제 웹 애플리케이션의 가장 일반적인 기능이라고 할 수 있는 로그인 기능을 구현하기 시작합니다.
먼저 로그인 로직에 대해 이야기해 보겠습니다.
사용자 이름과 비밀번호를 입력합니다(프런트 엔드 확인을 위해 유효성 검사) - ajax는 백그라운드 작업 메서드를 호출합니다. - 사용자 이름에 따라 비즈니스 계층을 데이터 계층으로 호출하여 쿼리합니다. 데이터베이스 정보 - 쿼리 비밀번호 사용자가 입력한 비밀번호와 비교 - 시로 로그인 인증 - 세션 내 사용자 정보 저장 - 프런트엔드 응답 - 프런트엔드 점프
이것이 제가 말씀드리고 싶은 자세이고, 여러 가지가 있습니다 , 많은 자세. 아래의 구체적인 코드를 살펴보겠습니다.
첫 번째, 여기에서는 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> <p class="container"> <p class="form row"> <form class="form-horizontal col-sm-offset-3 col-md-offset-3" id="login_form"> <h3 class="form-title">登录</h3> <p class="col-sm-9 col-md-9"> <p 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" /> </p> <p class="form-group"> <i class="fa fa-lock fa-lg"></i> <input class="form-control required" type="password" placeholder="请输入密码" name="loginPass" maxlength="8" /> </p> <p 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> </p> <p class="form-group"> <input type="submit" class="btn btn-success pull-right" value="登录 " /> </p> </p> </form> </p> <p class="form row"> <form class="form-horizontal col-sm-offset-3 col-md-offset-3" id="register_form"> <h3 class="form-title">注册</h3> <p class="col-sm-9 col-md-9"> <p 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" /> </p> <p class="form-group"> <i class="fa fa-lock fa-lg"></i> <input class="form-control required" type="password" placeholder="请输入密码" id="register_password" name="loginPass" /> </p> <p class="form-group"> <i class="fa fa-check fa-lg"></i> <input class="form-control required" type="password" placeholder="请输入确认密码" name="rloginPass" /> </p> <p 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"/> </p> <p 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="返回" /> </p> </p> </form> </p> </p> <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은 확인하려는 양식의 ID입니다. 규칙은 확인할 필드입니다. 채워지지 않으면 submitHandler는 제출 버튼을 클릭한 후의 콜백 메소드입니다. 여기서는 ajax를 사용하여 양식을 제출하려고 하기 때문에 false를 반환합니다. 등록의 loginAccount 필드에 있는 속성은 Ajax 확인을 위한 것입니다. 양식을 제출하기 전에 사용자가 입력한 사용자 이름이 시스템에 이미 존재하는지 확인합니다.
프로그래밍을 할 때 제어 계층에서 사용자 세션을 얻거나 dao 계층에서 Hibernate의 저장 메서드를 호출하는 등 항상 여러 메서드가 동일한 코드 계층에서 사용된다는 것을 알게 됩니다. 업데이트 방법, 삭제 방법 등 따라서 프레임워크 구성의 초기 단계에서 몇 가지 공통 도구 클래스 또는 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도 사용됩니다. 보려면 클릭하세요.
관련 권장 사항:
vue는 로그인 후 이전 페이지로 페이지 이동을 구현합니다. 예제 공유
새로 고침 없는 로그인 기능을 구현하는 AJAX 메서드
vue 경로가 점프할 때 사용자가 로그인했는지 여부를 판단합니다
위 내용은 Spring shiro bootstrap 로그인 및 등록 기능의 jquery.validate 구현 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!