首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java EE 郵箱驗證註冊系統:從資料庫設計到 JavaMail 完整實作

     編輯:Java 相關知識

系統架構

採用經典 Java EE (Servlet + JSP + JDBC + JavaMail) 分層架構:

  • 資料層:MySQL + C3P0 連線池 + DbUtils
  • 業務層:DAO / Service 介面與實作
  • 表現層:Servlet 控制器 + JSP 視圖 (JSTL)
  • 郵件層:非同步執行緒發送驗證信 (JavaMail API)

資料庫設計

CREATE TABLE `user` (
  `id`       CHAR(32) PRIMARY KEY,      -- UUID 無連字號
  `name`     VARCHAR(30) NOT NULL,
  `pwd`      VARCHAR(20) NOT NULL,
  `email`    VARCHAR(50) NOT NULL,
  `active`   CHAR(1) DEFAULT '0',       -- 0=未驗證, 1=已驗證
  `acode`    CHAR(32)                   -- 驗證碼 (UUID)
);

核心程式碼模組

1. 實體類 User.java

public class User {
    private String id, name, pwd, email, active, acode;
    // 標準 Getter/Setter、equals/hashCode (依 id)
}

2. 連線池 C3p0Pool.java

public class C3p0Pool {
    private static DataSource ds = new ComboPooledDataSource("hncu"); // 讀 c3p0-config.xml
    private static ThreadLocal tl = new ThreadLocal<>();
    
    public static Connection getCon() throws SQLException {
        Connection con = tl.get();
        if (con == null) { con = ds.getConnection(); tl.set(con); }
        return con;
    }
    // 提供 DataSource 給 DbUtils 使用
    public static DataSource getPool() { return ds; }
}

c3p0-config.xml 設定 `named-config name="hncu"`,含驅動、URL、帳密、池大小參數。

3. DAO 層 RegDaoJdbc.java

public class RegDaoJdbc implements RegDAO {
    private QueryRunner qr = new QueryRunner(C3p0Pool.getPool());
    
    public User reg(User user) {
        String sql = "INSERT INTO user(id,name,pwd,email,active,acode) VALUES(?,?,?,?,?,?)";
        String id = UUID.randomUUID().toString().replace("-", "");
        String acode = UUID.randomUUID().toString().replace("-", "");
        qr.update(sql, id, user.getName(), user.getPwd(), user.getEmail(), "0", acode);
        user.setId(id); user.setAcode(acode); user.setActive("0");
        return user;
    }
    
    public User active(String acode) {
        User user = qr.query("SELECT * FROM user WHERE acode=?", new BeanHandler<>(User.class), acode);
        if (user != null) {
            qr.update("UPDATE user SET active='1', acode='' WHERE acode=?", acode);
        }
        return user;
    }
}

4. Service 層 RegService.java

public class RegService implements IRegService {
    private RegDAO dao = new RegDaoJdbc();
    public User reg(User user) { return dao.reg(user); }
    public User active(String acode) { return dao.active(acode); }
}

5. 註冊 Servlet - 非同步發信


@WebServlet("/RegServlet")
public class RegServlet extends HttpServlet {
    private IRegService service = new RegService();
    
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        User user = new User();
        user.setName(req.getParameter("name"));
        user.setPwd(req.getParameter("pwd"));
        user.setEmail(req.getParameter("email"));
        
        user = service.reg(user);
        if (user != null) {
            resp.getWriter().print("註冊成功,請至信箱驗證");
            new SendMailThread(user.getAcode()).start(); // 非同步發信
        } else {
            resp.getWriter().print("註冊失敗");
        }
    }
}

6. 郵件發送執行緒 SendMailThread.java


public class SendMailThread extends Thread {
    private String acode;
    private static final Logger log = Logger.getLogger(SendMailThread.class);
    
    public SendMailThread(String acode) { this.acode = acode; }
    
    public void run() {
        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.sina.com");
        props.put("mail.smtp.auth", "true");
        
        Session session = Session.getInstance(props, new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("your_email@sina.com", "password");
            }
        });
        session.setDebug(true); // 除錯輸出 SMTP 交互
        
        try {
            MimeMessage msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress("your_email@sina.com"));
            msg.setRecipient(Message.RecipientType.TO, new InternetAddress("user@qq.com")); // 實際應用用 user.getEmail()
            msg.setSubject("啟用帳號");
            
            StringBuilder sb = new StringBuilder();
            sb.append("請點擊啟用: <a href='https://localhost:8080/mailWeb/ActiveServlet?acode=")
              .append(acode).append("'>啟用連結</a><br/>");
            sb.append("或複製: https://localhost:8080/mailWeb/ActiveServlet?acode=").append(acode);
            
            msg.setContent(sb.toString(), "text/html;charset=utf-8");
            Transport.send(msg);
            log.info("郵件發送成功");
        } catch (MessagingException e) {
            log.error("郵件發送失敗", e);
        }
    }
}

7. 啟用 Servlet ActiveServlet.java


@WebServlet("/ActiveServlet")
public class ActiveServlet extends HttpServlet {
    private IRegService service = new RegService();
    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        String acode = req.getParameter("acode");
        User user = service.active(acode);
        req.setAttribute("user", user);
        req.getRequestDispatcher("/jsps/result.jsp").forward(req, resp);
    }
}

8. 前端頁面 (JSTL)

index.jsp:登入/註冊入口

reg.jsp:註冊表單 (姓名、密碼、Email)

result.jsp:啟用結果頁,5 秒倒數跳回首頁

依賴 JAR 清單

  • c3p0-0.9.1.2.jar
  • commons-dbutils-1.4.jar
  • javax.mail-1.4.4.jar (或 jakarta.mail)
  • mysql-connector-java-5.1.34.jar
  • log4j, jstl, standard.jar 等

安全與優化建議

議題建議
密碼明文儲存**必須** 使用 BCrypt/Argon2 雜湊:`BCrypt.hashpw(pwd, BCrypt.gensalt())`
SQL 注入已使用 DbUtils 參數化查詢,安全
驗證碼暴力破解UUID 32 字元空間極大,但建議加上**過期時間** (如 24 小時)
郵件發送失敗重試引入重試機制 (指數退避) 或訊息佇列 (RabbitMQ/Kafka)
非同步執行緒管理生產環境請用 **線程池** (ExecutorService) 而非直接 `new Thread()`
SMTP 憑證硬編碼移至設定檔/環境變數/密碼管理系統
CSRF 保護表單加入 CSRF Token

總結

本系統示範了 Java EE 郵箱驗證註冊的完整閉環:

    1. 使用者提交註冊資訊 2. 後端產生 UUID 驗證碼、存入資料庫 (active=0) 3. 非同步執行緒發送含驗證連結的 HTML 郵件 4. 使用者點擊連結 → ActiveServlet 驗證碼比對 → 更新 active=1、清空 acode 5. 前端提示成功並倒數導回登入頁

架構清晰、分層分明,是進階 Spring Boot、JPA、Thymeleaf、Redis 快取驗證碼、OAuth2 整合的絕佳基礎專案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved