IBM Portal 开发系列讲座: 
  
开发一个系统登录的portlet 
  
北京东华合创数码科技公司 郑文平 
  
内容简介: 
  
我们用ibm自带的开发工具WSAD(已安装portlet toolkit包),开发一个Portlet,实现以下功能: 
l         用户不想通过点击系统右上角的“登录”按钮后切换到系统的登录页面,而是从首页山直接登录。这个portlet就实现了这个功能,用户可以从首页上输入用户名和密码并提交,登录成功后读取该用户在OA服务器上的邮件系统,并返回个人邮件信息、欢迎信息,转入并显示在指定页面; 
l         用户不能从Portal系统原登录页面登录。即:如果用户验证失败,系统会转向自带的登录页面,我们修改那个文件,使之强行定位到该Portlet所在的页面。系统将显示为该登录portlet,而非系统自带的登录页面; 
l         用户可以通过Url_Mapping功能,从这个portlet直接进入到指定的任意逻辑、物理页面,也可以进入到虚拟门户允许的首页。 
  
其数据流转是这样的: 
 
      
  [开发过程] 
  
1、首先编写这个类,用来读取OA系统中任一用户的邮件系统: 
  
  package youjiantishi; 
  
/** 
 *      这个类用来读取某一用户的邮件内容:  
 * 
 *      维护:[email protected]  郑文平 
 *      
 *      编码:赵建业 时间:2004年11月 
 */ 
  
import java.util.*; 
import java.io.*; 
import javax.mail.*; 
import javax.mail.event.*; 
import javax.mail.internet.*; 
import javax.activation.*; 
  
public class msgOAshow { 
  
    static String protocol; 
    static String host = null; 
    static String user = null; 
    static String password = null; 
    static String mbox = null; 
    static String url = null; 
    static int port = -1; 
    static boolean verbose = false; 
    static boolean debug = false; 
    static boolean showStructure = false; 
    static boolean showMessage = false; 
    static boolean showAlert = false; 
    static boolean saveAttachments = false; 
    static int attnum = 1; 
    static int dhcc_totalmsg=0; 
    static int dhcc_newmsg=0; 
  
    public int get_total() 
    { 
      return dhcc_totalmsg; 
    } 
    public int get_new() 
    { 
      return dhcc_newmsg; 
    } 
  
    public msgOAshow() 
        { 
        java.io.InputStream inputstream = getClass().getResourceAsStream("mailaddress.properties"); 
        Properties properties = new Properties(); 
        try 
        { 
            properties.load(inputstream); 
        } 
        catch(Exception exception) 
        { 
            System.err.println("Can not read the properties file. Make sure db.properties is in the CLASSPATH"); 
            return; 
        } 
        host = properties.getProperty("address", "localhost"); 
        protocol=properties.getProperty("protocol", "pop3"); 
        mbox=properties.getProperty("mbox", "INBOX"); 
  
    } 
    
    public static int getEmailMain(String argv[]) { 
        int msgnum = -1; 
        int optind; 
        user=argv[0]; 
        password=argv[1]; 
  
        try { 
  
        // Get a Properties object 
        Properties props = System.getProperties(); 
  
        // Get a Session object 
        Session session = Session.getInstance(props, null); 
        session.setDebug(debug); 
  
  
        // Get a Store object 
        Store store = null; 
        if (url != null) { 
        URLName urln = new URLName(url); 
        store = session.getStore(urln); 
        if (showAlert) { 
            store.addStoreListener(new StoreListener() { 
            public void notification(StoreEvent e) { 
                String s; 
                if (e.getMessageType() == StoreEvent.ALERT) 
                s = "ALERT: "; 
                else 
                s = "NOTICE: "; 
                //System.out.println(s + e.getMessage()); 
            } 
            }); 
        } 
        store.connect(); 
        } else { 
        if (protocol != null)       
            store = session.getStore(protocol); 
        else 
            store = session.getStore(); 
  
        // Connect 
        if (host != null || user != null || password != null) 
            store.connect(host, port, user, password); 
        else 
            store.connect(); 
        } 
         
  
        // Open the Folder 
  
        Folder folder = store.getDefaultFolder(); 
        if (folder == null) { 
            //System.out.println("No default folder"); 
            //System.exit(1); 
            return -1; 
        } 
  
        if (mbox == null) 
        mbox = "INBOX"; 
        folder = folder.getFolder(mbox); 
        if (folder == null) { 
            //System.out.println("Invalid folder"); 
            //System.exit(1); 
            return -1; 
        } 
  
        // try to open read/write and if that fails try read-only 
        try { 
        folder.open(Folder.READ_WRITE); 
        } catch (MessagingException ex) { 
        folder.open(Folder.READ_ONLY); 
        } 
        int totalMessages = folder.getMessageCount(); 
  
        if (totalMessages == 0) { 
        //System.out.println("Empty folder"); 
        folder.close(false); 
        store.close(); 
        dhcc_totalmsg=0; 
        dhcc_newmsg=0; 
        return 0; 
        //System.exit(1); 
        } 
  
        int newMessages = folder.getNewMessageCount(); 
        System.out.println("Total messages = " + totalMessages); 
        System.out.println("New messages = " + newMessages); 
        //System.out.println("-------------------------------"); 
        dhcc_totalmsg=totalMessages; 
        dhcc_newmsg=newMessages; 
  
  
  
        folder.close(false); 
        store.close(); 
    } catch (Exception ex) { 
        System.out.println("Oops, got exception! " + ex.getMessage()); 
        //ex.printStackTrace(); 
        //System.exit(1); 
        return -2; 
    } 
    return 0; 
    } 
  
   
} 
  
2、用WSAD开发一个使用凭证保险库的portlet,最好选用共享保险槽。接下来,在Portlet的View.jsp页面中我们提供用户登录表单(表单源代码略): 
    <wps:if loggedIn="no">   //如果用户没有登录,我们显示为登录表单: 
                                           
 
  
该表单接收到用户名和密码后,提交到ChenkLogin.jsp文件。 
<wps:if loggedIn="yes">            //当用户登录后,调用这个类读取OA系统: 
<jsp:useBean id="msgOAshow" scope="page" class="youjiantishi.msgOAshow"/> 
<% 
        String MyName=(String)(session.getAttribute("userid"));    
        String MyPass=(String)session.getAttribute("password"); 
        String argv[]=new String[2]; 
        argv[0]=MyName; 
        argv[1]=MyPass; 
        boolean b_flag=false;    
        int i=msgOAshow.getEmailMain(argv); 
        if (i!=0) 
           { 
                  //out.println("读取用户时发生错误!"); 
                  b_flag=true; 
           } 
        else 
          { 
                  b_flag=false; 
           } 
       %> 
   然后,将读到的内容显示出来(源代码略),并添加欢迎信息: 
 
                        
         图:获取该用户的邮箱信息,并显示出来。 
  
我们在这个jsp页面上显示出该用户的邮箱信息,并显示欢迎该用户的字样。该欢迎信息是这样获取的: 
l         首先,引入wps标签库: 
<%@ taglib uri="/WEB-INF/tld/engine.tld" prefix="wps" %> 
引入该标签库后,我们就可以使用其中的标签了,比如上面用到的: 
  <wps:if loggedIn="no">   //当用户没有登录时。 
</wps:if> 
l         我们引入欢迎标签:welcome: 
<wps:text key="welcome" bundle="nls.engine"> 
         <wps:textParam><wps:user attribute="givenName"/></wps:textParam> 
</wps:text> 
我们必须在wps包内找到名字为nsl.engine的标签文件,并添加或者修改键值为welcome的标签,并设置成我们要求的格式。这部分具体开发内容同于一般的标签开发,这里不再赘述。有兴趣的朋友可以自己查找资料研究,也可以与作者讨论。 
3、新建checklogin.jsp,用来将用户信息提交到portal系统,实现单点登录。 
l         新建一个表单,用来将用户信息提交到Portal系统的登陆action。 
 <form method="POST" action='/wps/portal/!ut/p/.cmd/li'  name="LoginPage">  // 
   <table width="196" height="150" cellspacing="0"> 
<tr> 
          <% 
String username=request.getParameter("userid"); 
                 String password=request.getParameter("password"); 
%> 
<td> 
           <input name="userid" type="hidden" value="<%=username%>"> 
</td> 
       <td> 
<input name="password" type="hidden" value="<%=password%>"> 
</td> 
    </tr> 
</ta ble> 
</form> 
   这个表单用来将提取到的用户信息,提交到portal系统的login系统。其中这里的action我们先使用了编译后的代码,如果您重装了Portal系统,您必须更改此portlet的选项,以符合portal系统登陆要求。读到这里,如果您是一个标签方面的高手,您可能已经猜到了更好的解决方案。是的,将这个portelt切换到配置模式,不如直接引入wps相应地标签库,使用一个简单的标签,就可以用键值将之写死,这些内容实现起来比较麻烦,笔者将在以后的相关文章中详细介绍,有兴趣的朋友,可以关注我的专栏。 
l         其他该注意的问题: 
到这里该Portlet可以算是开发完了,这里提醒开发者机电该注意的问题: 
1)Portal系统的action处理完用户登录后,会返回提交者,即:checklogin.jsp。这是我们所不希望的,因为系统一旦返回到checklogin,checklogin会再次提交!是的,您已经想到了,这会生成一个死循环,计算机的声卡会发出啪啪啪的声音,就是这个原因造成的。解决这个问题,实际上非常简单,我们可以在session里设置一个开关,如果checklogin没有提交过,就打开这个开关,让系统提交;一旦提交过了,就把这个开关关死,死循环的问题就OK了。参考代码如下: 
if (my_flagid==null) 
            my_flagid=""; 
if (my_flagid.equals("0")) 
{ 
  session.setAttribute("b_getPortaPass","1"); 
…….       
  
2)如果登录成功,我们可以将location转向到myportal的任何页面, 
如果登录不成功,系统会向用户要session,也就是用户信息,所以默认会返回到Portal系统自带的login页面,我们可以在.war/screen/html目录下找到login.jsp文件,并用javascript将location强行切换到我们自己开发的首页,也就是单点登录Portlet所在的页面。从而拒绝了系统登录。OK?
  
 
         
  
  
  
  
  
   
 
  |