【版本】
当前版本号v20211111
版本 | 修改说明 |
---|---|
v20211111 | 初始化版本 |
【实验名称】 实验7.1 完善用户密码加密功能
【实验目的】
- 掌握密码加密的编程和实现
【实验环境】
- 内存:至少4G
- 硬盘:至少空余10G
- 操作系统: 64位 Windows系统。
【实验资源】
下载地址:
链接:https://pan.baidu.com/s/1lwTbxGGCKKzC7TPXSgeVzQ
提取码:heis
【实验说明】
- 作为企业级应用,存储用户的明文密码是非常不专业而且充满安全风险的行为。因此我们要对用户的密码进行单向的加密(通过密文无法反向推出明文)。单向加密一般使用
消息摘要算法
实现,常见的消息摘要算法有以下几种:
- MD 系列算法包括 MD2、MD4 和 MD5 共 3 种算法。但是 MD5 已经在 2004 年被证明存在冲突,已不适用于安全认证。
- SHA 算法主要包括其代表算法 SHA-1 和 SHA-1 算法的变种 SHA-2 系列算法(包含 SHA-224、SHA-256、SHA-384 和 SHA-512);
- MAC 算法综合了上述两种算法,主要包括 HmacMD5、HmacSHA1、HmacSHA256、HmacSHA384 和 HmacSHA512 算法。
- 单向加密的常用做法,是通过给用户明文密码加上一个随机的字符串(salt,中文翻译为盐)。然后再对加盐的密码进行单向加密。得到密文再加盐,再次进行单向加密。如此循环数次,再存储最终的密文,达到较为安全的加密效果。
//第1次加密
密文1=加密算法计算(明文密码+盐)
//第2次加密
密文2=加密算法计算(密文1+盐)
...
第N次加密
密文N=加密算法计算(密文(N-1)+盐)
【实验要求】
- 完善用户的密码加密功能。表
tab_user
增加字段salt
,用于存储盐
。同时修改tab_user
增加字段password
的长度为128。请在src/main/resources/db/migration
目录下新增 SQL 脚本完成对数据库的修改。
字段 | 修改说明 |
---|---|
tab_user.salt | 新增,可变长字符串,最大长度8 |
tab_user.password | 修改,长度修改为128 |
- 修改原有明文存储的代码,修改为通过加盐(随机字符串)和使用 SHA-256 循环3次实现加密,并把密文存储在
tab_user.password
字段,盐存储在tab_user.salt
字段。
【实验提示和注意事项】
增加数据库字段以后注意修改实体类
User
。SHA256 加密方法。
- pom.xml 增加依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
- SHA256 加密实现
package com.zjtec.travel.util;
import com.alibaba.druid.sql.visitor.functions.Hex;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MsgDigestUtils {
/**
* SHA256 加密
* @param str 明文
* @return 密文
*/
public static String encodeSHA256(String str){
MessageDigest messageDigest;
String encdeStr = "";
try {
messageDigest = MessageDigest.getInstance("SHA-256");
byte[] hash = messageDigest.digest(str.getBytes("UTF-8"));
encdeStr = byte2Hex(hash);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return encdeStr;
}
private static String byte2Hex(byte[] bytes){
StringBuffer stringBuffer = new StringBuffer();
String temp = null;
for (int i=0;i<bytes.length;i++){
temp = Integer.toHexString(bytes[i] & 0xFF);
if (temp.length()==1){
//1得到一位的进行补0操作
stringBuffer.append("0");
}
stringBuffer.append(temp);
}
return stringBuffer.toString();
}
}
【实验名称】 实验7.2 完成旅游产品详细信息页面动态数据加载
【实验目的】
- 掌握 SSM 的编程和实现
【实验环境】
- 内存:至少4G
- 硬盘:至少空余10G
- 操作系统: 64位 Windows系统。
【实验资源】
下载地址:
链接:https://pan.baidu.com/s/1lwTbxGGCKKzC7TPXSgeVzQ
提取码:heis
【实验要求】
- 目前用户点击旅游产品的
查看详情
,调转到的链接是一个静态的页面。http://localhost:8082/route_detail.html。请完善该功能,实现点击某项旅游产品的查看详情
可以跳转到旅游产品的详细信息页面,并真正加载对应的产品的信息(下图2中红框的部分都是动态内容)。
【实验提示和注意事项】
- 该功能涉及到获取2个表格的数据,分别是
tab_route
和tab_seller
,以下为2个表字段说明。
tab_route
旅游产品信息表
字段 | 说明 |
---|---|
rid | 旅游产品唯一ID |
rname | 产品名称 |
price | 价格 |
routeIntroduce | 产品介绍 |
cid | 产品目录ID |
rimage | 产品图片 |
sid | 经营商家ID |
tab_seller
经营商家信息表
字段 | 说明 |
---|---|
sid | 唯一ID |
sname | 经营商家名称 |
consphone | 经营商家联系方式 |
address | 经营商家地址 |
【实验名称】 实验7.3 完成邮件发送功能
【实验目的】
- 掌握发送邮件的相关的编程和实现
【实验环境】
- 内存:至少4G
- 硬盘:至少空余10G
- 操作系统: 64位 Windows系统。
【实验资源】
下载地址:
链接:https://pan.baidu.com/s/1lwTbxGGCKKzC7TPXSgeVzQ
提取码:heis
【实验要求】
实现邮件的发送功能。邮件的发送需要我们准备一个发送方的邮箱,这里推荐使用139 邮箱。点击这里注册
注册邮箱以后,勾选
开启IMAP/SMTP服务
,并生成授权码,注意记录你授权码。在用户注册成功以后,给用户发送激活邮件,邮件内附激活链接。
【实验提示和注意事项】
- 发送邮件的代码参考。注意注入的各个属性的设置。
package com.zjtec.travel.service.impl;
import com.zjtec.travel.service.EmailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
@Service
public class EmailServiceImpl implements EmailService {
private final static Logger log= LoggerFactory.getLogger(EmailServiceImpl.class);
@Value("#{email.smtphost}")
private String smtpHost;//SMTP 地址,例如smtp.139.com
@Value("#{email.username}")
private String username;//发送方邮箱地址
@Value("#{email.password}")
private String password;//密码或授权码
@Value("#{email.smtpauth}")
private String smtpAuth;//设置为true
/**
* 发送邮件
* @param sendTo 对方邮箱地址
* @param title 邮件标题
* @param content 邮件内容
*/
@Override
public void sendEmail(String sendTo, String title, String content) {
try {
final Properties props = new Properties();
props.put("mail.smtp.auth", smtpAuth);
props.put("mail.smtp.host", smtpHost);
// 发件人的账号
props.put("mail.user", username);
//发件人的密码
props.put("mail.password", password);
// 构建授权信息,用于进行SMTP进行身份验证
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
// 用户名、密码
String userName = props.getProperty("mail.user");
String password = props.getProperty("mail.password");
return new PasswordAuthentication(userName, password);
}
};
// 使用环境属性和授权信息,创建邮件会话
Session mailSession = Session.getInstance(props, authenticator);
// 创建邮件消息
MimeMessage message = new MimeMessage(mailSession);
// 设置发件人
String username = props.getProperty("mail.user");
InternetAddress form = new InternetAddress(username);
message.setFrom(form);
// 设置收件人
InternetAddress toAddress = new InternetAddress(sendTo);
message.setRecipient(Message.RecipientType.TO, toAddress);
// 设置邮件标题
message.setSubject(title);
// 设置邮件的内容体
message.setContent(content, "text/html;charset=UTF-8");
// 发送邮件
Transport.send(message);
} catch (Exception e) {
log.error(e.getMessage(),e);
}
}
public void setSmtpHost(String smtpHost) {
this.smtpHost = smtpHost;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setSmtpAuth(String smtpAuth) {
this.smtpAuth = smtpAuth;
}
}