この例では,統合ユーザ管理フレームワークの提供の機能を利用して,メールサーバにシングルサインオンするポートレットを示します。
(1) カスタムログインモジュールの作成
まず,メールサーバとのシングルサインオンを実現するために,メールサーバと認証するカスタムログインモジュールを作成します。カスタムログインモジュールでは,sharedStateオブジェクトから,ユーザIDとパスワードを取得して認証します。次の二つのファイルを作成します。
package mail;
import java.security.Principal;
import java.io.Serializable;
public class MailPrincipal implements Principal, Serializable
{
private String name;
public MailPrincipal(String name) {
if (name == null) throw new NullPointerException();
this.name = name;
}
public String getName() { return name; }
public String toString() { return getName(); }
public boolean equals(Object o) {
if (o == null) return false;
if (this == o) return true;
if (!(o instanceof MailPrincipal)) return false;
MailPrincipal rhs = (MailPrincipal)o;
if (getName().equals(rhs.getName())) return true;
return false;
}
public int hashCode() { return getName().hashCode(); }
}
package mail.login;
import com.cosminexus.admin.auth.*;
import javax.security.auth.*;
import javax.security.auth.login.*;
import javax.security.auth.callback.*;
import javax.security.auth.spi.*;
import java.text.*;
import java.util.*;
import javax.mail.*;
import java.util.Properties;
import mail.MailPrincipal;
public class MailLoginModule implements LoginModule {
private Subject subject;
private CallbackHandler callbackHandler;
private Map sharedState;
private Map options;
private static final String USER_HOST_OPT = "mail.login.host";
private static final String USER_PROV_OPT = "mail.login.provider";
private static final String USERNAME = "mail.login.username";
private static final String PASSWORD = "mail.login.password";
private static final String DEFAULT_PROV = "imap";
private static final String MSG_USERNOTFOUND = "user not found!";
private static final String MSG_NOHOSTOPT = "not host option!";
private boolean commitSucceeded = false;
private Store store;
private String username;
public void initialize(
Subject subject,
CallbackHandler callbackHandler,
Map sharedState,
Map options)
{
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
this.options = options;
}
public boolean login()
throws LoginException
{
// get user-name & password
this.username = (String)this.sharedState.get(USERNAME);
if (username == null) throw new LoginException(MSG_USERNOTFOUND);
String password = (String)this.sharedState.get(PASSWORD);
// option check
String host = (String)this.options.get(USER_HOST_OPT);
if (host == null || host.length()==0) throw new LoginException(MSG_NOHOSTOPT);
String provider = (String)this.options.get(USER_PROV_OPT);
if (provider == null ) provider = DEFAULT_PROV;
// login
Properties props = new Properties();
Session session = Session.getInstance(props, null);
try {
store = session.getStore(provider);
store.connect(host, username, password);
} catch(Exception ex) {
throw new LoginException(ex.toString());
}
return true;
}
public boolean commit() throws LoginException {
this.subject.getPrincipals().add( new MailPrincipal(this.username) );
this.subject.getPublicCredentials().add( this.store );
return this.commitSucceeded = true;
}
public boolean abort() throws LoginException {
try {
if (store != null) store.close();
} catch(MessagingException ex) {
// Disregard
}
if (this.commitSucceeded) {
logout();
}
return true;
}
public boolean logout() throws LoginException {
try {
if (store != null) store.close();
} catch(MessagingException ex) {
// Disregard
}
this.commitSucceeded = false;
return true;
}
}
(2) 日立APIポートレット
次に,メール情報を表示する日立APIポートレットを作成します。このポートレットでは,ログインに成功したあと,subjectからメール情報を取得しています。メール情報を表示するポートレットのサンプルコードを次に示します。
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib uri="http://cosminexus.com/admin/auth/uatags" prefix="ua" %>
<%@ page import="com.cosminexus.admin.auth.*" %>
<%@ page import="com.cosminexus.admin.auth.sso.callback.*" %>
<%@ page import="javax.security.auth.*" %>
<%@ page import="javax.security.auth.login.*" %>
<%@ page import="java.security.*" %>
<%@ page import="javax.mail.*" %>
<%@ page import="java.util.Properties" %>
<%
LoginContext lc = null;
try {
WebSSOHandler h =
new WebSSOHandler(request, response, null);
lc = new LoginContext("Mail", h);
lc.login();
}
catch (LoginException e) {
out.println("Mailへのログインに失敗しました。");
return;
}
catch (Exception e) {
out.println("Mailへのログインで障害が発生しました。");
return;
}
try {
Subject subject = lc.getSubject();
Principal principal = (Principal)subject.getPrincipals().
iterator().next();
String mailid = principal.getName();
Store store =
(Store)subject.getPublicCredentials().iterator().next();
out.println("メールID="+mailid+"<br />");
Folder folder = null;
try {
folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
Message msg[] = folder.getMessages();
out.println("メール総数="+msg.length+"<br />");
out.println("<br />");
if (msg.length == 0) {
out.println("メールはありません<br />");
}
else {
out.println("メール一覧<br />");
out.println("<table border>");
{
// 先頭行
out.println("<tr>");
out.println(
"<th><font size=¥"4¥">項番</th>"
+"<th><font size=¥"4¥">送信者</th>"
+"<th><font size=¥"4¥">メールタイトル</th>");
out.println("</tr>");
// メールのタイトル表示
int loop = msg.length>10 ? 10 : msg.length;
for (int i = 0; i < loop ; ++i) {
out.println("<tr>");
out.print("<td align=¥"right¥">"+(i+1)+"</td>");
Address[] addrs = msg[i].getFrom();
String requestName = (addrs != null && addrs.length > 0) ?
addrs[0].toString() : "不明";
out.print("<td>"+requestName+"</td>");
out.print("<td>"+msg[i].getSubject()+"</td>");
out.println("</tr>");
} // for i
}
out.println("</table>");
}
}
catch (Exception e) {
out.println("Mailの表示中に障害が発生しました。");
return;
}
finally {
try {
if (folder != null) folder.close(false);
}
catch (MessagingException e) { e.printStackTrace(); }
}
}
finally {
try {
lc.logout();
}
catch (Exception e) {
out.println("Mailのログオフに障害が発生しました。");
return;
}
}
%>
<hr />
(3) ポートレットを動作させるための設定
(2)の日立APIポートレットを動作させるための設定について説明します。
Portal {
com.cosminexus.admin.auth.sso.login.WebSSOLoginModule required
com.cosminexus.admin.auth.realm="Portal"
com.cosminexus.admin.auth.ldap.r="0"
com.cosminexus.admin.auth.ldap.w="1"
;
};
Mail {
com.cosminexus.admin.auth.sso.login.WebSSOLoginModule required
com.cosminexus.admin.auth.sso="MailLM"
com.cosminexus.admin.auth.realm="Mail"
mail.login.host="localhost" /* MailLoginModuleのオプション */
;
};
com.cosminexus.admin.auth.sso.lm.MailLM=mail.login.MailLoginModule
com.cosminexus.admin.auth.sso.param.userid.MailLM=mail.login.username
com.cosminexus.admin.auth.sso.param.secdat.MailLM=mail.login.password
REALMNAME,USERID,SECRETDATA,PUBLICDATA,LINK_Mail
Portal,user1,,,muser1
Mail,muser1,pass1,,