在 JavaMail 中,可以通过 extends Authenticator 抽象类,在子类中覆盖父类中的 getPasswordAuthentication() 方法,就可以实现以不同的方式来进行登录邮箱时的用户身份认证。JavaMail 中的这种设计是使用了策略模式(Strategy),具体的请参看相关文章。
在我们的代码中,我们设计了一种简单的 SimpleAuthenticator 子类通过构造函数传入用户名和密码,而另一种 GUIAuthenticator 子类则使用 GUI 界面的形式进行身份认证,它可以使得程序在运行时弹出输入对话框来让用户提交用户名和密码,具体的请看下面运行图。
代码实现:
import java.util.Date;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.mail.Authenticator;
import javax.mail.Transport;
import javax.mail.Message.RecipientType;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.swing.JOptionPane;
// 普通的通过构造函数传入身份验证信息的 Authenticator 子类
class SimpleAuthenticator extends Authenticator {
private String user;
private String pwd;
public SimpleAuthenticator(String user, String pwd) {
this.user = user;
this.pwd = pwd;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, pwd);
}
}
// 具有弹出输入对话框的 Authenticator 子类
class GUIAuthenticator extends Authenticator {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
String user;
String pwd;
// 弹出输入对话框
String result = JOptionPane.showInputDialog("请输入用户名和密码,以','隔开!");
StringTokenizer st = new StringTokenizer(result, ","); user = st.nextToken();
pwd = st.nextToken();
return new PasswordAuthentication(user, pwd);
}
}
/**
- 使用Authenticator子类进行用户身份认证
- @author haolloyin
*/
public class UseAuthenticatorSender {
private String smtpServer = "smtp.126.com";
private String from = "testhao@126.com";
private String to = "test_hao@sina.cn";
private String subject = "使用Authenticator子类进行用户身份认证";
private String body = "使用Authenticator子类进行用户身份认证的测试!!!";
public void sendMails(Authenticator auth) throws Exception {
// 设置协议、是否身份验证、服务器等信息
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.host", smtpServer);
// 通过传入的参数获得Authenticator子类对象
Session session = Session.getInstance(props, auth);
session.setDebug(true);
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
msg.addRecipient(RecipientType.CC, new InternetAddress(from));
msg.setRecipient(RecipientType.BCC, new InternetAddress(to));
msg.setSubject(subject);
msg.setSentDate(new Date());
msg.setText(body);
msg.saveChanges();
Transport.send(msg);
}
// 测试
public static void main(String[] args) throws Exception {
UseAuthenticatorSender sender = new UseAuthenticatorSender();
// 这里体现了使用策略模式的好处,客户端可以选择使用
// 具体的哪一种身份验证方式来提交信息
// Authenticator auth = new SimpleAuthenticator("testhao", "123456");
Authenticator auth = new GUIAuthenticator();
sender.sendMails(auth);
}
}
两种测试结果(只需要在main()方法中注释掉其中的一行则可):
1、使用 SimpleAuthenticator 子类:
AuthenticatorMails012、使用 GUIAuthenticator 子类:
注:程序在运行到用户身份验证时会自动弹出下面的输入对话框,由于上面的代码中的 Session 对象启动了 JavaMail API 调试功能,所以这个现象可以很明显地从控制台中得知。
AuthenticatorMails02 AuthenticatorMails04 AuthenticatorMails03通过上面使用 Authenticator 的具体子类来实现不同的身份验证方式,我们大概地了解到策略模式的好处,我们还可以在设计一个从网页中或者数据库表中获取登录信息的 Authenticator 子类,而客户端在使用时却可以不受影响。
小结:
Authenticator 类的这种结构设计是设计模式运用在实际应用中的体现,从 JavaMail 的帮助文档中可以看到 Authenticator 类中的其他方法都是 protected final 修饰的,这与策略模式(Strategy)的设计一样。
网友评论