这里写目录标题

  • 一、演示GIF
  • 二、开发前期准备
    • 1、数据库
    • 2、依赖POM.XML
    • 3、idea结构目录
  • 三、后端
    • 1、实体类
    • 2、mapper接口
    • 3、mapper.xml
    • 4、Servicce接口
    • 5、Impl实现
    • 6、Controller控制器
    • 7、全局异常处理类
      • GlobalException
      • GlobalExceptionHandler
    • 8、工具类
      • MD5Util
      • UUIDUtil
      • CookieUtil
      • ValidatorUtil
    • 9、手机号处理类
      • validator
      • IsMobileValidator
    • 10、Vo类
      • LoginVo
      • RespBean
      • RespBeanEnum
  • 四、前端
    • login.html
    • list.html

一、演示GIF


本文通过SpringBoot+2次MD5登录密码加密+MyBatisPlus+Thymeleaf+bootstrap简单实现登录功能

  • 登录时手机号作为账号有验证
  • 密码作为2次MD5加密
  • MybatisPlus开发时方便 高效
  • Bootstrap作为前端框架

二、开发前期准备

1、数据库

CREATE TABLE `t_user` (`id` bigint(20) NOT NULL COMMENT '用户ID shoujihaoma',`nickname` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,`pasword` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'MD5二次加密',`slat` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`head` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '头像',`register_date` datetime DEFAULT NULL COMMENT '注册时间',`last_login_date` datetime DEFAULT NULL COMMENT '最后一次登录时间',`login_count` int(11) DEFAULT '0' COMMENT '登录次数',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

2、依赖POM.XML

  <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!--        mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--        MD5依赖--><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId></dependency><!--   validation   参数校验-->`在这里插入代码片`<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>

3、idea结构目录

三、后端

1、实体类

package com.seckilldemo.pojo;import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.io.Serializable;
import java.util.Date;/*** <p>** </p>** @author syj* @since 2023-01-14*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_user")
public class User implements Serializable {private static final long serialVersionUID = 1L;/*** 用户ID shoujihaoma*/private Long id;private String nickname;/*** MD5二次加密*/private String pasword;private String slat;/*** 头像*/private String head;/*** 注册时间*/private Date registerDate;/*** 最后一次登录时间*/private Date lastLoginDate;/*** 登录次数*/private Integer loginCount;}

2、mapper接口

package com.seckilldemo.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.seckilldemo.pojo.User;/*** <p>*  Mapper 接口* </p>** @author syj* @since 2023-01-14*/
public interface UserMapper extends BaseMapper<User> {}

3、mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.seckilldemo.mapper.UserMapper"><!-- 通用查询映射结果 --><resultMap id="BaseResultMap" type="com.seckilldemo.pojo.User"><id column="id" property="id" /><result column="nickname" property="nickname" /><result column="pasword" property="pasword" /><result column="slat" property="slat" /><result column="head" property="head" /><result column="register_date" property="registerDate" /><result column="last_login_date" property="lastLoginDate" /><result column="login_count" property="loginCount" /></resultMap><!-- 通用查询结果列 --><sql id="Base_Column_List">id, nickname, pasword, slat, head, register_date, last_login_date, login_count</sql></mapper>

4、Servicce接口

package com.seckilldemo.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.seckilldemo.pojo.User;
import com.seckilldemo.vo.LoginVo;
import com.seckilldemo.vo.RespBean;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** <p>*  服务类* </p>** @author syj* @since 2023-01-14*/
public interface IUserService extends IService<User> {RespBean doLogin(LoginVo loginVo, HttpServletResponse response, HttpServletRequest request);
}

5、Impl实现

package com.seckilldemo.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.seckilldemo.exception.GlobalException;
import com.seckilldemo.mapper.UserMapper;
import com.seckilldemo.pojo.User;
import com.seckilldemo.service.IUserService;
import com.seckilldemo.utils.CookieUtil;
import com.seckilldemo.utils.MD5Util;
import com.seckilldemo.utils.UUIDUtil;
import com.seckilldemo.utils.ValidatorUtil;
import com.seckilldemo.vo.LoginVo;
import com.seckilldemo.vo.RespBean;
import com.seckilldemo.vo.RespBeanEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.StringUtils;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** <p>*  服务实现类* </p>** @author syj* @since 2023-01-14*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Autowiredprivate UserMapper userMapper;@Overridepublic RespBean doLogin(LoginVo loginVo, HttpServletResponse response, HttpServletRequest request){String mobile = loginVo.getMobile();String password = loginVo.getPassword();
//        if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)){//            return RespBean.error(RespBeanEnum.LOGIN_ERROR);
//        }
//        if(!ValidatorUtil.isMobile(mobile)){//            return RespBean.error(RespBeanEnum.MOBILE_ERROR);
//        }User user = userMapper.selectById(mobile);//根据手机号获取用户if (null == user){throw new GlobalException(RespBeanEnum.LOGIN_ERROR);}//判断密码是否正确if(!MD5Util.fromPassToDBPass(password,user.getSlat()).equals(user.getPasword())){throw new GlobalException(RespBeanEnum.LOGIN_ERROR);}//生成cokieString ticket = UUIDUtil.uuid();request.getSession().setAttribute(ticket,user);CookieUtil.setCookie(request,response,"userTicket",ticket);return RespBean.success();}
}

6、Controller控制器

package com.seckilldemo.controller;import com.seckilldemo.service.IUserService;
import com.seckilldemo.utils.ValidatorUtil;
import com.seckilldemo.vo.LoginVo;
import com.seckilldemo.vo.RespBean;
import com.seckilldemo.vo.RespBeanEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.util.StringUtils;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;@Controller
@RequestMapping("/login")
@Slf4j
public class LoginController {@Autowiredprivate IUserService userService;@RequestMapping("/toLogin")public String toLogin(){return "login";}@RequestMapping("/doLogin")@ResponseBodypublic RespBean doLogin(@Valid LoginVo loginVo, HttpServletRequest request, HttpServletResponse response){return userService.doLogin(loginVo,response,request);}}

7、全局异常处理类

  • GlobalException

package com.seckilldemo.exception;import com.seckilldemo.vo.RespBean;
import com.seckilldemo.vo.RespBeanEnum;/*** 全局异常** @author: LC* @date 2022/3/2 5:32 下午* @ClassName: GlobalException*/
public class GlobalException extends RuntimeException {private RespBeanEnum respBeanEnum;public RespBeanEnum getRespBeanEnum() {return respBeanEnum;}public void setRespBeanEnum(RespBeanEnum respBeanEnum) {this.respBeanEnum = respBeanEnum;}public GlobalException(RespBeanEnum respBeanEnum) {this.respBeanEnum = respBeanEnum;}
}
  • GlobalExceptionHandler

package com.seckilldemo.exception;import com.seckilldemo.vo.RespBean;
import com.seckilldemo.vo.RespBeanEnum;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** 全局异常处理类** @author: LC* @date 2022/3/2 5:33 下午* @ClassName: GlobalExceptionHandler*/
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public RespBean ExceptionHandler(Exception e) {if (e instanceof GlobalException) {GlobalException exception = (GlobalException) e;return RespBean.error(exception.getRespBeanEnum());} else if (e instanceof BindException) {BindException bindException = (BindException) e;RespBean respBean = RespBean.error(RespBeanEnum.BIND_ERROR);respBean.setMessage("参数校验异常:" + bindException.getBindingResult().getAllErrors().get(0).getDefaultMessage());return respBean;}System.out.println("异常信息" + e);return RespBean.error(RespBeanEnum.ERROR);}
}

8、工具类

  • CookieUtil
package com.seckilldemo.utils;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;/*** Cookie工具类** @author: LC* @date 2022/3/2 5:48 下午* @ClassName: CookieUtil*/
public final class CookieUtil {/*** 得到Cookie的值, 不编码** @param request* @param cookieName* @return*/public static String getCookieValue(HttpServletRequest request, String cookieName) {return getCookieValue(request, cookieName, false);}/*** 得到Cookie的值,** @param request* @param cookieName* @return*/public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {Cookie[] cookieList = request.getCookies();if (cookieList == null || cookieName == null) {return null;}String retValue = null;try {for (int i = 0; i < cookieList.length; i++) {if (cookieList[i].getName().equals(cookieName)) {if (isDecoder) {retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");} else {retValue = cookieList[i].getValue();}break;}}} catch (UnsupportedEncodingException e) {e.printStackTrace();}return retValue;}/*** 得到Cookie的值,** @param request* @param cookieName* @return*/public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {Cookie[] cookieList = request.getCookies();if (cookieList == null || cookieName == null) {return null;}String retValue = null;try {for (int i = 0; i < cookieList.length; i++) {if (cookieList[i].getName().equals(cookieName)) {retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);break;}}} catch (UnsupportedEncodingException e) {e.printStackTrace();}return retValue;}/*** 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue) {setCookie(request, response, cookieName, cookieValue, -1);}/*** 设置Cookie的值 在指定时间内生效,但不编码*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue, int cookieMaxage) {setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);}/*** 设置Cookie的值 不设置生效时间,但编码*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue, boolean isEncode) {setCookie(request, response, cookieName, cookieValue, -1, isEncode);}/*** 设置Cookie的值 在指定时间内生效, 编码参数*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue, int cookieMaxage, boolean isEncode) {doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);}/*** 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue, int cookieMaxage, String encodeString) {doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);}/*** 删除Cookie带cookie域名*/public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,String cookieName) {doSetCookie(request, response, cookieName, "", -1, false);}/*** 设置Cookie的值,并使其在指定时间内生效** @param cookieMaxage cookie生效的最大秒数*/private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {try {if (cookieValue == null) {cookieValue = "";} else if (isEncode) {cookieValue = URLEncoder.encode(cookieValue, "utf-8");}Cookie cookie = new Cookie(cookieName, cookieValue);if (cookieMaxage > 0)cookie.setMaxAge(cookieMaxage);if (null != request) {// 设置域名的cookieString domainName = getDomainName(request);System.out.println(domainName);if (!"localhost".equals(domainName)) {cookie.setDomain(domainName);}}cookie.setPath("/");response.addCookie(cookie);} catch (Exception e) {e.printStackTrace();}}/*** 设置Cookie的值,并使其在指定时间内生效** @param cookieMaxage cookie生效的最大秒数*/private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,String cookieName, String cookieValue, int cookieMaxage, String encodeString) {try {if (cookieValue == null) {cookieValue = "";} else {cookieValue = URLEncoder.encode(cookieValue, encodeString);}Cookie cookie = new Cookie(cookieName, cookieValue);if (cookieMaxage > 0) {cookie.setMaxAge(cookieMaxage);}if (null != request) {// 设置域名的cookieString domainName = getDomainName(request);System.out.println(domainName);if (!"localhost".equals(domainName)) {cookie.setDomain(domainName);}}cookie.setPath("/");response.addCookie(cookie);} catch (Exception e) {e.printStackTrace();}}/*** 得到cookie的域名*/private static final String getDomainName(HttpServletRequest request) {String domainName = null;// 通过request对象获取访问的url地址String serverName = request.getRequestURL().toString();if (serverName == null || serverName.equals("")) {domainName = "";} else {// 将url地下转换为小写serverName = serverName.toLowerCase();// 如果url地址是以http://开头  将http://截取if (serverName.startsWith("http://")) {serverName = serverName.substring(7);}int end = serverName.length();// 判断url地址是否包含"/"if (serverName.contains("/")) {//得到第一个"/"出现的位置end = serverName.indexOf("/");}// 截取serverName = serverName.substring(0, end);// 根据"."进行分割final String[] domains = serverName.split("\\.");int len = domains.length;if (len > 3) {// www.xxx.com.cndomainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];} else if (len <= 3 && len > 1) {// xxx.com or xxx.cndomainName = domains[len - 2] + "." + domains[len - 1];} else {domainName = serverName;}}if (domainName != null && domainName.indexOf(":") > 0) {String[] ary = domainName.split("\\:");domainName = ary[0];}return domainName;}
}
  • MD5Util

package com.seckilldemo.utils;import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;@Component
public class MD5Util {public static String md5(String src){return DigestUtils.md5Hex(src);}private static final String salt="1a2b3c4d";public static String inpuntPassToFromPass(String inputPass){String str = "" +salt.charAt(0)+salt.charAt(2)+inputPass+salt.charAt(5)+salt.charAt(4);return md5(str);}public static String fromPassToDBPass(String fromPass,String salt){String str = "" +salt.charAt(0)+salt.charAt(2)+fromPass+salt.charAt(5)+salt.charAt(4);return md5(str);}public static String inputPassToDBPass(String inputPass,String salt){String fromPass = inpuntPassToFromPass(inputPass);String dbPass = fromPassToDBPass(fromPass, salt);return dbPass;}public static void main(String[] args) {//d3b1294a61a07da9b49b6e22b2cbd7f9System.out.println(inpuntPassToFromPass("123456"));System.out.println(fromPassToDBPass("d3b1294a61a07da9b49b6e22b2cbd7f9","1a2b3c4d"));System.out.println(inputPassToDBPass("123456","1a2b3c4d"));}
}
  • UUIDUtil

package com.seckilldemo.utils;import java.util.UUID;/*** UUID工具类** @author: LC* @date 2022/3/2 5:46 下午* @ClassName: UUIDUtil*/
public class UUIDUtil {public static String uuid() {return UUID.randomUUID().toString().replace("-", "");}
}
  • CookieUtil

package com.seckilldemo.utils;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;/*** Cookie工具类** @author: LC* @date 2022/3/2 5:48 下午* @ClassName: CookieUtil*/
public final class CookieUtil {/*** 得到Cookie的值, 不编码** @param request* @param cookieName* @return*/public static String getCookieValue(HttpServletRequest request, String cookieName) {return getCookieValue(request, cookieName, false);}/*** 得到Cookie的值,** @param request* @param cookieName* @return*/public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {Cookie[] cookieList = request.getCookies();if (cookieList == null || cookieName == null) {return null;}String retValue = null;try {for (int i = 0; i < cookieList.length; i++) {if (cookieList[i].getName().equals(cookieName)) {if (isDecoder) {retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");} else {retValue = cookieList[i].getValue();}break;}}} catch (UnsupportedEncodingException e) {e.printStackTrace();}return retValue;}/*** 得到Cookie的值,** @param request* @param cookieName* @return*/public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {Cookie[] cookieList = request.getCookies();if (cookieList == null || cookieName == null) {return null;}String retValue = null;try {for (int i = 0; i < cookieList.length; i++) {if (cookieList[i].getName().equals(cookieName)) {retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);break;}}} catch (UnsupportedEncodingException e) {e.printStackTrace();}return retValue;}/*** 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue) {setCookie(request, response, cookieName, cookieValue, -1);}/*** 设置Cookie的值 在指定时间内生效,但不编码*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue, int cookieMaxage) {setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);}/*** 设置Cookie的值 不设置生效时间,但编码*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue, boolean isEncode) {setCookie(request, response, cookieName, cookieValue, -1, isEncode);}/*** 设置Cookie的值 在指定时间内生效, 编码参数*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue, int cookieMaxage, boolean isEncode) {doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);}/*** 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)*/public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,String cookieValue, int cookieMaxage, String encodeString) {doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);}/*** 删除Cookie带cookie域名*/public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,String cookieName) {doSetCookie(request, response, cookieName, "", -1, false);}/*** 设置Cookie的值,并使其在指定时间内生效** @param cookieMaxage cookie生效的最大秒数*/private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {try {if (cookieValue == null) {cookieValue = "";} else if (isEncode) {cookieValue = URLEncoder.encode(cookieValue, "utf-8");}Cookie cookie = new Cookie(cookieName, cookieValue);if (cookieMaxage > 0)cookie.setMaxAge(cookieMaxage);if (null != request) {// 设置域名的cookieString domainName = getDomainName(request);System.out.println(domainName);if (!"localhost".equals(domainName)) {cookie.setDomain(domainName);}}cookie.setPath("/");response.addCookie(cookie);} catch (Exception e) {e.printStackTrace();}}/*** 设置Cookie的值,并使其在指定时间内生效** @param cookieMaxage cookie生效的最大秒数*/private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,String cookieName, String cookieValue, int cookieMaxage, String encodeString) {try {if (cookieValue == null) {cookieValue = "";} else {cookieValue = URLEncoder.encode(cookieValue, encodeString);}Cookie cookie = new Cookie(cookieName, cookieValue);if (cookieMaxage > 0) {cookie.setMaxAge(cookieMaxage);}if (null != request) {// 设置域名的cookieString domainName = getDomainName(request);System.out.println(domainName);if (!"localhost".equals(domainName)) {cookie.setDomain(domainName);}}cookie.setPath("/");response.addCookie(cookie);} catch (Exception e) {e.printStackTrace();}}/*** 得到cookie的域名*/private static final String getDomainName(HttpServletRequest request) {String domainName = null;// 通过request对象获取访问的url地址String serverName = request.getRequestURL().toString();if (serverName == null || serverName.equals("")) {domainName = "";} else {// 将url地下转换为小写serverName = serverName.toLowerCase();// 如果url地址是以http://开头  将http://截取if (serverName.startsWith("http://")) {serverName = serverName.substring(7);}int end = serverName.length();// 判断url地址是否包含"/"if (serverName.contains("/")) {//得到第一个"/"出现的位置end = serverName.indexOf("/");}// 截取serverName = serverName.substring(0, end);// 根据"."进行分割final String[] domains = serverName.split("\\.");int len = domains.length;if (len > 3) {// www.xxx.com.cndomainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];} else if (len <= 3 && len > 1) {// xxx.com or xxx.cndomainName = domains[len - 2] + "." + domains[len - 1];} else {domainName = serverName;}}if (domainName != null && domainName.indexOf(":") > 0) {String[] ary = domainName.split("\\:");domainName = ary[0];}return domainName;}
}
  • ValidatorUtil

package com.seckilldemo.utils;import org.thymeleaf.util.StringUtils;import java.util.regex.Matcher;
import java.util.regex.Pattern;public class ValidatorUtil {private static final Pattern mobile_patten = Pattern.compile("[1]([3-9])[0-9]{9}$");public static boolean isMobile(String mobile){if(StringUtils.isEmpty(mobile)){return false;}Matcher matcher = mobile_patten.matcher(mobile);return matcher.matches();}}

9、手机号处理类

  • validator

package com.seckilldemo.validator;
import com.seckilldemo.utils.ValidatorUtil;import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.Validator;
import javax.validation.constraints.NotNull;
import java.lang.annotation.*;/*** 验证手机号** @author: LC* @date 2022/3/2 3:05 下午* @ClassName: isMobile*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {IsMobileValidator.class}
)
public @interface IsMobile {boolean required() default true;String message() default "手机号码格式错误";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}
  • IsMobileValidator

package com.seckilldemo.validator;import com.seckilldemo.utils.ValidatorUtil;
import org.thymeleaf.util.StringUtils;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;/*** 手机号码校验规则** @author: LC* @date 2022/3/2 3:08 下午* @ClassName: IsMobileValidator*/
public class IsMobileValidator implements ConstraintValidator<IsMobile, String> {private boolean required = false;@Overridepublic void initialize(IsMobile constraintAnnotation) {//        ConstraintValidator.super.initialize(constraintAnnotation);required = constraintAnnotation.required();}@Overridepublic boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {if (required) {return ValidatorUtil.isMobile(s);} else {if (StringUtils.isEmpty(s)) {return true;} else {return ValidatorUtil.isMobile(s);}}}
}

10、Vo类

  • LoginVo

package com.seckilldemo.vo;import com.seckilldemo.validator.IsMobile;
import lombok.Data;
import org.hibernate.validator.constraints.Length;import javax.validation.constraints.NotNull;@Data
public class LoginVo {@NotNull@IsMobileprivate String mobile;@NotNull@Length(min = 32)private String password;}
  • RespBean

package com.seckilldemo.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 公共返回对象** @author: LC* @date 2022/3/2 1:50 下午* @ClassName: RespBean*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RespBean {private long code;private String message;private Object object;public static RespBean success() {return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), null);}public static RespBean success(Object object) {return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBean.success().getMessage(), object);}public static RespBean error(RespBeanEnum respBeanEnum) {return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), null);}public static RespBean error(RespBeanEnum respBeanEnum, Object object) {return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), object);}}
  • RespBeanEnum

package com.seckilldemo.vo;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;/*** 公共返回对象枚举** @author: LC* @date 2022/3/2 1:44 下午* @ClassName: RespBean*/
@Getter
@ToString
@AllArgsConstructor
public enum RespBeanEnum {//通用SUCCESS(200, "SUCCESS"),ERROR(500, "服务端异常"),//登录模块LOGIN_ERROR(500210, "用户名或者密码不正确"),MOBILE_ERROR(500211, "手机号码格式不正确"),BIND_ERROR(500212, "参数校验异常"),MOBILE_NOT_EXIST(500213, "手机号码不存在"),PASSWORD_UPDATE_FAIL(500214, "更新密码失败"),SESSION_ERROR(500215, "用户SESSION不存在"),//秒杀模块EMPTY_STOCK(500500, "库存不足"),REPEATE_ERROR(500501, "该商品每人限购一件"),REQUEST_ILLEGAL(500502, "请求非法,请重新尝试"),ERROR_CAPTCHA(500503, "验证码错误,请重新输入"),ACCESS_LIMIT_REACHED(500504, "访问过于频繁,请稍后重试"),//订单模块5003xxORDER_NOT_EXIST(500300, "订单不存在"),;private final Integer code;private final String message;}

四、前端

  • login.html

<!DOCTYPE html>
<html lang="en"xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>登录</title><!-- jquery --><script type="text/javascript" th:src="@{/js/jquery.min.js}"></script><!-- bootstrap --><link rel="stylesheet" type="text/css" th:href="@{/bootstrap/css/bootstrap.min.css}"/><script type="text/javascript" th:src="@{/bootstrap/js/bootstrap.min.js}"></script><!-- jquery-validator --><script type="text/javascript" th:src="@{/jquery-validation/jquery.validate.min.js}"></script><script type="text/javascript" th:src="@{/jquery-validation/localization/messages_zh.min.js}"></script><!-- layer --><script type="text/javascript" th:src="@{/layer/layer.js}"></script><!-- md5.js --><script type="text/javascript" th:src="@{/js/md5.min.js}"></script><!-- common.js --><script type="text/javascript" th:src="@{/js/common.js}"></script>
</head>
<body>
<form name="loginForm" id="loginForm" method="post" style="width:50%; margin:0 auto"><h2 style="text-align:center; margin-bottom: 20px">用户登录</h2><div class="form-group"><div class="row"><label class="form-label col-md-4">请输入手机号码</label><div class="col-md-5"><input id="mobile" name="mobile" class="form-control" type="text" placeholder="手机号码" required="true"/><!--             取消位数限制          minlength="11" maxlength="11"--></div><div class="col-md-1"></div></div></div><div class="form-group"><div class="row"><label class="form-label col-md-4">请输入密码</label><div class="col-md-5"><input id="password" name="password" class="form-control" type="password" placeholder="密码"required="true"/><!--             取消位数限制            minlength="6" maxlength="16"--></div></div></div><div class="row"><div class="col-md-5"><button class="btn btn-primary btn-block" type="reset" onclick="reset()">重置</button></div><div class="col-md-5"><button class="btn btn-primary btn-block" type="submit" onclick="login()">登录</button></div></div>
</form>
</body>
<script>function login() {$("#loginForm").validate({submitHandler: function (form) {doLogin();}});}function doLogin() {g_showLoading();var inputPass = $("#password").val();var salt = g_passsword_salt;var str = "" + salt.charAt(0) + salt.charAt(2) + inputPass + salt.charAt(5) + salt.charAt(4);var password = md5(str);$.ajax({url: "/login/doLogin",type: "POST",data: {mobile: $("#mobile").val(),password: password},success: function (data) {layer.closeAll();if (data.code == 200) {layer.msg("成功");console.log(data);document.cookie = "userTicket=" + data.object;window.location.href = "/goods/toList";} else {layer.msg(data.message);}},error: function () {layer.closeAll();}});}
</script>
</html>
  • list.html

<!DOCTYPE html>
<html lang="en"xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>商品列表</title>
</head>
<body><p th:text="'Hello:'+${user.nickname}"></p>
</body>
</html>

SpringBoot+2次MD5登录密码加密+MyBatisPlus+Thymeleaf+Bootstrap简单实现登录功能,一文轻松搞定!相关推荐

  1. python登录网页账号密码_遇到需要登录的网站怎么办?学好python,用这3招轻松搞定...

    你好 由于你是游客 无法查看本文 请你登录再进 谢谢合作..... 当你在爬某些网站的时候 需要你登录才可以获取数据 咋整? 莫慌 把这几招传授给你 让你以后从容应对 登录的常见方法无非是这两种 1. ...

  2. 怎么去调需要登录的接口_遇到需要的登录的网站怎么办?学好python,用这3招轻松搞定...

    你好 由于你是游客 无法查看本文 请你登录再进 谢谢合作..... 当你在爬某些网站的时候 需要你登录才可以获取数据 咋整? 莫慌 把这几招传授给你 让你以后从容应对 登录的常见方法无非是这两种 1. ...

  3. Python_49模块及模块导入_OS模块_SYS模块_hashlib模块_用户登录密码加密验证的例子...

    一个py文件就可以是一个模块 Python导入模块名的查找:先去该文件目录下找   Pycharm 里面查找    安装包查找 import 自写模块的时候需要把模块的全部地址尽量写出写全 例如:模块 ...

  4. 关于登录密码加密的三个方式

    登录密码对于用户来说是最重要的数据,所以在存储的时候需要进行加密,防止在一些外部攻击下用户重要数据被别人获取了.对于登录密码加密,本人整理了三种简单的方式. 具体思路如下: 一.数据库加密 1.在后端 ...

  5. 新浪微博登录密码加密函数 wsse加密算法说明

    // 新浪微博登录密码加密函数 // password   密码明文 // servertime 提交的参数之一 // nonce      提交的参数之一 // encode_password 输出 ...

  6. SpringBoot集成Druid和数据库密码加密

    Druid是阿里开发的数据库连接池,通过简单的配置,可以实现数据库的连接,性能特别强大,可以在页面访问,包括监控数据库性能参数,慢SQL统计,当然还包括数据库连接等. 今天主要记录一下SpringBo ...

  7. jemter-测试登录密码加密的情况

    jemter-测试登录密码加密的情况 废话不多说,直接上截图 1.先添加cookie管理器.请求头管理器.以及用户定义变量. 利用抓包工具fiddler,找到表头重要的信息,至于cookie管理器一样 ...

  8. 使用MD5作密码加密与校验

    一.工具类做个记录,直接上代码: package com.prison.common.util;import com.prison.common.enums.ResultType; import or ...

  9. springBoot配置文件设置mongodb连接密码加密

    springBoot配置文件设置mongodb连接密码加密 方案 实践 pom文件引入依赖 application.yml文件中定义加密的秘钥 定义main函数测试加解密 把加密后的密码放置到Mong ...

最新文章

  1. 如何在ABAP Netweaver和CloudFoundry里记录并查看日志 1
  2. python解决urllib发送请求报错:urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED].....>
  3. Vmware ESX5i 环境下部署Windows Storage Server 2008 R2
  4. 用opencv进行图像处理-之用matplotlib显示
  5. pygame使用多种方法让背景和人物运动起来
  6. 西安电子科技大学计算机学院保研政策,西安电子科技大学计算机学院(专业学位)计算机技术保研条件...
  7. 大数据实战第十二课之-Scala知识05
  8. (转) 如何在Excel和Word文档中插入GIF动画
  9. 【赠书】熊德意老师的一部不止于技术的神经机器翻译“百科全书”
  10. 制作方舟mod如何连接服务器,方舟服务器怎么添加MOD | 手游网游页游攻略大全
  11. 1、 输入长方形的长和宽,编程求该长方形的周长和面积
  12. 数据库查询和数据操纵
  13. [生存志] 第112节 义军起山东
  14. 长痘的原因及治疗方法
  15. 008.西门子M440变频器USS通信
  16. 森林怎么训练野人_迷失森林怎么养野人,来研究下吧
  17. 基于k8s+Prometheus+Alertmanager+Grafana构建企业级监控告警系统
  18. 无法打开“Soundflower.pkg”,因为它来自身份不明的开发者。
  19. 张家口计算机中专学校,张家口中专学校名单
  20. nutch和solr做爬虫

热门文章

  1. GPT-4 手画设计稿 直接生成前端页面
  2. C# wpf 使用d3d渲染dxva2解码数据
  3. 电话键盘(JAVA)
  4. 2023年【劳务员-岗位技能(劳务员)】找解析及劳务员-岗位技能(劳务员)考试技巧
  5. psp运行java模拟器如何全屏_我玩psp模拟器用Java时不小心设置成全屏模式弄不回来了,现在什么都玩不了求解...
  6. Word处理代码文本之删除注释与空行
  7. 为什么二进制0代表正数,1代表负数
  8. CRM中的俱乐部管理
  9. 计算机运行速度靠什么,怎么提高老电脑的运行速度
  10. autoformr7安装许可证_AutoForm R6 安装方法