IBM Portal 开发系列讲座:
开发一个系统登录的portlet
北京东华合创数码科技公司 郑文平
内容简介:
我们用ibm自带的开发工具WSAD(已安装portlet toolkit包),开发一个Portlet,实现以下功能:
l 用户不想通过点击系统右上角的“登录”按钮后切换到系统的登录页面,而是从首页山直接登录。这个portlet就实现了这个功能,用户可以从首页上输入用户名和密码并提交,登录成功后读取该用户在OA服务器上的邮件系统,并返回个人邮件信息、欢迎信息,转入并显示在指定页面;
l 用户不能从Portal系统原登录页面登录。即:如果用户验证失败,系统会转向自带的登录页面,我们修改那个文件,使之强行定位到该Portlet所在的页面。系统将显示为该登录portlet,而非系统自带的登录页面;
l 用户可以通过Url_Mapping功能,从这个portlet直接进入到指定的任意逻辑、物理页面,也可以进入到虚拟门户允许的首页。
其数据流转是这样的:
[开发过程]
1、首先编写这个类,用来读取OA系统中任一用户的邮件系统:
package youjiantishi;
/**
* 这个类用来读取某一用户的邮件内容:
*
* 维护:zhengwp@dhcc.com.cn 郑文平
*
* 编码:赵建业 时间: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?