第一個SSM前端專案(六):完善註冊後端處理並設定郵箱啟用模式
一、註冊功能後端設計
二、根據設計可以看出我們需要redis來做啟用碼的儲存工作,因此需要在框架中繼承redis
1) 在linux伺服器中安裝redis(建議在伺服器中直接安裝,這樣正式執行的時候比較好操作),可以檢視此篇文章:騰訊雲CentOS 7.4 64位安裝Redis並開啟遠端連線
2) 在resource目錄下新增redis.properties檔案,設定redis的相關屬性(與資料庫設定原理相同)
#定義redis的伺服器地址 ip=123.207.71.72 #定義redis的埠(預設埠) port=6379 #定義使用的是redis的哪個庫,從0開始 database=0 #定義最大連線數 maxActive=1024 #定義最大空閒 maxIdle=200 #定義最大等待時間 maxWait=1000
3) 在spring的資料夾中新增spring-redis.xml的整合檔案,並配置以下內容
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--定義redis連線池,使用jedis來繼承--> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" > <property name="maxIdle" value="${maxIdle}" /> <property name="maxWaitMillis" value="${maxWait}" /> <!--檢測連結的可用性--> <property name="testOnBorrow" value="true" /> </bean> <!--配置redis資料來源--> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${ip}"></property> <property name="port" value="${port}"></property> <property name="database" value="${database}"></property> <property name="poolConfig" ref="poolConfig"></property> </bean> <!--將redis資料來源注入到redis的模板中,呼叫模板來完成redis的操作--> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory"></property> <!-- 對於中文的儲存,物件的儲存 需要進行序列化操作儲存 --> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> </bean> </beans>
4)在spring-application.xml中增加對redis的配置檔案的載入
<!--載入配置檔案,便於讀取配置檔案的屬性--> <bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="locations"> <list> <!--資源路徑--> <value>classpath:db.properties</value> <value>classpath:redis.properties</value> </list> </property> </bean>
5)在web.xml中新增對於spring-redis.xml的檔案載入
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:spring/spring-application.xml,
classpath*:spring/spring-redis.xml
</param-value>
</context-param>
6)在pom包中引入對redis的相關依賴
<!--spring-data-redis版本號 -->
<spring.data.redis.version>1.7.1.RELEASE</spring.data.redis.version>
<!-- spring-data-redis整合依賴 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>${spring.data.redis.version}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
7)進行測試,檢視redis是否整合成功,訪問以下Controller檢視控制檯是否可以打出123456;若有該記錄則代表整合成功
package cn.com.gulu.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(value = "/test")
public class TestController
{
//注入配置檔案中配置的bean
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* ceshi
*/
@RequestMapping(value = "/test")
public String test()
{
redisTemplate.opsForValue().set("ceshi", "123465");
System.out.println(redisTemplate.opsForValue().get("ceshi"));
return "";
}
}
三、設計加密機制
1)密碼加密由密碼+固定字串通過MD5生成32位的字串進行加密儲存資料庫
2)郵件啟用碼由郵箱賬號+固定字串通過MD5生成32位字串加密後再發送到使用者的郵箱
3) 因此可以自己設計一個加密工具類進行操作(也可以呼叫其餘的加密介面等)
4) Md5加密工具類如下:
package cn.com.gulu.util;
import java.security.MessageDigest;
/**
* 加密工具類
*
* @author Administrator
*
*/
public class Md5Util
{
/**
* 把字串通過md5加密成陣列
*
* @throws Exception
*/
public static byte[] encodeByte(String target) throws Exception
{
// java自帶的安全工具類 指定加密方式
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.reset(); // 重置
digest.update(target.getBytes("utf-8")); // 將位元組陣列放入加密工具中
return digest.digest(); // 進行加密操作,返回加密後的位元組陣列
}
/**
* 返回32位加密字串
*/
public static String encodeString(String target)
{
try
{
byte[] encodeByte = encodeByte(target);// 先加密成位元組陣列
StringBuffer sbBuffer = new StringBuffer();
for (int i = 0; i < encodeByte.length; i++)
{
String encodeIndex = Integer.toHexString(0xff & encodeByte[i]); // 補位
if (encodeIndex.length() == 1)
{
sbBuffer.append("0"); // 補位
}
sbBuffer.append(encodeIndex);
}
return sbBuffer.toString();
}
catch (Exception e)
{
e.printStackTrace();
}
return "";
}
}
四、設計郵件傳送工具類
1)因為涉及到郵件傳送的工作,因此可考慮使用smtp傳送郵件服務(參考開通網易163郵箱的smtp服務),最終拿到授權碼
2) 新建一個SendEmailUtil的工具類專用於傳送郵件啟用碼,利用javax.mail的工具jar包來實現功能,因此pom包需要引入相關依賴
<!--mail 相關依賴 -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
3)郵件工具類設計如下
package cn.com.gulu.util;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
/**
* 傳送郵件工具類
* @author Administrator
*
*/
public class SendEmailUtil
{
/**
* 傳送郵件
* @param email 目標郵箱
* @param vilidationCode 啟用碼
* @throws MessagingException
* @throws AddressException
*/
public static void sendEmail(String email,String vilidationCode) throws AddressException, MessagingException
{
String host="smtp.163.com"; //服務商
String from = "[email protected]";//傳送郵箱
String to = email; //接受郵箱
//獲取系統變數
Properties properties = System.getProperties();
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.auth", "true"); // smtp許可權驗證
SendEmailAuthUtil authUtil=new SendEmailAuthUtil(from,ConstUtil.EMIALAUTH);
//建立javaMail執行的環境資訊
Session defaultInstance = Session.getDefaultInstance(properties, authUtil);
//郵件資訊載體,封裝者所有的郵件資訊MimeMessage 是Message的實現類
MimeMessage message=new MimeMessage(defaultInstance);
//設定發件箱地址
message.setFrom(new InternetAddress(from));
//設定收件地址(接受者型別和地址,to是主要接收人,還有抄送人,祕密抄送人等)
message.addRecipients(Message.RecipientType.TO, to);
//設定郵件標題
message.setSubject("咕嚕網啟用郵件通知");
//設定郵件正文(內容,格式),點選超連結後訪問專案的某個方法即可
String neirong="<a href=\""+PathUtil.getPathWebAddress()+"activeMail/activeMail?email="+from+"&vilidationCode="+vilidationCode+"\" target=\"_blank \">請於24小時內點選啟用</a>";
//因為存在漢字,所以直接用gb2312
message.setContent(neirong, "text/html;charset=gb2312");
message.saveChanges();
Transport.send(message); //傳送郵件
}
/**
* 定義郵箱許可權驗證內部類
*/
public static class SendEmailAuthUtil extends Authenticator
{
private String user; //郵箱
private String password; //授權碼
public SendEmailAuthUtil(String user,String password )
{
this.user=user;
this.password=password;
}
//許可權驗證
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user, password);
}
}
}
五、設計後臺註冊方法
package cn.com.gulu.controller;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.sun.jmx.snmp.UserAcl;
import cn.com.gulu.entity.User;
import cn.com.gulu.service.UserService;
import cn.com.gulu.util.ConstUtil;
import cn.com.gulu.util.Md5Util;
import cn.com.gulu.util.SendEmailUtil;
import cn.com.gulu.util.UuidUtil;
/**
* 註冊類
*
* @author Administrator
*
*/
@Controller
@RequestMapping(value = "/register")
public class RegisterController
{
@Autowired
private UserService userService;
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 註冊後臺方法
*/
@RequestMapping(value = "/register")
public String register(Model model, String phone, String email,
String password, String nickName, String code,
HttpServletRequest request)
{
//校驗驗證碼
if(StringUtils.isBlank(code))
{
model.addAttribute("error", "非法註冊");
return "../../register";
}
Object attribute = request.getSession().getAttribute(ConstUtil.VALIDATIONCODE);
if(attribute==null)
{
model.addAttribute("error", "驗證碼已超時");
return "../../register";
}else if(!code.equalsIgnoreCase(attribute.toString()))
{
model.addAttribute("error", "驗證碼錯誤");
return "../../register";
}
//防止通過url提交連結過來,因此需要校驗郵箱和手機號
User user=userService.findByEmail(email);
User user2=userService.findByPhone(phone);
if(user!=null||user2!=null)
{
model.addAttribute("error", "非法註冊");
return "../../register";
}
user=new User();
user.setId(UuidUtil.get32Uuid()); //設定成32位隨機id
user.setEmail(email);
user.setPhone(phone);
user.setNick_name(nickName);
user.setIs_active(false);
user.setCreate_time(new Date());
//進行密碼加密
String newPassword=Md5Util.encodeString(password+ConstUtil.ENCODE);
user.setPassword(newPassword);
userService.save(user);
//生成郵件啟用碼
String emailCode=Md5Util.encodeString(email+ConstUtil.ENCODE);
//存入redis並設定24小時有效
redisTemplate.opsForValue().set(email, emailCode,24, TimeUnit.HOURS);
//傳送郵件
try
{
SendEmailUtil.sendEmail(email, emailCode);
}
catch (Exception e)
{
e.printStackTrace();
}
//跳轉註冊成功頁面
String message = email + "," + emailCode;
model.addAttribute("message", message);
return "regist/registerSuccess";
}
}
六、測試註冊是否成功,並校驗是否收到啟用郵件
1、訪問註冊頁面,提交資訊點選註冊
2、註冊成功後,資料庫使用者表多一條記錄,郵箱多一封啟用郵件,頁面跳轉至啟用頁面