最近完成一个小项目,每次都会编写注册功能的实现。为了方便以后自己查阅和使用相同技术点的开发人员参考,记录一下注册页面所涉及知识点。
目录
2.使用bootstrapvalidator 技术进行前端字段验证
首先是页面的效果:



下面是重点知识点整理内容:
1.图片验证码技术保护web应用
后端生成验证码的工具类如下:
package com.justcs.utils;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 生成随机的验证码图片工具
*/
public class RandomCodeUtil {
public static final String RANDOMCODEKEY = "randomcode_key";//放到session中的key
private Random random = new Random();
private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生的字符串
private int width = 80;//图片宽
private int height = 26;//图片高
private int lineSize = 40;//干扰线数量
private int stringNum = 4;//随机产生字符数量
/**
* 生成随机图片
*/
public void getRandcode(HttpServletRequest request,
HttpServletResponse response) {
HttpSession session = request.getSession();
//BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
//产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
Graphics g = image.getGraphics();
g.fillRect(0, 0, width, height);
g.setFont(new Font("Times New Roman",Font.ROMAN_BASELINE,18));
g.setColor(getRandColor(160, 200));
//绘制干扰线
for(int i=0;i<=lineSize;i++){
drowLine(g);
}
//绘制随机字符
String randomString = "";
for(int i=1;i<=stringNum;i++){
randomString=drowString(g,randomString,i);
}
session.removeAttribute(RANDOMCODEKEY);
session.setAttribute(RANDOMCODEKEY, randomString);
g.dispose();
try {
//将内存中的图片通过流动形式输出到客户端
ImageIO.write(image, "JPEG", response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 获得字体
*/
private Font getFont(){
return new Font("Fixedsys",Font.CENTER_BASELINE,18);
}
/*
* 获得颜色
*/
private Color getRandColor(int fc,int bc){
if(fc > 255)
fc = 255;
if(bc > 255)
bc = 255;
int r = fc + random.nextInt(bc-fc-16);
int g = fc + random.nextInt(bc-fc-14);
int b = fc + random.nextInt(bc-fc-18);
return new Color(r,g,b);
}
/*
* 绘制字符串
*/
private String drowString(Graphics g,String randomString,int i){
g.setFont(getFont());
g.setColor(new Color(random.nextInt(101),random.nextInt(111),random.nextInt(121)));
String rand = String.valueOf(getRandomString(random.nextInt(randString.length())));
randomString +=rand;
g.translate(random.nextInt(3), random.nextInt(3));
g.drawString(rand, 13*i, 16);
return randomString;
}
/*
* 绘制干扰线
*/
private void drowLine(Graphics g){
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(13);
int yl = random.nextInt(15);
g.drawLine(x, y, x+xl, y+yl);
}
/*
* 获取随机的字符
*/
public String getRandomString(int num){
return String.valueOf(randString.charAt(num));
}
}
Controller层这样对外提供接口:
/**
* 输出验证码图片
*
* @param request
* @param response
*/
@RequestMapping("/checkcode")
public void checkcode(HttpServletRequest request, HttpServletResponse response) {
//设置相应类型,告诉浏览器输出的内容为图片
response.setContentType("image/jpeg");
//设置响应头信息,告诉浏览器不要缓存此内容
response.setHeader("pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expire", 0);
RandomCodeUtil randomValidateCode = new RandomCodeUtil();
try {
randomValidateCode.getRandcode(request, response);//输出图片方法
} catch (Exception e) {
e.printStackTrace();
}
}
前端页面这样引用:
<img src="/usr/checkcode" onclick="this.src=this.src+'?timestamp='+new Date().getTime()"
class="valicodeimg" alt=""/>
2.使用bootstrapvalidator 技术进行前端字段验证
首先需要引用bootstrapvalidator的插件的js和css文件(前提是页面已经引用了jquery和bootstrap或者其他的框架:
<%-- 引入bootstrap表单验证资源 --%>
<link rel="stylesheet" href="../../bootstrapvalidator/css/bootstrapValidator.min.css"/>
<script src="../../bootstrapvalidator/js/bootstrapValidator.min.js" type="text/javascript"></script>
好了,下面列出我的注册页面的html结构:
<div class="panel">
<div class="panel-heading text-left">
<div class="text-gray" style="font-weight: 600;line-height:40px;font-size:20px;">学生注册</div>
</div>
<div class="panel-body">
<form method="post" id="registform" class="form-horizontal" action="#">
<div class="form-group">
<label for="stuid" class="col-sm-3">学号</label>
<div class="col-md-7 col-sm-9">
<input type="text" class="form-control" name="stuid" id="stuid"
placeholder="请输入您的学号(必填)">
</div>
</div>
<div class="form-group">
<label for="stuname" class="col-sm-3">姓名</label>
<div class="col-md-7 col-sm-9">
<input type="text" class="form-control" name="stuname" id="stuname"
placeholder="请输入姓名(必填)">
</div>
</div>
<div class="form-group">
<label for="classno" class="col-sm-3">班级</label>
<div class="col-md-7 col-sm-9">
<input type="text" class="form-control" name="classno" id="classno"
placeholder="请输入班级(必填)">
</div>
</div>
<div class="form-group">
<label for="stupwd" class="col-sm-3">输入密码</label>
<div class="col-md-7 col-sm-9">
<input type="password" class="form-control" name="stupwd" id="stupwd"
placeholder="请输入账号密码(必填)">
</div>
</div>
<div class="form-group">
<label for="surepwd" class="col-sm-3">确认密码</label>
<div class="col-md-7 col-sm-9">
<input type="password" class="form-control" name="surepwd" id="surepwd"
placeholder="请再次输入密码(必填)">
</div>
</div>
<div class="form-group">
<label for="tips" class="col-sm-3">备注</label>
<div class="col-md-7 col-sm-9">
<textarea class="form-control" id="tips" name="tips"
placeholder="请输入备注(非必填项)"></textarea>
</div>
</div>
<div class="form-group">
<label for="valicode" class="col-sm-3">验证码</label>
<div class="col-md-4 col-sm-6">
<input type="text" class="form-control" id="valicode" name="valicode"
placeholder="验证码(必填)"/>
</div>
<div class="col-md-4 col-sm-4">
<img src="/usr/checkcode" onclick="this.src=this.src+'?timestamp='+new Date().getTime()"
class="valicodeimg" alt=""/>
</div>
</div>
<div style="margin-top:20px;margin-bottom:20px;">
<button
type="button"
id="subregistbtn"
class="btn btn-success">
提交注册
</button>
<button
type="button"
id="resetregist"
class="btn btn-info">
重置表单
</button>
</div>
<br>
<span onclick="window.location.href='/'"
class="text-danger" style="text-decoration: underline;cursor: pointer;"><<返回登录</span>
</form>
</div>
</div>
下面编写js代码来完成前端验证的功能:
$('#registform').bootstrapValidator({
message: "请输入有效的字段",
fields: {
"stuid": {
message: "学号非法",
validators: {
notEmpty: {
message: '学号不能为空'
},
stringLength: {
max: 20,
message: '学号最多20位'
}
}
},
"stuname": {
validators: {
notEmpty: {
message: '姓名不能为空'
},
stringLength: {
max: 40,
message: '姓名过长不能超过40个字'
}
}
},
"classno": {
validators: {
notEmpty: {
message: '班级不能为空'
},
stringLength: {
max: 50,
message: '班级过长不能超过50个字'
}
}
},
"stupwd": {
validators: {
notEmpty: {
message: '密码不能为空'
},
stringLength: {
min: 6,
max: 20,
message: '密码至少6位,最多20位'
},
different: {
field: 'stuid',
message: '密码不能和学号一致'
}
}
},
"surepwd": {
validators: {
notEmpty: {
message: '确认密码不能为空'
},
identical: {
field: 'stupwd',
message: '密码和确认密码不一致'
}
}
},
"valicode": {
validators: {
notEmpty: {
message: "验证码不能为空"
}
}
}
}
});
在页面提交时候,需要验证字段,这样编写:
var bootstrapValidator = $("#registform").data('bootstrapValidator');
bootstrapValidator.validate();
if (bootstrapValidator.isValid()) {
}
3.后端使用JSR303进行字段验证
这里我的项目是maven构建的,在pom.xml引入包:
<!--jsr 303-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<!-- hibernate validator-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.0.Final</version>
</dependency>
然后在项目中创建form对象RegistForm:
package com.justcs.form;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
/**
* 注册表单
*/
public class RegistForm {
@NotEmpty(message = "学号不能为空")
@Length(min = 1, max = 20, message = "学号最多20位")
private String stuid;
@NotEmpty(message = "学生的姓名不能为空")
@Length(min = 1, max = 40, message = "姓名过长不能超过40个字")
private String stuname;
@NotEmpty(message = "班级不能为空")
@Length(min = 1, max = 50, message = "班级过长不能超过50个字")
private String classno;
@NotEmpty(message = "密码不能为空")
private String stupwd;
@NotEmpty(message = "确认密码不能为空")
private String surepwd;
@Length(max = 100, message = "备注长度不能超过100个字")
private String tips;
@NotEmpty(message = "验证码不能为空")
private String valicode;
public String getStuid() {
return stuid;
}
public void setStuid(String stuid) {
this.stuid = stuid;
}
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public String getClassno() {
return classno;
}
public void setClassno(String classno) {
this.classno = classno;
}
public String getStupwd() {
return stupwd;
}
public void setStupwd(String stupwd) {
this.stupwd = stupwd;
}
public String getSurepwd() {
return surepwd;
}
public void setSurepwd(String surepwd) {
this.surepwd = surepwd;
}
public String getTips() {
return tips;
}
public void setTips(String tips) {
this.tips = tips;
}
public String getValicode() {
return valicode;
}
public void setValicode(String valicode) {
this.valicode = valicode;
}
}
其实前后端都需要验证的,前端使用来防君子,后端是为了堤防小人的。jsr303字段验证功能很丰富,拓展的还可以继续探索,通过正则表达式或者自定义验证注解。
然后在Controller层,这样来实现我们的字段验证:
/**
* 注册
*
* @return
*/
@ResponseBody
@RequestMapping("/doregist")
public WebJSONResult doregist(@Valid @RequestBody RegistForm registForm,
BindingResult result,
HttpServletRequest request) {
if (result.hasErrors()) {
return WebJSONResult.errorMsgData("字段验证不通过",
WebJSONResult.convertErrorToMap(result));
}
// 验证码校验
HttpSession session = request.getSession();
String valicode = (String) session.getAttribute(RandomCodeUtil.RANDOMCODEKEY);
if(StringUtils.equalsIgnoreCase(valicode, registForm.getValicode())){
//TODO:执行录入操作
} else {
return WebJSONResult.errorMsg("验证码错误");
}
// 执行注册服务
return WebJSONResult.ok();
}
convertErrorToMap方法:
public static Map convertErrorToMap(BindingResult result) {
Map<String, Object> map = null;
if (result != null) {
map = new HashMap<>();
List<FieldError> errors = result.getFieldErrors();
for (FieldError fieldError : errors) {
map.put(fieldError.getField(), fieldError.getDefaultMessage());
}
}
return map;
}
4.这里封装了两个js小方法
一个是能够将form表单转化为对象,一个是封装了jquery的ajax方法:
// 序列化对象
$.fn.serializeObject = function () {
var o = {};
// 将表单转为数组[{},{}...]
var a = this.serializeArray();
$.each(a, function () {
// 如果对象中已有这个对象
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else { // 如果o中没有这个对象
o[this.name] = this.value || '';
}
});
return o;
};
// 执行ajax的post请求
window.dopost = function (url, jsondata) {
return new Promise(function (resolve, reject) {
$.ajax({
url: url,
contentType: "application/json;charset=utf-8",
dataType: "json",
type: "post",
data: JSON.stringify(jsondata),
success: function (result) {
resolve(result);
},
error: function (result) {
console.log("->dopost异常...")
}
});
});
}
5.使用md5.js来对前端的密码加密
首先页面上引用md5.js的文件:
<script src="../../static/js/md5.js" type="text/javascript"></script>
然后在提交按钮这样编写:
// 提交注册功能
$("#subregistbtn").click(function () {
var bootstrapValidator = $("#registform").data('bootstrapValidator');
bootstrapValidator.validate();
if (bootstrapValidator.isValid()) {
var obj = $("#registform").serializeObject();
console.log(obj);
obj['stupwd'] = hex_md5(obj['stupwd']);
obj['surepwd'] = hex_md5(obj['surepwd']);
console.log(obj);
dopost("/usr/doregist", obj).then(function (value) {
console.log(value);
});
}
});
$("#resetregist").click(function () {
$('#registform').data('bootstrapValidator').resetForm(true);
});
6.使用sweetalert进行弹框消息处理:
首先引入sweetalert的js文件:
<script src="../../static/js/sweetalert.min.js"></script>
其次在用户注册完毕后弹出提示框:
// 提交注册功能
$("#subregistbtn").click(function () {
var bootstrapValidator = $("#registform").data('bootstrapValidator');
bootstrapValidator.validate();
if (bootstrapValidator.isValid()) {
var obj = $("#registform").serializeObject();
console.log(obj);
obj['stupwd'] = hex_md5(obj['stupwd']);
obj['surepwd'] = hex_md5(obj['surepwd']);
console.log(obj);
dopost("/usr/doregist", obj).then(function (value) {
if (value.msg == "success") {
$("#resetregist").click();
$("#valicodeimg").attr("src", "/usr/checkcode");
swal({
text: "恭喜你注册成功!",
icon: "success",
button: "确定"
});
} else {
$("#valicodeimg").click();
swal({
text: value.msg,
icon: "error",
button: "确定"
})
}
});
}
});
好了,注册页面的主要的通常面对的问题已经交代完毕了。

本文详细介绍了一个注册页面的设计与实现,包括图片验证码生成、前端与后端字段验证、密码加密及弹窗消息处理等关键技术点。

1万+

被折叠的 条评论
为什么被折叠?



