1. 程式人生 > >第一個SSM前端專案(六):完善註冊後端處理並設定郵箱啟用模式

第一個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、註冊成功後,資料庫使用者表多一條記錄,郵箱多一封啟用郵件,頁面跳轉至啟用頁面