重点:

  • 密码加密存储
  • 使用jQuery插件做校验和错误提示等

密码不能明文存储,在数据库中是加密存储的

  • 可逆加密:通过密文使用解密算法得到明文 DES AES
  • 不可逆加密:通过密文,得不到明文 MD5 SHA-1 SHA-2

MD5优点:压缩性,长度固定;容易计算;抗修改性;强抗碰撞;MD5加盐值加密码

一、公司的工具类中加入MD5

project-commons下

创建MD5Util.java

package com.atguigu.project;

import java.security.MessageDigest;

public class MD5Util {
public static String digest16(String inStr) {
return digest(inStr, 16);
}
public static String digest(String inStr) {
return digest(inStr, 32);
}
private static String digest(String inStr, int rang) {
MessageDigest md5 = null;
if ( MyStringUtils.isEmpty(inStr) ) {
return "";
} try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
e.printStackTrace();
return "";
} char[] charArray = inStr.toCharArray();
byte[] byteArray = new byte[charArray.length]; for (int i = 0; i < charArray.length; i++) {
byteArray[i] = (byte) charArray[i];
} byte[] md5Bytes = md5.digest(byteArray); StringBuilder hexValue = new StringBuilder(); for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16)
hexValue.append("0");
hexValue.append(Integer.toHexString(val));
}
if ( rang == 32 ) {
return hexValue.toString();
} else {
return hexValue.toString().substring(8, 24);
}
} public static void main(String args[]) {
String s = new String("admin");
System.out.println(digest(s));
}
}

MyStringUtils

package com.atguigu.project;

public class MyStringUtils {

    public static boolean isEmpty(String str) {
if (str == null) {
return true;
}
if (str.trim().equals("")) {
return true;
}
return false;
}
}
业务中使用MD5加密:
1.将用户输入的用户密码拿到
2.去数据库查询用户,使用用户带来的用户名和加密后的密码进行查询

二、使用jQuery插件做校验和错误提示

jQuery Validate 插件为表单提供了强大的验证功能,让客户端表单验证变得更简单,同时提供了大量的定制选项,满足应用程序各种需求。该插件捆绑了一套有用的验证方法,包括 URL 和电子邮件验证,同时提供了一个用来编写用户自定义方法的 API。所有的捆绑方法默认使用英语作为错误信息,且已翻译成其他 37 种语言。

该插件是由 Jörn Zaefferer 编写和维护的,他是 jQuery 团队的一名成员,是 jQuery UI 团队的主要开发人员,是 QUnit 的维护人员。该插件在 2006 年 jQuery 早期的时候就已经开始出现,并一直更新至今。目前版本是 1.14.0

访问 jQuery Validate 官网,下载最新版的 jQuery Validate 插件

使用:引入jQuery和jQuery Validate
<script type="application/javascript" src="yourpath/jquery-3.2.1.min.js"></script> 
<script type="application/javascript" src="yourpath/jquery.validate.js"></script>
rules指定校验规则
messages指定报错信息 举例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script type="application/javascript" src="js/jquery-3.2.1.min.js"></script>
<script type="application/javascript" src="plugin/jquery-validation-1.13.1/dist/jquery.validate.js"></script>
</head>
<body>
<form class="cmxform" id="commentForm" method="get" action="">
<fieldset>
<legend>Please provide your name, email address (won't be published) and a comment</legend>
<p>
<label for="cname">Name (required, at least 2 characters)</label>
<input id="cname" name="name" minlength="2" type="text" required>
</p>
<p>
<label for="cemail">E-Mail (required)</label>
<input id="cemail" type="email" name="email" required>
</p>
<p>
<label for="curl">URL (optional)</label>
<input id="curl" type="url" name="url">
</p>
<p>
<label for="ccomment">Your comment (required)</label>
<textarea id="ccomment" name="comment" required></textarea>
</p>
<p>
<input class="submit" type="submit" value="Submit">
</p>
</fieldset>
</form>
</body>
<script>
$.validator.setDefaults({
submitHandler: function() {
alert("submitted!");
}
}); $().ready(function() { $("#commentForm").validate({
rules: {
name: "required", email: {
required: true,
email: true
}
},
messages: {
name:{
required:"名字是必须的",
},
email: {
required: "邮箱是必须的",
email: "邮箱格式必须是合法的"
} }
}); });
</script>
</html>

rules指定规则,name: "required"意为name是必须的,当有多条规则的时候使用大括号,email字段是必须的,且要检查email格式

rules: {
name: "required", email: {
required: true,
email: true
}
}

messages是错误信息,与上面的rules相对应

messages: {
name:{
required:"名字是必须的",
},
email: {
required: "邮箱是必须的",
email: "邮箱格式必须是合法的"
}
}

三、用户登陆和注册界面

将css和js的引入统一放到WEB-INF的includes文件夹下,所有页面共用的css和js聚集在一起,各页面独有的则存放在各个页面

js-file.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script src="${ctp}/jquery/jquery-2.1.1.min.js"></script>
<script src="${ctp}/plugin/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<script src="${ctp}/script/docs.min.js"></script>
<script src="${ctp}/script/back-to-top.js"></script>
<!-- --------随着项目不断增加 -->

<script src="${ctp}/plugin/jquery-validation-1.13.1/dist/jquery.validate.min.js"></script>

css-file.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<link rel="stylesheet" href="${ctp}/plugin/bootstrap-3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="${ctp}/css/font-awesome.min.css">
<link rel="stylesheet" href="${ctp}/css/login.css">
<link rel="stylesheet" href="${ctp}/css/main.css">
在各页面需要引入js和css的地方分别使用:
<%@include file="/WEB-INF/includes/js-file.jsp" %>
<%@include file="/WEB-INF/includes/css-file.jsp" %>

JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。
JSP指令的基本语法格式:
<%@ 指令 属性名="值" %>

include指令
include指令用于通知JSP引擎在翻译当前JSP页面时将其他文件中的内容合并进当前JSP页面转换成的Servlet源文件中,这种在源文件级别进行引入的方式称之为静态引入,当前JSP页面与静态引入的页面紧密结合为一个Servlet。
语法:
<%@ include file="relativeURL"%>
其中的file属性用于指定被引入文件的相对路径。

在index.jsp中配置登陆和注册页面的url

<ul class="nav navbar-nav navbar-right">
<li><a href="${ctp}/login.jsp">登录</a></li>
<li><a href="${ctp}/reg.jsp">注册</a></li>
</ul>

同时也配置login.jsp和reg.jsp中的相关链接

四、管理员用户注册

注册的流程:

来到注册页面--->输入表单内容--->js插件校验--->来到控制器处理注册请求--->调用UserService的注册方法--->UserMapper给数据库中保存东西--->注册完跳转到管理员控制台

注册页面找到注册表单

表单有action指向

method是post

 <form id="regForm" class="form-signin" role="form" action="${ctp }/permission/user/reg" method="post">
...
</div>
<a id="submitBtn" class="btn btn-lg btn-success btn-block" > 注册</a>
</form>
</div>
<%@include file="/WEB-INF/includes/js-file.jsp" %>
<script type="text/javascript">
$("#submitBtn").click(function () {
$("#regForm").submit();
return false;
}); </script>

action 属性规定当提交表单时,向何处发送表单数据

action="${ctp }/permission/user/reg",因此点击提交后会将表单数据发送给/manager-web/permission/user/reg

在web控制器里

分层,后台有很多功能

controller中根据功能分包

权限

业务审核

业务管理

参数管理

我们将处理上面注册请求的功能放在permission下,接收并响应上面的请求

处理注册请求

 超详细 Spring @RequestMapping 注解使用技巧

项目部属对应的path

从上面可知webapp在根路径下

@RequestMapping("/permission/user") 正是上面发送数据的地址

package com.atguigu.scw.manager.controller.permission;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import com.atguigu.scw.manager.bean.TUser; //处理所有/permission/user下的请求
@RequestMapping("/permission/user")
@Controller
public class UserController { private String manager = "manager/"; /**
*
*/
// /permission/user/reg
@RequestMapping("/reg")
public String reg(TUser user) {
System.out.println("用户注册...");
// 1.注册成功后来到控制面板页面
return "manager/main";
}
}

return "manager/main"

实际访问的是/manager-web/WEB-INF/jsps/manager/main.jsp

为什么能访问到呢?因为我们在SpringMVC中配置了解析器

<!--2、视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsps/"></property>
<property name="suffix" value=".jsp"></property>
</bean>

controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。因此,根据上面的前后缀配置,manager/main解析为/manager-web/WEB-INF/jsps/manager/main.jsp

控制台页面不是直接能够访问的,不放在webapp,放在WEB-INF的jsps下的manager中

manger存放管理员的页面

下面又包含permission、audi、serviceman、system文件夹,分别对应权限管理、业务审核、业务管理、参数管理

将main.jsp放在manager下

五、表单校验

设置下注册页面的表单

校验插件拷贝到plugin文件夹下

修改reg.jsp

...
<div class="container"> <form id="regForm" class="form-signin" role="form" action="${ctp }/permission/user/reg" method="post">
<h2 class="form-signin-heading"><i class="glyphicon glyphicon-log-in"></i> 用户注册</h2>
<div class="form-group has-success has-feedback">
<input type="text" name="loginacct" class="form-control"
id="loginacct_input"
placeholder="请输入登录账号" autofocus>
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-success has-feedback">
<input type="password" name="userpswd" class="form-control"
id="userpswd_input"
placeholder="请输入登录密码" style="margin-top:10px;">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="form-group has-success has-feedback">
<input type="text" name="email" class="form-control"
id="email_input" placeholder="请输入邮箱地址" style="margin-top:10px;">
<span class="glyphicon glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-success has-feedback">
<select class="form-control" >
<option>会员</option>
<option>管理</option>
</select>
</div>
<div class="checkbox">
<label>
忘记密码
</label>
<label style="float:right">
<a href="${ctp}/login.jsp">我有账号</a>
</label>
</div>
<a id="submitBtn" class="btn btn-lg btn-success btn-block" > 注册</a>
</form>
</div>
<%@include file="/WEB-INF/includes/js-file.jsp" %>
<script type="text/javascript">
$("#submitBtn").click(function () {
$("#regForm").submit();
return false;
}); $("#regForm").validate({
rules:{
loginacct:{
required: true,
minlength: 6
},
userpswd: {
required: true,
minlength: 6
},
email: {
required: true,
email: true
}
},
messages:{
loginacct:{
required: "请填写用户账号",
minlength: "登陆账号必须是6位以上"
},
userpswd: {
required: "请填写密码",
minlength: "密码必须是6位以上"
},
email: {
required: "请填写邮箱",
email: "请输入正确的邮箱"
}
}
}); </script>
...

运行

可以发现图标因为显示提示信息位置有点错乱

可以想办法把提示信息放在图标的下边

自定义错误显示

 <script type="text/javascript">

//给校验器设置一些策略
$.validator.setDefaults({
showErrors:function(map, list) {
//console.log(map);
//console.log(list);
//将每个元素自己的错误信息显示在自己的图标下
//先清除所有错误;清状态
$(".errorinfo").empty();
$(".form-group").removeClass("has-success has-error has-warning") $.each(list,function(){
//当前发生错误的详细信息;
//element当前错误元素
//错误信息
$(this.element).nextAll(".errorinfo").text(this.message);
//改变input的状态;
$(this.element).parent("div.form-group").addClass("has-error") })
}
});
...

showErrors:function(map, list)

map和list

map封装了每个字段的错误信息

element是错误信息的元素

在图标下面加一个span用来显示错误信息

<span class="errorinfo" style="color: red"></span>

注册分会员注册和管理员注册

修改下reg.jsp中提交时的js

 $("#submitBtn").click(function () {
var loginType = $("select.form-control").val();
if(loginType == "管理"){
$("#regForm").submit();
}else{
alert("此功能尚未开通")
}
return false;
});

在表单提交的UserController中编写注册的逻辑

//处理所有/permission/user下的请求
@RequestMapping("/permission/user")
@Controller
public class UserController { private String manager = "manager/";
@Autowired
UserService userService; /**
*
*/
// /permission/user/reg
@RequestMapping("/reg")
public String reg(TUser user, Model model, HttpSession session) {
System.out.println("用户注册..." + user);
// 1.注册成功后来到控制面板页面
// 1.注册用户
boolean flag = userService.register(user);
if (flag == true) {
// 1.注册成功,来到控制面板
// 用户保存的数据在user对象中,id是数据库生成的自增主键
// 需要修改mybatis的mapper文件,让其使用自动生成的id
session.setAttribute(Constants.LOGIN_USER, user); return "manager/main";
} else {
// 2.注册失败
model.addAttribute("regError", "用户名已经被使用");
// 3.来到页面要回显user之前输入的内容
// 4.user先从隐含模型中拿的;只要pojo,确定完值以后会自动放在隐含模型中
// 用的key是类名首字母小写${tUser.loginacct }
// 由于bean包中的类名前两个字母大写,比较特殊,这里实际使用的是TUser
return "forward:/reg.jsp";
} }
}

注册失败好要回显,在reg.jsp的表格中设置用户名和邮箱的value,value="${TUser.loginacct }

<form id="regForm" class="form-signin" role="form" action="${ctp }/permission/user/reg" method="post">
<h2 class="form-signin-heading"><i class="glyphicon glyphicon-log-in"></i> 用户注册</h2>
<div class="form-group has-success has-feedback">
<input type="text" name="loginacct" class="form-control"
id="loginacct_input"
placeholder="请输入登录账号" value="${TUser.loginacct }" autofocus>
<span class="glyphicon glyphicon-user form-control-feedback"></span>
<span class="errorinfo" style="color: red"></span>
</div>
<div class="form-group has-success has-feedback">
<input type="password" name="userpswd" class="form-control"
id="userpswd_input"
placeholder="请输入登录密码" style="margin-top:10px;">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
<span class="errorinfo" style="color: red"></span>
</div>
<div class="form-group has-success has-feedback">
<input type="text" name="email" class="form-control"
id="email_input" placeholder="请输入邮箱地址" value="${TUser.email }" style="margin-top:10px;">
<span class="glyphicon glyphicon glyphicon-envelope form-control-feedback"></span>
<span class="errorinfo" style="color: red"></span>
</div>

由于bean起名的时候前两个字母都是大写,因此页面中要和类名相同,即TUser,而不是常用的tUser

上面用到了UserService的register方法和Constants.LOGIN_USER常量

编写UserService接口和实现类

package com.atguigu.scw.manager.service;

import com.atguigu.scw.manager.bean.TUser;

public interface UserService {

    public boolean register(TUser user);
}
package com.atguigu.scw.manager.service.impl;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.atguigu.project.MD5Util;
import com.atguigu.project.MyStringUtils;
import com.atguigu.scw.manager.bean.TUser;
import com.atguigu.scw.manager.dao.TUserMapper;
import com.atguigu.scw.manager.service.UserService; @Service
public class UserServiceImpl implements UserService { @Autowired
TUserMapper userMapper; public boolean register(TUser user) {
// 1.拿到用户信息,先加密密码
// 加密的密码 盐,这里使用了用户名
// 盐不能超过8位,因此本打算用用户名,但容易出错,这里取部分用户名
// String loginacct = user.getLoginacct();
// String salt = loginacct.substring(0, 6) + "HA";
// String crypt = Md5Crypt.md5Crypt(user.getUserpswd().getBytes());
String diget = MD5Util.digest(user.getUserpswd());
user.setUserpswd(diget);
// 2.在将用户的其他信息设置默认值
// 设置昵称 创建时间
user.setUsername(user.getLoginacct());
user.setCreatetime(MyStringUtils.formatSimpleDate(new Date()));
// 3.去数据库保存用户,登陆账号不能重复
int i;
try {
i = userMapper.insertSelective(user);
} catch (Exception e) {
// 保存失败的原因就是用户重复,数据库设置了Loginacct不可重复
return false;
}
// i影响多少行
return i == 1 ? true : false;
} }

用到了MyStringUtils.formatSimpleDate(new Date())

MyStringUtils中添加方法

 public static String formatSimpleDate(Date date) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
return format.format(date);
}

Constants.LOGIN_USER常量

package com.atguigu.scw.manager.constant;

public class Constants {

    public static final String LOGIN_USER = "loginUser";
}

修改下/manager-dao/src/main/resources/mybatis/mapper/TUserMapper.xml

<insert id="insertSelective" parameterType="com.atguigu.scw.manager.bean.TUser" useGeneratedKeys="true" keyProperty="id">

数据库里密码长度改为64

登陆后的控制面板,右上角显示用户名

从session中取,用loginUser

main.jsp中

<div class="btn-group">
<button type="button" class="btn btn-default btn-success dropdown-toggle" data-toggle="dropdown">
<i class="glyphicon glyphicon-user"></i>
${loginUser.username }
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#"><i class="glyphicon glyphicon-cog"></i> 个人设置</a></li>
<li><a href="#"><i class="glyphicon glyphicon-comment"></i> 消息</a></li>
<li class="divider"></li>
<li><a href="index.html"><i class="glyphicon glyphicon-off"></i> 退出系统</a></li>
</ul>
</div>

【JavaWeb项目】一个众筹网站的开发(四)后台用户注册功能的更多相关文章

  1. 【JavaWeb项目】一个众筹网站的开发(八)后台页面详细设置

    一.user.jsp改造 删除引入菜单 抽取导航栏 nav-bar.jsp,删除引入导航栏 删除引入main.jsp的到好烂 数据库里添加url 报错,url不对 没有/ url正确 action=& ...

  2. 【JavaWeb项目】一个众筹网站的开发(一)架构搭建

    本项目是@尚硅谷相关视频的记录. 本项目使用Maven构建,工程架构如下图所示: 一.公司的公共父工程和工具类包 1.父工程 每个公司都有自己的父工程 父工程作用:对公司使用的jar包进行统一管理,别 ...

  3. 【JavaWeb项目】一个众筹网站的开发(五)后台用户登录功能

    用户模块 1)注册 表单校验,使用校验插件 用户密码需要加密存储 注册成功后来到管理控制台,将用户放在session中,防止以后获取 以后用户经常获取用户id,使用mabatis主键自增策略,保存用户 ...

  4. 【JavaWeb项目】一个众筹网站的开发(九)邮件开发

    Java官方支持邮件开发,Javax-mail jdk中默认没有,需要另外下载 apache的基于Javax-mail开发了commons-mail,更加简单高效,推荐使用 一.电子邮件接收和发送协议 ...

  5. 【JavaWeb项目】一个众筹网站的开发(六)后台用户权限控制

    登陆成功进入控制面板后 左侧的菜单是共同的元素,抽取出来做静态包含 要求必须是按照不同的用户得到不同的菜单 用户做了权限限制,哪个用户能操作哪些内容(链接.按钮.内容) 一.RBAC权限模型 权限管理 ...

  6. 【JavaWeb项目】一个众筹网站的开发(三)第一个网页

    一.bootstrap 本项目采用bootstrap3 bootstrap中文网 https://www.bootcss.com/ 使用bootstrap三步: 1.导入jQuery 2.导入boot ...

  7. 【JavaWeb项目】一个众筹网站的开发(二)架构搭建之架构测试

    1.dao层和pojo都是使用mbg生成,基本的CRUD以及JavaBean 2.将mbg放在dao层,一旦dao层打包以后mbg就删除掉 一.创建数据库用于测试 数据库名称:scw_0325 SQL ...

  8. 【JavaWeb项目】一个众筹网站的开发(七)后台用户菜单

    mvn命令不能运行: jar-war-pom之间是可以直接写,优先找这个工程,而不是仓库的位置 pom-pom子父关系,需要去仓库中找,我们需要使用<relativePath>../pro ...

  9. ios开发视频播放后台下载功能实现 :1,ios播放视频 ,包含基于AVPlayer播放器,2,实现下载,iOS后台下载(多任务同时下载,单任务下载,下载进度,下载百分比,文件大小,下载状态)(真机调试功能正常)

    ABBPlayerKit ios开发视频播放后台下载功能实现 : 代码下载地址:https://github.com/niexiaobo/ABBPlayerKit github资料学习和下载地址:ht ...

随机推荐

  1. Node.js require 方法

    Node.js 中存在 4 类模块(原生模块和3种文件模块),尽管 require 方法极其简单,但是内部的加载却是十分复杂的,其加载优先级也各自不同

  2. 【串线篇】mybatis-config.xml配置事项

    一.术语 properties 属性 settings 设置 typeAliases 类型命名 typeHandlers 类型处理器 objectFactory 对象工厂, plugins 插件, e ...

  3. diff算法(核心)

    ps:大致转载知乎文章 vue和react的虚拟dom都采用类似的diff算法,核心大概可以归为两点 1,两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构: 2,同一层级的一组节点, ...

  4. python 数组元素个数

    list=[1,2,3,{1,4,5,6,7}] print(len(list)) 输出4

  5. OpenCV常用基本处理函数(3)颜色空间

    颜色空间转换 对图像进行颜色空间转换,比如从 BGR 到灰度图,或者从BGR 到 HSV 等 我们要用到的函数是:cv2.cvtColor(input_image ,flag),其中 flag就是转换 ...

  6. Cesium鼠标事件

    computed: { handler() { return new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas) } } ...

  7. PHP上传文件和下载

    PHP 中文件上传的基础知识: 1)客户端 form 表单设置 必须设置的 form 表单项: <!DOCTYPE html> <html> <head> < ...

  8. JavaSE---IO体系

    1.BIO 1.1 Block IO,同步阻塞IO: 1.2 eg:java.io   包下的      InputStream . OutputStream.  Writer.Reader... j ...

  9. ArcGIS Runtime SDK for .NET (Quartz Beta)之连接ArcGIS Portal

    1. 介绍 ArcGIS Portal作为ArcGIS平台的中枢,在ArcGIS体系中起着至关重要的地位.在ArcGIS Runtime的新架构Quartz中添加了连接ArcGIS Portal(或A ...

  10. MySQL timestampdiff 和 timestampadd 的用法

    在应用时,经常要使用这两个函数TIMESTAMPDIFF和TIMESTAMPADD. 一,TIMESTAMPDIFF 语法: TIMESTAMPDIFF(interval,datetime_expr1 ...