【版本】
当前版本号v20211111
版本 | 修改说明 |
---|---|
v20211111 | 初始化版本 |
【实验名称】 实验7.1 完善用户密码加密功能
【实验目的】
- 掌握密码加密的编程和实现
【实验环境】
- 内存:至少4G
- 硬盘:至少空余10G
- 操作系统: 64位 Windows系统。
【实验资源】
下载地址:
链接:https://pan.baidu.com/s/1qy0QpYbG_dWT8fKx3ZjvnQ 提取码: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/1qy0QpYbG_dWT8fKx3ZjvnQ 提取码: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; } }
复制