率講郵箱驗證功能應該大多數人都使用過,比如:對用戶賬號密碼進行找回,注冊某網站以郵箱作為登錄名激活賬號.....等多個應用場景都需要我們通過郵件進行驗證。此篇教程就是講解如何用Java實現郵箱驗證功能,10分鐘就搞定了,簡單得一匹!
在日常生活中,我們在一個網站中注冊一個賬戶時,往往在提交個人信息后,網站還要求我們通過手機或郵件來驗證,郵件的話大概會是下面這個樣子的:
用戶通過點擊鏈接從而完成注冊,然后才能登錄。也許你會想,為什么要這么麻煩直接提交注冊不就行了嗎?這其中很大一部分原因是為了防止惡意注冊。接下來讓我們一起來使用最簡單的JSP+Servlet的方式來完成一個通過郵箱驗證注冊的小案例吧。
1、了解相關協議:動手實踐之前,你最好對JSP、Servlet、SMTP協議和POP3協議知識有所了解,如果對郵件收發過程完全不了解的話,可以花點時間仔細看一下如下圖:
2、郵箱授權準備:在了解的上述內容之后,要實現這個案例,首先我們還得有兩個郵箱賬號,一個用來發送郵件,一個用來接收郵件。本案例使用QQ郵箱向163郵箱發送激活郵件,因此需要登錄QQ郵箱,在設置->賬戶面板中開啟POP3/SMTP服務,以允許我們通過第三方客戶端發送郵件:進入發件人郵件空間 -> 設置 -> 賬戶 –> 開啟(POP3/SMT)服務 注意:僅限QQ郵箱
圖一
圖二
圖三
還要注意的是,登錄以下服務: POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務時,需要用到授權碼而不是QQ密碼,授權碼是用于登錄第三方郵件客戶端的專用密碼。因此我們需要獲得授權碼,以在后面的程序中使用。
3、需要一個jar包:mail-1.4.7.jar
下載地址:https://mvnrepository.com/artifact/javax.mail/mail/1.4.7
具體步驟如下:
1. 首先創建一個web工程,并加入相關依賴包:
mail-1.4.7.jar 下載地址:https://mvnrepository.com/artifact/javax.mail/mail/1.4.7
2. 使用MySQL創建一張簡單的用戶表:t_user
create table t_user(
id int(11) primary key auto_increment comment '用戶id',
userName varchar(100) not null comment '用戶名',
userEmail varchar(100) not null comment '用戶郵箱',
userPwd varchar(50) not null comment '用戶密碼',
state int(1) not null default 0 comment '用戶激活狀態:0表示未激活,1表示激活',
code varchar(255) not null comment '激活碼'
);
PS:state字段(用來判斷用戶賬號是否激活)和code字段(激活碼)
3. 創建一個注冊頁面
使用JSP創建一個最簡單的注冊頁面(過于簡單,代碼省略):
頁面效果
4. 注冊業務邏輯分析
1、用戶填寫相關信息,點擊注冊按鈕
2、系統先將用戶記錄保存到數據庫中,其中用戶狀態為未激活
3、系統發送一封郵件并通知用戶去驗證
4、用戶登錄郵箱并點擊激活鏈接
5、系統將用戶狀態更改為已激活并通知用戶注冊成功
.................搞清楚了整個流程,實現起來應該就不難了...................
public class Constants {
public static final int CODE_STATUS_EXPIRED = 400;//驗證碼過期或者沒有點擊發送驗證碼
public static final String SEND_EMAIL_ACCOUNT = "2921272303@qq.com";//發件人郵箱賬號
public static final String SEND_EMAIL_CODE = "arnsutissvofzfdshj";//授權碼(自己的)
}
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public int addUser(Users users) {
//注冊生成唯一標識符
String code = UUID.randomUUID().toString().replaceAll("-","");
try {
String newpwd = MD5.getMD5(users.getUser_pwd()).toString();
users.setUser_pwd(newpwd);
users.setCode(code);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
int result = userDao.addUser(users);
if(result > 0){//注冊成功
//獲取發送郵件對象
EmailUtil emailUtil = new EmailUtil(users.getUser_email(),code);
//發起郵箱驗證
new Thread(emailUtil).start();
}
return result;
}
}
package com.cnlm.utils;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.security.GeneralSecurityException;
import java.util.Properties;
import java.util.UUID;
/**
* Created with IntelliJ IDEA.
* User: cnlm
* Date: 2020/09/014 22:30
* Description: JavaMail發送郵件工具類
* QQ郵箱賬戶為發送方,首先需要進入QQ郵箱,找到左上方的設置,然后選擇賬戶,找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務,開啟pop3,獲得授權碼
* Version: V1.0
*/
public class EmailUtil implements Runnable{
private String receiveEmail; // 收件人郵箱
private String uuidCode; // uuid唯一激活碼
public EmailUtil(String receiveEmail, String uuidCode) {
this.receiveEmail = receiveEmail;
this.uuidCode = uuidCode; // 生成唯一隨機碼;
}
@Override
public void run() {
// 1.創建連接對象javax.mail.Session
// 2.創建郵件對象 javax.mail.Message
// 3.發送一封激活郵件
String host = "smtp.qq.com"; // 指定發送郵件的主機smtp.qq.com(QQ)|smtp.163.com(網易)
Properties properties = System.getProperties();// 獲取系統屬性
properties.setProperty("mail.smtp.host", host);// 設置郵件服務器
properties.setProperty("mail.smtp.auth", "true");// 打開認證
//QQ郵箱需要下面這段代碼,163郵箱不需要
try {
//QQ郵箱需要下面這段代碼,163郵箱不需要
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
// 1.獲取默認session對象
Session session = Session.getDefaultInstance(properties, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
// 發件人郵箱賬號、授權碼
return new PasswordAuthentication(Constant.SEND_EMAIL_ACCOUNT, Constant.SEND_EMAIL_CODE);
}
});
// 2.創建郵件對象
Message message = new MimeMessage(session);
// 3.設置發件人
message.setFrom(new InternetAddress(Constant.SEND_EMAIL_ACCOUNT));
// 4.設置收件人
message.addRecipient(Message.RecipientType.TO, new InternetAddress(receiveEmail));
// 5.設置郵件主題
message.setSubject("賬號激活");
String content = "<html><head></head><body>" +
"<h1>這是一封激活郵件,激活請點擊以下鏈接</h1><h3>" +
"<a href='http://localhost:8080/register/checkRegister.do?code="
+ uuidCode + "'>http://localhost:8080/register/checkRegister.do?code=" + uuidCode
+ "</a></h3></body></html>";
message.setContent(content, "text/html;charset=UTF-8");
// 7.發送郵件
Transport.send(message); // 阻塞方法
System.out.println("郵件成功發送!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
PS:自己測試時需修改賬號與授權碼。
完成后,再有用戶提交注冊信息時,應該就能收到驗證郵件了。用戶點擊鏈接后,我們要做的工作就是根據code(利用UUID生成)更改數據庫中相應用戶的狀態,然后提示用戶注冊結果了。
最后總結:
簡單介紹了如何使用JavaMail完成了一個帶郵箱驗證的注冊案例,當然在實際開發中還有許多細節要注意,例如對用戶提交信息的校驗,密碼進行加密等,此處的簡單案例并未詳盡處理這些細節。
學會了嗎?誰在最需要的時候輕輕拍著我肩膀,誰在最快樂的時候愿意和我分享。我是一個包夜敲代碼,想靠技術茍且的程序員。如果覺得有點用的話,請毫不留情地關注、點贊、轉發。這將是我寫出更多優質文章的最強動力!
碼重置、兩步驗證、商業機密、私人對話……電子郵件是大多數生活和商業活動的中心,因此我們必須確保它是可信和真實的。
如果你在使用自己的域名郵箱,證明郵箱真實性的工作就會轉移到你自己的頭上。本指南旨在為你提供所需的相關信息和實踐操作,以保證你域名郵箱的真實性,并減少你受上當受騙的風險。
該指南將介紹域名郵箱安全的三個主要組成部分:用于簽名的DKIM、用于發件人驗證的SPF和用于更嚴格執行其他兩個部分的DMARC。請確保你對DNS有基本的了解,并有使用域名郵箱的經驗。
SPF,全稱“Sender Policy Framework”,即“發送方策略框架”,是最基本的電子郵件驗證技術之一,是最簡單、最常見的保護。通常,服務提供商會提供DNS記錄內容,您只需在設置過程中簡單地復制、粘貼即可。
在DNS解析中,SPF的記錄類型為 TXT。基本格式如下:
"v=spf1 include:spf.httpsmail.com -all"
SPF的核心是一個IP地址列表,被授權從你的域名發送郵件。除此之外,還有其它幾種不同的選項:
以上面的地址spf.httpsmail.com為例,該網址下的所有A類型的解析記錄通過include:選項包含在SPF策略之中。
除了ip地址和包含的主機名之外,還有其它限定符來作為選項的前綴。
每個符號都會向郵件服務器推薦一個不同的策略,默認情況下,如果沒有符號,它被視為等同于“+”,即“通過”。(其它限定符可見:https://datatracker.ietf.org/doc/html/rfc7208#section-4.6.2,主要包括4個:+、-、~和?等,好像“~”用得較多,為“soft-failure”,字面意思是“軟失敗”,接收但是會標記)
在上面的示例中,主要有兩個機制選項:
SPF是一個非常簡單的工具,提供了基本的電子郵件驗證(“允許哪些IP可以發送我的電子郵件”)來進行基本的垃圾郵件過濾。即使只是單獨設置SPF,也會對你的郵件成功投遞有很大幫助。
DKIM,全稱“Domain Keys Identified Mail”,即“域名密鑰識別郵件標準”,另一種安全機制,通過使用非對稱密鑰以加密的方式驗證為你域名郵箱發送郵件的服務器是否有權這樣做。配置DKIM后,接收你郵件的服務器可以在DNS中查找公鑰,并驗證郵件是否從你的域合法發送。
DKIM可防止IP易手或大型服務提供商在客戶之間共享IP空間。如果你說“谷歌IP可以發送我的電子郵件”,是什么阻止其他人從你的域中欺騙電子郵件并從他們自己的谷歌帳戶發送?由于這些IP是共享的,所以它仍將通過SPF檢查,但不會通過DKIM。
DKIM有兩個主要部分:一個是帶有公鑰的DNS記錄,另一個是添加到每個已發送電子郵件中的header(頭部信息),其中包含加密簽名和有關如何查找上述DNS記錄的詳細信息。
DKIM的DNS解析記錄就是一個普通的TXT記錄類型,但目前主要以CNAME記錄類型為主,通用格式為:
<selector>._domainkey.<domain>
“selector”通常由您的電子郵件服務提供商設置,并在您啟用DKIM時提供給您。一些提供商,如Fastmail和Microsoft 365,甚至提供多個選擇器供您設置。例如,對于谷歌來說,它只是一個“google”:
google._domainkey.example.com
DKIM頭部信息被添加在你所發送的每一封郵件中,包含的內容很多,但最主要的是以下兩個部分(其它可見https://datatracker.ietf.org/doc/html/rfc6376#section-3.5):
通過這兩段元數據,收件人的服務器可以重建包含DKIM密鑰的子域并解析它,并根據此密鑰以驗證DKIM簽名和消息是否真實。
DKIM是一個比SPF強得多的檢測垃圾郵件的方法,因為它涉及到實際的數學運算,而不僅僅是一個IP列表。即使你的域名郵箱只配置了SPF和DKIM也已經非常不錯了,但還可以更進一步。
DKIM僅在郵件中有頭部信息時才適用。這意味著非法消息將不會有頭部信息,因此不會發生DKIM驗證。這導致DKIM驗證是“中性”的,而不是“失敗”,因為它被簡單地忽略了。
添加DMARC策略使我們能夠:
DMARC記錄與其他兩個記錄的格式相同,而且非常簡單。下面是一個非常基本的示例:
v=DMARC1; p=quarantine; adkim=s; aspf=s; rua=mailto: test@dmarc.postmarkapp.com;
DMARC是現代電子郵件安全性中最強大的一部分,它的報告可以令人難以置信地洞察哪些垃圾郵件偽裝成你。如果您從本指南中得到了什么,我希望您應該花時間和精力制定嚴格的DMARC政策。
如果你的域名不想發送郵件,可以通過以下設置來防止垃圾郵件以你的名義發送出去。
本文翻譯自:Email Authenticity 101: DKIM, DMARC, and SPF,部分內容有改動,已獲得原作者授權。
現代web開發中,表單是用戶與網站互動的重要方式之一。HTML5為表單提交提供了強大的功能和豐富的輸入類型,讓收集和驗證用戶輸入數據變得更加容易和安全。本文將詳細介紹HTML5表單的各個方面,包括基本結構、輸入類型、驗證方法和提交過程。
HTML表單由<form>標簽定義,它可以包含輸入字段、標簽、按鈕等元素。一個基本的表單結構如下所示:
<form action="/submit_form" method="post">
<label for="name">姓名:</label>
<input type="text" id="name" name="name" required>
<label for="email">電子郵箱:</label>
<input type="email" id="email" name="email" required>
<input type="submit" value="提交">
</form>
在這個例子中,表單有兩個輸入字段:姓名和電子郵箱。每個輸入字段都有一個<label>標簽,這不僅有助于用戶理解輸入的內容,也有助于屏幕閱讀器等輔助技術。<form>標簽的action屬性定義了數據提交到服務器的URL,method屬性定義了提交數據的HTTP方法(通常是post或get)。
HTML5提供了多種輸入類型,以支持不同的數據格式和設備。
<!-- 單行文本 -->
<input type="text" name="username" placeholder="請輸入用戶名" required>
<!-- 密碼 -->
<input type="password" name="password" required minlength="8">
<!-- 郵箱 -->
<input type="email" name="email" required placeholder="example@domain.com">
<!-- 搜索框 -->
<input type="search" name="search" placeholder="搜索...">
<!-- 數值 -->
<input type="number" name="age" min="18" max="100" step="1" required>
<!-- 滑動條 -->
<input type="range" name="volume" min="0" max="100" step="1">
<!-- 電話號碼 -->
<input type="tel" name="phone" pattern="^\+?\d{0,13}" placeholder="+8613800000000">
<!-- 日期 -->
<input type="date" name="birthdate" required>
<!-- 時間 -->
<input type="time" name="appointmenttime">
<!-- 日期和時間 -->
<input type="datetime-local" name="appointmentdatetime">
<!-- 復選框 -->
<label><input type="checkbox" name="interest" value="coding"> 編程</label>
<label><input type="checkbox" name="interest" value="music"> 音樂</label>
<!-- 單選按鈕 -->
<label><input type="radio" name="gender" value="male" required> 男性</label>
<label><input type="radio" name="gender" value="female"> 女性</label>
<!-- 下拉選擇 -->
<select name="country" required>
<option value="china">中國</option>
<option value="usa">美國</option>
</select>
<!-- 顏色選擇器 -->
<input type="color" name="favcolor" value="#ff0000">
<!-- 文件上傳 -->
<input type="file" name="resume" accept=".pdf,.docx" multiple>
HTML5表單提供了內置的驗證功能,可以在數據提交到服務器之前進行檢查。
<input type="text" name="username" required>
<input type="text" name="zipcode" pattern="\d{5}(-\d{4})?" title="請輸入5位數的郵政編碼">
<input type="number" name="age" min="18" max="99">
<input type="text" name="username" minlength="4" maxlength="8">
當用戶填寫完表單并點擊提交按鈕時,瀏覽器會自動檢查所有輸入字段的有效性。如果所有字段都滿足要求,表單數據將被發送到服務器。否則,瀏覽器會顯示錯誤信息,并阻止表單提交。
<input type="submit" value="提交">
可以使用JavaScript來自定義驗證或處理提交事件:
document.querySelector('form').addEventListener('submit', function(event) {
// 檢查表單數據
if (!this.checkValidity()) {
event.preventDefault(); // 阻止表單提交
// 自定義錯誤處理
}
// 可以在這里添加額外的邏輯,比如發送數據到服務器的Ajax請求
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表單提交并顯示JSON</title>
</head>
<body>
<!-- 表單定義 -->
<form id="myForm">
<label for="name">姓名:</label>
<input type="text" id="name" name="name">
<br>
<label for="email">電子郵件:</label>
<input type="email" id="email" name="email">
<br>
<input type="button" value="提交" onclick="submitForm()">
</form>
<script>
// JavaScript函數,處理表單提交
function submitForm() {
// 獲取表單元素
var form = document.getElementById('myForm');
// 創建一個FormData對象
var formData = new FormData(form);
// 創建一個空對象來存儲表單數據
var formObject = {};
// 將FormData轉換為普通對象
formData.forEach(function(value, key){
formObject[key] = value;
});
// 將對象轉換為JSON字符串
var jsonString = JSON.stringify(formObject);
// 彈出包含JSON字符串的對話框
alert(jsonString);
// 阻止表單的默認提交行為
return false;
}
</script>
</body>
</html>
在這個例子中:
注意,這個例子中我們使用了type="button"而不是type="submit",因為我們不希望表單有默認的提交行為。我們的JavaScript函數submitForm會處理所有的邏輯,并且通過返回false來阻止默認的表單提交。如果你想要使用type="submit",你需要在<form>標簽上添加一個onsubmit="return submitForm()"屬性來代替按鈕上的onclick事件。
HTML5的表單功能為開發者提供了強大的工具,以便創建功能豐富、用戶友好且安全的網站。通過使用HTML5的輸入類型和驗證方法,可以確保用戶輸入的數據是有效的,同時提高用戶體驗。隨著技術的不斷進步,HTML5表單和相關API將繼續發展,為前端工程師提供更多的可能性。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。