JavaMail:用Authenticator的子类进行身份验证及策略模式(Strategy)

简介:

假如我们修改了邮箱登录密码,那么原来编译好的文件就不能再用了,这样子做的缺点很明显:邮箱登录时的用户身份认证不灵活。

在 JavaMail 中,可以通过 extends Authenticator 抽象类,在子类中覆盖父类中的 getPasswordAuthentication() 方法,就可以实现以不同的方式来进行登录邮箱时的用户身份认证。JavaMail 中的这种设计是使用了策略模式(Strategy),具体的请参看相关文章。

在我们的代码中,我们设计了一种简单的 SimpleAuthenticator 子类通过构造函数传入用户名和密码,而另一种 GUIAuthenticator 子类则使用 GUI 界面的形式进行身份认证,它可以使得程序在运行时弹出输入对话框来让用户提交用户名和密码,具体的请看下面运行图。

代码实现: 

 
  1. import java.util.Date;  
  2. import java.util.Properties;  
  3. import java.util.StringTokenizer;  
  4.  
  5. import javax.mail.Authenticator;  
  6. import javax.mail.Transport;  
  7. import javax.mail.Message.RecipientType;  
  8. import javax.mail.PasswordAuthentication;  
  9. import javax.mail.Session;  
  10. import javax.mail.internet.InternetAddress;  
  11. import javax.mail.internet.MimeMessage;  
  12. import javax.swing.JOptionPane;  
  13.  
  14. // 普通的通过构造函数传入身份验证信息的 Authenticator 子类  
  15. class SimpleAuthenticator extends Authenticator {  
  16.     private String user;  
  17.     private String pwd;  
  18.  
  19.     public SimpleAuthenticator(String user, String pwd) {  
  20.         this.user = user;  
  21.         this.pwd = pwd;  
  22.     }  
  23.  
  24.     @Override 
  25.     protected PasswordAuthentication getPasswordAuthentication() {  
  26.         return new PasswordAuthentication(user, pwd);  
  27.     }  

 

 
  1. // 具有弹出输入对话框的 Authenticator 子类  
  2. class GUIAuthenticator extends Authenticator {  
  3.     @Override 
  4.     protected PasswordAuthentication getPasswordAuthentication() {  
  5.         String user;  
  6.         String pwd;  
  7.  
  8.         // 弹出输入对话框  
  9.         String result = JOptionPane.showInputDialog("请输入用户名和密码,以','隔开!");  
  10.         StringTokenizer st = new StringTokenizer(result, ",");  
  11.         user = st.nextToken();  
  12.         pwd = st.nextToken();  
  13.  
  14.         return new PasswordAuthentication(user, pwd);  
  15.     }  

 

 
  1. /**  
  2.  * 使用Authenticator子类进行用户身份认证  
  3.  * @author haolloyin  
  4.  */ 
  5. public class UseAuthenticatorSender {  
  6.     private String smtpServer = "smtp.126.com";  
  7.     private String from = "testhao@126.com";  
  8.     private String to = "test_hao@sina.cn";  
  9.     private String subject = "使用Authenticator子类进行用户身份认证";  
  10.     private String body = "使用Authenticator子类进行用户身份认证的测试!!!";  
  11.  
  12.     public void sendMails(Authenticator auth) throws Exception {  
  13.         // 设置协议、是否身份验证、服务器等信息  
  14.         Properties props = new Properties();  
  15.         props.setProperty("mail.transport.protocol""smtp");  
  16.         props.setProperty("mail.smtp.auth""true");  
  17.         props.setProperty("mail.host", smtpServer);  
  18.  
  19.         // 通过传入的参数获得Authenticator子类对象
  20.          
  21.         Session session = Session.getInstance(props, auth);  
  22.         session.setDebug(true);  
  23.  
  24.         MimeMessage msg = new MimeMessage(session);  
  25.         msg.setFrom(new InternetAddress(from));  
  26.         msg.setRecipient(RecipientType.BCC, new InternetAddress(to));  
  27.         msg.setSubject(subject);  
  28.         msg.setSentDate(new Date());  
  29.         msg.setText(body);  
  30.  
  31.         msg.saveChanges();  
  32.  
  33.         /*  
  34.          *  由于Session对象中注册了Authenticator子类对象,因此可以直接  
  35.          *  从该Authenticator子类对象中获取登录的相关信息,故直接使用  
  36.          *  Transport 抽象类中静态 send() 方法来简化代码编写  
  37.          */ 
  38.         Transport.send(msg);  
  39.     }  
  40.  
  41.     // 测试  
  42.     public static void main(String[] args) throws Exception {  
  43.         UseAuthenticatorSender sender = new UseAuthenticatorSender();  
  44.         // 这里体现了使用策略模式的好处,客户端可以选择使用  
  45.         // 具体的哪一种身份验证方式来提交信息  
  46. //      Authenticator auth = new SimpleAuthenticator("testhao", "123456");  
  47.         Authenticator auth = new GUIAuthenticator();  
  48.         sender.sendMails(auth);  
  49.     }  

两种测试结果(只需要在main()方法中注释掉其中的一行则可):

1、使用 SimpleAuthenticator 子类:

AuthenticatorMails01

2、使用 GUIAuthenticator 子类:

注:程序在运行到用户身份验证时会自动弹出下面的输入对话框,由于上面的代码中的 Session 对象启动了 JavaMail API 调试功能,所以这个现象可以很明显地从控制台中得知。

AuthenticatorMails02

AuthenticatorMails04 

AuthenticatorMails03

 

通过上面使用 Authenticator 的具体子类来实现不同的身份验证方式,我们大概地了解到策略模式的好处,我们还可以在设计一个从网页中或者数据库表中获取登录信息的 Authenticator 子类,而客户端在使用时却可以不受影响。

小结:

Authenticator 类的这种结构设计是设计模式运用在实际应用中的体现,从 JavaMail 的帮助文档中可以看到 Authenticator 类中的其他方法都是 protected final 修饰的,这与策略模式(Strategy)的设计一样。


本文转自 xxxx66yyyy 51CTO博客,原文链接:http://blog.51cto.com/haolloyin/354585,如需转载请自行联系原作者

相关文章
|
3月前
|
算法 搜索推荐 Java
策略模式 Strategy
策略模式 Strategy
42 0
|
2月前
|
设计模式 算法 测试技术
flea-common使用之通用策略模式实现
跟着 Huazie 一起了解通用策略模式实现【Flea Strategy】
70 1
flea-common使用之通用策略模式实现
|
6月前
|
API 数据安全/隐私保护
06 Shrio Authenticator及AuthenticationStrategy
06 Shrio Authenticator及AuthenticationStrategy
20 1
|
6月前
|
SQL 安全 测试技术
05 Shrio Realm
05 Shrio Realm
13 0
|
10月前
|
Java 网络安全
【SSH】Struts2中的ModelDriven机制
【SSH】Struts2中的ModelDriven机制
51 0
|
缓存 安全 Apache
2021年你还不会Shiro?----3.分析身份认证源码实现自定义Realm
我们已经知道无论我们是认证还是授权,数据的获取都是来源于Realm,Realm就相当于我们的datasource,在上一篇中我们使用的是用IniRealm来加载我们的配置文件shiro.ini,同时我们也说了ini只是临时解决方案,在实际的开发中是不可能把用户信息和权限信息放在ini文件中的,都是来源于数据库,那么系统提供的IniRealm就不能满足我们的需要了,我们就需要自定义Realm来实现真正的场景,事实上ini文件也只是apache为我们提供学习使用的策略,下面我们就来看下怎么自己定义一个Realm。
85 0
2021年你还不会Shiro?----3.分析身份认证源码实现自定义Realm
|
安全
Security重写权限服务配置类
Security重写权限服务配置类
91 0
|
安全
Security配置类
学习Security配置Demo1
107 0
|
算法 Java 程序员
Java策略模式(Strategy)
文章目录 策略模式(Strategy) 一.不使用策略模式 二.使用策略模式 1.案例类图 2.案例实现 3.总结 4.开发中的使用场景
Java策略模式(Strategy)
|
C# 设计模式 .NET
使用C# (.NET Core) 实现简单工厂(Simple Factory) 和工厂方法设计模式 (Factory Method Pattern)
本文源自深入浅出设计模式. 只不过我是使用C#/.NET Core实现的例子.   前言 当你看见new这个关键字的时候, 就应该想到它是具体的实现. 这就是一个具体的类, 为了更灵活, 我们应该使用的是接口(interface).
1401 0

热门文章

最新文章