7.5.1 ログインモジュール

ログインモジュールは,WebLoginModuleとWebPrincipalを作成します。

<この項の構成>
(1) ログインモジュール(WebLoginModule)
(2) ログインモジュール(WebPrincipal)

(1) ログインモジュール(WebLoginModule)

package web.login;

import com.cosminexus.admin.auth.*;
import javax.security.auth.*, javax.security.auth.login.*, javax.security.auth.callback.*, javax.security.auth.spi.*;
import java.io.*, java.util.*, java.net.*;
import java.util.Properties;
import web.WebPrincipal;

public class WebLoginModule implements LoginModule {
   private Subject subject;
   private CallbackHandler callbackHandler;
   private Map sharedState;
   private Map options;

   // 接続先Webアプリパラメータ名(jaas.conf)
   private static final String PORTLET_URL = "web.portlet.url";
   private static final String LOGOUT_URL = "web.logout.url";
   private static final String LOGIN_URL = "web.login.url";
   private static final String LOGIN_FORM_UID = "web.login.form.uid";
   private static final String LOGIN_FORM_PASSWD = "web.login.form.passwd";

   // SSOパラメータ名(ua.conf)
   private static final String USERNAME = "web.login.username";
   private static final String PASSWORD = "web.login.password";

   // エラーメッセージ
   private static final String MSG_USERNOTFOUND = "user not found!";
   private static final String MSG_INVALID_URL = "invalid url option specifed";
   private static final String MSG_INVALID_LOGININFO = "invalid id/password/method option specifed";

   private boolean commitSucceeded = false;

   private String sid; // セッションID
   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 {
       // ユーザ名とパスワードを取得
       username = (String)sharedState.get(USERNAME);
       if (username == null) throw new LoginException(MSG_USERNOTFOUND);
       String passwd = (String)this.sharedState.get(PASSWORD);

       URL url;
       String form_uid_name;
       String form_passwd_name;
       String method;

       try {
           url = new URL((String)options.get(LOGIN_URL));
       } catch (Exception e) {
           throw new LoginException(MSG_INVALID_URL);
       }

       form_uid_name = (String)options.get(LOGIN_FORM_UID);
       form_passwd_name = (String)options.get(LOGIN_FORM_PASSWD);
       if (form_uid_name == null || form_passwd_name == null) {
           throw new LoginException(MSG_INVALID_LOGININFO);
       }

       // バックエンドログイン
       try {
           HttpURLConnection conn = (HttpURLConnection)url.openConnection();
           conn.setRequestMethod("POST");
           conn.setDoOutput(true);
           conn.setRequestProperty("Content-Type",
                                   "application/x-www-form-urlencoded");

           StringBuffer sb = new StringBuffer();
           sb.append(form_uid_name).append("=").append(username).append("&")
             .append(form_passwd_name).append("=").append(passwd)
             .append("&action=login");

           conn.setRequestProperty("Content-Length",
                                   Integer.toString(sb.length()));

           BufferedWriter out =
             new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
           out.write(sb.toString(), 0, sb.length());
           out.flush();

           String cookie = conn.getHeaderField("Set-Cookie");
           sid = cookie.substring(0, cookie.indexOf(";"));
           sid = "jsessionid" + sid.substring(sid.indexOf("="), sid.length());
       } catch (Exception e) {
           throw new LoginException(e.toString());
       }

       return true;
   }

   public boolean commit() throws LoginException {
       subject.getPrincipals().add( new WebPrincipal(username) );

       Vector tmp = new Vector();
       tmp.add(sid);
       tmp.add(options.get(PORTLET_URL));
       subject.getPublicCredentials().add( tmp );

       return this.commitSucceeded = true;
   }

   public boolean abort() throws LoginException {
       if (commitSucceeded) {
           logout();
       }
       return true;
   }

   public boolean logout() throws LoginException {
       try {
           URL url = new URL(options.get(LOGOUT_URL)+";"+sid);
           BufferedInputStream in =
               new BufferedInputStream(url.openConnection().getInputStream());
           int BUFLEN = 1024;
           byte[] buf = new byte[BUFLEN];
           while (in.read(buf, 0, BUFLEN) > 0) { }
           in.close();
       } catch (Exception e) {
       }
       
       commitSucceeded = false;

       return true;
   }
}

注意
本サンプルではCookieの先頭の値をセッションID(変数名はsid)として引き継いでいます。Cookieの先頭にセッションID以外の値が設定される場合や,セッションID以外のCookie(負荷分散のサーバIDなど)を引き継ぐ必要がある場合は,使用する環境に合わせて処理を追加・変更してください。

(2) ログインモジュール(WebPrincipal)

ログインモジュール(WebPrincipal)の作成を次に示します。

package web;

import java.security.Principal;
import java.io.Serializable;

public class WebPrincipal implements Principal, Serializable {
 private String name;

 public WebPrincipal(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 WebPrincipal)) return false;
   WebPrincipal rhs = (WebPrincipal)o;
   if (getName().equals(rhs.getName())) return true;

   return false;
 }

 public int hashCode() { return getName().hashCode(); }
}