UUID工具类
1.概述:UUID 是通用唯一识别码(Universally Unique Identifier)的缩写。UUID 让分布式系统中的所有元素,都能有唯一的辨识信息,而不需要通过中央控制端来做辨识信息的指定。
是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部份。
UUID 的目的,是让分布式系统中的所有元素,都能有唯一的辨识资讯,而不需要透过中央控制端来做辨识资讯的指定。如此一来,每个人都可以建立不与其它人冲突的 UUID。在这样的情况下,就不需考虑数据库建立时的名称重复问题。目前最广泛应用的 UUID,即是微软的 Microsoft's Globally Unique Identifiers (GUIDs),而其他重要的应用,则有 Linux ext2/ext3 档案系统、LUKS 加密分割区、GNOME、KDE、Mac OS X 等等。
2.UUID 的组成
- 1~8位采用系统时间,在系统时间上精确到毫秒级保证时间上的惟一性;
- 9~16位采用底层的IP地址,在服务器集群中的惟一性;
- 17~24位采用当前对象的HashCode值,在一个内部对象上的惟一性;
- 25~32位采用调用方法的一个随机数,在一个对象内的毫秒级的惟一性。
Java生成UUID的例子:
import java.util.UUID;
public class UUIDGenerator {
public UUIDGenerator() {
}
public static String getUUID() {
UUID uuid = UUID.randomUUID();
String str = uuid.toString();
// 去掉"-"符号
String temp = str.substring(0, 8) + str.substring(9, 13) + str.substring(14, 18) + str.substring(19, 23) + str.substring(24);
return str + "," + temp;
}
//获得指定数量的UUID
public static String[] getUUID(int number) {
if (number < 1) {
return null;
}
String[] ss = new String[number];
for (int i = 0; i < number; i++) {
ss[i] = getUUID();
}
return ss;
}
public static void main(String[] args) {
String[] ss = getUUID(10);
for (int i = 0; i < ss.length; i++) {
System.out.println("ss[" + i + "]=====" + ss[i]);
}
}
}
控制台运行效果
文件上传
编程思路:
- 本地文件输入到网络上
- 网络再把文件输出到服务器上]
- 服务器读取文件
- 服务器把文件写入到指定位置
MultipartFile接口常用的的API见下表:
方法 | 功能描述 |
String getOriginalFilename() | 获取上传文件的原始文件名,即该文件在客户端中的文件名 |
boolean isEmpty() | 判断上传的文件是否为空,当没有选择文件就直接上传,或者选中的文件是0字节的空文件时,返回true,否则返回false |
long getSize() | 获取上传的文件大小,以字节为单位 |
String getContentType() | 根据所上传的文件的扩展名决定该文件的MIME类型,例如上传.jpg格式的图片,将返回image/jpeg |
InputStream getInputStream() | 获取上传文件的输入字节流,通常用于自定义读取所上传的文件的过程,该方法与transferTo()方法不可以同时使用 |
void transferTo(File dest) | 保存上传的文件,该方法与getInputStream()方法不可以同时使用 |
@WebServlet("/upload")
@MultipartConfig(maxFileSize = 4*1024*1024)
public class FileUploadbank extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
String uname = request.getParameter("uname");
System.out.println(uname);
Part pic = request.getPart("pic");
String contentType = pic.getContentType();
String submittedFileName = pic.getSubmittedFileName();
String name = pic.getName();
long size = pic.getSize();
System.out.println("contentType:"+contentType);
System.out.println("submittedFileName:"+submittedFileName);
System.out.println("name:"+name);
System.out.println("size:"+size);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
@WebServlet("/upload")
@MultipartConfig(maxFileSize = 4*1024*1024)
public class FileUpload extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置请求和响应的编码格式
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
Part pic = request.getPart("pic");
String submittedFileName = pic.getSubmittedFileName();
//获得一个永远不会重复的文件名字
submittedFileName = UUID.randomUUID().toString().replace("-","").toUpperCase()+new Date().getTime() +submittedFileName;
//获得服务器根目录下面upload文件夹的路径
String realPath = request.getSession().getServletContext().getRealPath("/upload");
//写入服务器指定文件夹,存储某个文件名字
pic.write(realPath+"/"+submittedFileName);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
注意:form表单的请求方式必须设置为POST,并配置属性enctype=“multipart/form-data”,文件上传input控件的name属性值需设置为file值。
项目架构
MySQL创建数据库和表;
#创建表
create table t_user(
uid int(11) primary key not null auto_increment,
uname varchar(20),
pwd varchar(32),
realname varchar(20),
sex varchar(11),
address varchar(50),
userImg varchar(100),
salt varchar(32)
)
创建项目并变为web项目,导入jar包;
项目中用户头像的上传
编程思路:
1、设置register.jsp页面:文件传输需要设置表单的enctype 为 multipart/form-data;略缩图
register.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册页</title>
<style>
#imgPreview img {
width: 80px;
height: 80px;
margin: 10px 5px;
}
</style>
<script src="js/jquery.min.js"></script>
<script>
$(function () {
$("#fileupload").change(function () {
if (typeof (FileReader) != "undefined") {
//先把略缩图div内容清空
var dvPreview = $("#imgPreview");
dvPreview.html("");
//拿到文件对象
var file = $($(this)[0].files[0]); //获取输入框的文件对象
var reader = new FileReader(); //定义文件缓存读取对象
reader.readAsDataURL(file[0]); //读取缓存中的文件对象
reader.onload = function (e) {
var img = $("<img />");
img.attr("src", e.target.result);
dvPreview.append(img);
}
}else {
alert("This browser does not support HTML5 FileReader.");
}
});
});
</script>
</head>
<body>
<h2>欢迎注册</h2>
<!--文件传输需要设置表单的enctype 为 multipart/form-data-->
<form action="register" method="post" enctype="multipart/form-data">
昵称:<input type="text" name="uname" value=""> <br>
密码:<input type="password" name="pwd" value=""> <br>
姓名:<input type="text" name="realname" value=""> <br>
性别:<input type="radio" name="sex" value="男">男 <input type="radio" name="sex" value="女">女 <br>
地址:<input type="text" name="address" value=""> <br>
头像:<input type="file" name="upload" value="" id="fileupload"> <br>
<div id="imgPreview"></div>
<input type="submit" value="提交"><a href="index.jsp">有帐号? 点击登录</a><br>
</form>
</body>
</html>
页面效果如下:
"enctype='multipart/form-data'" 指示使用 "multipart/form-data" 编码类型提交表单数据。这种编码类型允许在表单中包含文件上传字段。
- enctype就是encodetype就是编码类型的意思。
- multipart/form-data是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。
注意:默认情况下,enctype的值是application/x-www-form-urlencoded,不能用于文件上传,只有使用了multipart/form-data,才能完整的传递文件数据。
- application/x-www-form-urlencoded不是不能上传文件,是只能上传文本格式的文件。
- multipart/form-data是将文件以二进制的形式上传,这样可以实现多种类型的文件上传。
2、 获得头像路径并存入user对象
fileSizeThershold | int型 | 是(可选) | 当前数据量大于该值时,内容将被写入文件 |
location | String型 | 是(可选) | 存放生成文件的地址 |
maxFileSize | long型 | 是(可选) | 允许上传的文件最大值,默认为-1,表示没有限制 |
maxRequestSize | long型 | 是(可选) | 针对 multipart/form-data 请求的最大数量 |
UserRegister.java
@WebServlet("/register")
@MultipartConfig(maxFileSize = 4*1024*1024)
public class UserRegister extends HttpServlet {
UserService userService = new UserServiceImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//1.获取页而提交的赏规教花
User user = new User();
user.setUname(request.getParameter("uname"));
user.setPwd(request.getParameter( "pwd"));
user.setRealname(request.getParameter( "realname"));
user.setSex(request.getParameter("sex"));
user.setAddress(request.getParameter( "address"));
/**
* 2.完成图片上传
*/
//2.1拿到头像图片对象
Part upload = request.getPart("upload");
//2.2获取用户上传的图片的原始名字
String fileName = upload.getSubmittedFileName();
//2.3把原始名更改为一个永远会重复的文件名字:UUID+时间戳+原始名字
fileName= UUID.randomUUID().toString().replace( "-", "").toUpperCase() + new Date().getTime() +fileName;
//2.4获得头像在服务器存储的路径--获得头像图片在服务器存储的路径
String path = request.getSession().getServletContext().getRealPath( "/upload");
//2.5判断文件不存在则创建文件
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
//2.6把图片文件写人到 指定路径 指定名字 存储起来
upload.write( path+"/"+fileName);
//3.补充用户头像图片的完整路径,存入User对象
user.setUserImg("upload/"+fileName);
//执行数据库的插入,把user对象的值插入数据库中
boolean flag = userService.insert(user);
if(flag){
response.sendRedirect("index.jsp");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
使用MD5进行密码加密
MD5加密
- MD5算法为计算机安全领域广泛使用的一种散列函数,用于提供消息的完整性,是计算机广泛使用的哈希算法之一
- MD5的固定长度为128比特,16字节,通常用他的16进制字面值输出他,是一个长度为32位的字符串。
MD5特点
- 长度固定(无论输入多少字节,输出总是16字节)
- 不可逆(从结果无法反推原始数据)
- 具有高度的离散性(输出的16字节数据,没有任何规律可言,无法预测结果)
- 抗碰撞性(在原始数据固定的情况下,几乎不会出现两个数据的MD5相同)
MD5应用场景
- 用户密码保护:在保存用户密码时,不记录密码本身,只记录密码的MD5结果(即使数据库被盗也无法反推出明文)
- 文件完整性校验:先在发送端计算一次文件的MD5,并把结果发送给接收端,接收端在接受文件后也计算一次MD5,两次结果一致文件完整。
- 云盘秒传:云盘上传时计算MD5,并在自己的数据库中搜索一下 MD5是否存在,存在则使用已有的文件就可以了,从而实现云盘秒传。
- 数字签名:发布程序时同时发布其MD5,下载后比较MD5是否相同,就可知道程序是否被篡改。
代码展示
public class Test01 {
public static void main(String[] args) {
//创建加密类对象,使用MD5加密规则
Digester md5 = new Digester(DigestAlgorithm.MD5);
String pwd = md5.digestHex("123");
System.out.println(pwd);
}
}
控制台输出
MD5加盐加密
实现方式
package com.zhan.util;
import java.security.MessageDigest;
import java.util.Random;
public class MD5Utils {
/**
* byte[]字节数组 转换成 十六进制字符串
*
* @param arr 要转换的byte[]字节数组
*
* @return String 返回十六进制字符串
*/
private static String hex(byte[] arr) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < arr.length; ++i) {
sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
}
/**
* MD5加密,并把结果由字节数组转换成十六进制字符串
*
* @param str 要加密的内容
*
* @return String 返回加密后的十六进制字符串
*/
private static String md5Hex(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(str.getBytes());
return hex(digest);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.toString());
return "";
}
}
/**
* 生成含有随机盐的密码
*
* @param password 要加密的密码
*
* @return String 含有随机盐的密码
*/
public static String getSaltMD5(String password) {
// 生成一个16位的随机数
Random random = new Random();
StringBuilder sBuilder = new StringBuilder(16);
sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
int len = sBuilder.length();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
sBuilder.append("0");
}
}
// 生成最终的加密盐
String salt = sBuilder.toString();
password = md5Hex(password + salt);
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = password.charAt(i / 3 * 2);
char c = salt.charAt(i / 3);
cs[i + 1] = c;
cs[i + 2] = password.charAt(i / 3 * 2 + 1);
}
return String.valueOf(cs);
}
/**
* 验证加盐后是否和原密码一致
*
* @param password 原密码
*
* @param password 加密之后的密码
*
*@return boolean true表示和原密码一致 false表示和原密码不一致
*/
public static boolean getSaltverifyMD5(String password, String md5str) {
char[] cs1 = new char[32];
char[] cs2 = new char[16];
for (int i = 0; i < 48; i += 3) {
cs1[i / 3 * 2] = md5str.charAt(i);
cs1[i / 3 * 2 + 1] = md5str.charAt(i + 2);
cs2[i / 3] = md5str.charAt(i + 1);
}
String Salt = new String(cs2);
return md5Hex(password + Salt).equals(String.valueOf(cs1));
}
public static void main(String[] args) {
// 原密码
String plaintext = "123456";
// 获取加盐后的MD5值
String ciphertext = MD5Utils.getSaltMD5(plaintext);
System.out.println("加盐后MD5:" + ciphertext);
System.out.println("是否是同一字符串:" + MD5Utils.getSaltverifyMD5(plaintext, ciphertext));
}
}
控制台输出
MD5和SHA-1混合加盐加密
实现方式
package com.zhan.util;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
public class MD5Utils {
/**
* md5和sha-1混合加密
*
* @param inputText 要加密的内容
*
* @return String md5和sha-1混合加密之后的密码
*/
public static String md5AndSha(String inputText) {
return sha(md5(inputText));
}
/**
* md5加密
*
* @param inputText 要加密的内容
*
* @return String md5加密之后的密码
*/
public static String md5(String inputText) {
return encrypt(inputText, "md5");
}
/**
* sha-1加密
*
* @param inputText 要加密的内容
*
* @return sha-1加密之后的密码
*/
public static String sha(String inputText) {
return encrypt(inputText, "sha-1");
}
/**
* md5或者sha-1加密
*
* @param inputText 要加密的内容
*
* @param algorithmName 加密算法名称:md5或者sha-1,不区分大小写
*
* @return String md5或者sha-1加密之后的结果
*/
private static String encrypt(String inputText, String algorithmName) {
if (inputText == null || "".equals(inputText.trim())) {
throw new IllegalArgumentException("请输入要加密的内容");
}
if (algorithmName == null || "".equals(algorithmName.trim())) {
algorithmName = "md5";
}
String encryptText = null;
try {
MessageDigest m = MessageDigest.getInstance(algorithmName);
m.update(inputText.getBytes("UTF8"));
byte s[] = m.digest();
return hex(s);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return encryptText;
}
/**
* byte[]字节数组 转换成 十六进制字符串
*
* @param arr 要转换的byte[]字节数组
*
* @return String 返回十六进制字符串
*/
private static String hex(byte[] arr) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < arr.length; ++i) {
sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
}
/**
* 生成含有随机盐的密码
*
* @param password 要加密的密码
*
* @return String 含有随机盐的密码
*/
public static String getSaltMd5AndSha(String password) {
// 生成一个16位的随机数
Random random = new Random();
StringBuilder sBuilder = new StringBuilder(16);
sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
int len = sBuilder.length();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
sBuilder.append("0");
}
}
// 生成最终的加密盐
String salt = sBuilder.toString();
password = md5AndSha(password + salt);
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = password.charAt(i / 3 * 2);
char c = salt.charAt(i / 3);
cs[i + 1] = c;
cs[i + 2] = password.charAt(i / 3 * 2 + 1);
}
return String.valueOf(cs);
}
/**
* 验证加盐后是否和原密码一致
*
* @param password 原密码
*
* @param password 加密之后的密码
*
*@return boolean true表示和原密码一致 false表示和原密码不一致
*/
public static boolean getSaltverifyMd5AndSha(String password, String md5str) {
char[] cs1 = new char[32];
char[] cs2 = new char[16];
for (int i = 0; i < 48; i += 3) {
cs1[i / 3 * 2] = md5str.charAt(i);
cs1[i / 3 * 2 + 1] = md5str.charAt(i + 2);
cs2[i / 3] = md5str.charAt(i + 1);
}
String salt = new String(cs2);
String encrypPassword = md5AndSha(password + salt);
// 加密密码去掉最后8位数
encrypPassword = encrypPassword.substring(0 , encrypPassword.length() - 8);
return encrypPassword.equals(String.valueOf(cs1));
}
public static void main(String[] args) {
// 原密码
String plaintext = "123456";
// 获取加盐后的MD5值
String ciphertext = MD5Utils.getSaltMd5AndSha(plaintext);
System.out.println("加盐后MD5:" + ciphertext);
System.out.println("是否是同一字符串:" + MD5Utils.getSaltverifyMd5AndSha(plaintext, ciphertext));
}
}
控制台输出
项目创建工具类
Druid(德鲁伊)
Druid连接池是阿里巴巴开源的数据库连接池项目
功能强大,性能优秀,是Java语言最好的数据库连接池之一
3.Driud使用步骤
- 导入jar包druid-1.1.12.jar
- 定义配置文件.properties
- 加载配置文件
- 获取数据库连接池对象
- 获取连接
jdbc.properties
JDBCUtil.java
/**
*数据库连接工具类
*/
public class JDBCUtil {
//定义数据源
private static DataSource dataSource;
/**
* 静态代码块:编译后自动执行
* 加载配置文件,获得数据库的数据源
*/
static {
//在src根日英下陵最jdbc的配置文件,获想一个输入减
InputStream inputStream = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
//创建Properties对象,加载输入流
Properties properties = new Properties();
properties.load(inputStream);
//使用Druid连接池技术管理数据库的数据源
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 通过阿里巴巴的德鲁伊连接池获得数据库连接
* @return
*/
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 资源的释放
* @param rs
* @param ps
* @param conn
*/
public static void close(ResultSet rs, PreparedStatement ps,Connection conn){
try {
DbUtils.close(rs);
DbUtils.close(ps);
DbUtils.close(conn);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
dao层
实现类
public class UserDaoImpl implements UserDao {
private QueryRunner queryRunner = new QueryRunner();
private Connection conn = JDBCUtil.getConnection();
private String sql = null;
@Override
public List<User> selectAll() throws SQLException {
sql ="select * from t_user";
//指定结果集要封装到哪个实体类
BeanListHandler<User> beanListHandler = new BeanListHandler<User>(User.class);
//传入连接对象,sql语句,表字段和实体类属性映射关系的处理类
List<User> userList = queryRunner.query(conn, sql, beanListHandler);
return userList;
}
@Override
public User insert(User user) throws SQLException {
sql="insert into t_user(uname,pwd,realname,sex,address,userImg,salt)values(?,?,?,?,?,?,?)";
BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
//执行插入后把带主键的信息返回
user = queryRunner.insert(conn, sql, beanHandler, user.getUname(), user.getPwd(),
user.getRealname(), user.getSex(), user.getAddress(), user.getUserImg(),
user.getSalt());
return user;
}
@Override
public User selectByName(String uname) throws SQLException {
sql="select * from t_user where uname=?";
BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
User user = queryRunner.query(conn,sql,beanHandler,uname);
// System.out.println(user);
return user;
}
}
service层
实现类
public class UserServiceImpl implements UserService {
UserDao userDao = new UserDaoImpl();
Digester md5=new Digester(DigestAlgorithm.MD5);
@Override
public List<User> selectAll() {
try {
return userDao.selectAll();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 注册时需要把用户的输入密码进行MD5加密,然后存储到数据库中
* @param user
* @return
*/
@Override
public boolean insert(User user) {
try {
//定义加密类,设置加密规则为MD5
Digester md5=new Digester(DigestAlgorithm.MD5);
//MD5还可以加盐,确保密码更加安全
String salt= UUID.randomUUID().toString().replace("-","").toUpperCase(); //随机UUID作为盐
md5.setSalt(salt.getBytes()); //加密规则加入盐值
//对原始密码进行MD5加密,获得加密后的密码
String md5Pwd=md5.digestHex(user.getPwd());
user.setPwd(md5Pwd);
user.setSalt(salt);
User insert = userDao.insert(user);
if(insert!=null){
return true;
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
/**
* 登录时需要把用户输入的密码进行MD5加密后与数据库的进行比对
* @param uname
* @return
*/
@Override
public User selectByName(String uname) {
try {
//把原始密码进行MD5加密后比对数据库的密码
return userDao.selectByName(uname);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
验证码
方式一
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页</title>
<script src="js/jquery.min.js"></script>
<script>
window.onload=function(){
var img =document.getElementById("getCode");
img.onclick=function(){
var date = new date().getTime();
img.src="getCode"+date;
}
}
</script>
</head>
<body>
<h2>文件上传</h2>
<!--图片上传需要设置enctype为multipart/form-data,以二进制进行传输-->
<form action="login" method="post">
用户:<input type="text" name="uname" value=""> <br/>
密码:<input type="password" name="pwd" value=""><br/>
验证码:<input type="text" name="yzm" value="">
<img src="getCode"><a id="change" href="">看不清换一张</a> <br/>
<input type="submit" value="登录"> <a href="register.jsp">去注册</a>
</form>
</body>
</html>
@WebServlet("/getCode")
public class GetCode extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//生成圆形干扰的验证码图片,设置宽度、高度、验证码数量、干扰数量
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(80, 30, 4, 10);
//CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200,100,6,100);
// LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200,100 6,100);
//获取生成的验证码并打印输出
String code = captcha.getCode();
// System.out.println("随机的验证码为:"+code);
//把验证码写入响应的输出流
captcha.write(response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
效果:点击超链接切换验证码
方式二
@WebServlet("/getCode")
public class GetCode extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//生成圆形干扰的验证码图片,设置宽度、高度、验证码数量、干扰数量
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(80, 30, 4, 10);
// CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200,100,6,100);
// LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200,100 6,100);
// captcha.setBackground(new Color(99,97,255));
// captcha.setFont(new Font("隶书",1,36));
// captcha.setTextAlpha(0.5F);
//获取生成的验证码并打印输出
String code = captcha.getCode();
// System.out.println("随机的验证码为:"+code);
//把验证码值存入session域,方便用户登录的时候进行比对
request.getSession().setAttribute("code",code);
//把验证码写入响应的输出流
captcha.write(response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
zhuye.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
<style>
img{
width: 200px;
height: 200px;
border-radius: 50%;
}
</style>
</head>
<body>
<h2>欢迎来到主页!</h2>
<div>
<%-- ${user}--%>
${user.uname}<br/>
<img src="${user.userImg}">
</div>
</body>
</html>
servlet层
登录和验证码判断
@WebServlet("/login")
public class UserLogin extends HttpServlet {
UserService userService = new UserServiceImpl();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
String uname = request.getParameter("uname");
String pwd = request.getParameter("pwd");
String code = request.getParameter("code");
// System.out.println(uname);
// System.out.println(pwd);
// System.out.println(code);
//判断验证码
if(code!=null && code.equals(request.getSession().getAttribute("code"))){
User user = userService.selectByName(uname);
if(user!=null){
//创建加密类对象,使用MD5加密规则
Digester md5 = new Digester(DigestAlgorithm.MD5);
md5.setSalt(user.getSalt().getBytes());//md5加入用户的盐
if(md5.digestHex(pwd).equals(user.getPwd())){//加盐加密后 和数据库存的安全密码一致
request.getSession().setAttribute("user",user);
response.sendRedirect("zhuye.jsp");
}else{
request.setAttribute("error","密码错误!");
request.getRequestDispatcher("index.jsp").forward(request,response);
}
}else{
request.setAttribute("error","帐号不存在!");
request.getRequestDispatcher("index.jsp").forward(request,response);
}
}else{
request.setAttribute("error","验证码错误!");
request.getRequestDispatcher("index.jsp").forward(request,response);
}
}
}
效果图:点击登录跳转主页展示头像