2010年02月10日
こんにちは、開発本部の大西です。
最近、非常にご質問の多い、シングルサインオン(SSO)の対応方法について、お話したいと思います。
個人的には、XSSやSQLインジェクションなどの脆弱性などのセキュリティに関して、いろいろと非常にうるさい世の中の癖に、一番重要なはずのログイン認証、特に、SSOに関しては、非常に緩く、SSOぐらい当たり前というのが納得がいかない、きょう、この頃です・・・。
そんなことは置いておいて、intra-martには、SSO認証対応として、認証およびユーザ情報を外部で管理した場合に、ログイン認証処理を省略することが可能になる仕組みがあります。(Ver5.0以降)
つまり、intra-martでは、他システムで認証された情報を元に自動的にログインさせるということが可能になっています。
SSOにて、外部で認証した場合のイメージが、以下の図になります。
ただし、以下の条件が必須になります。
このような場合、intra-martでの認証シーケンスのうち、下記の図にある赤丸のリクエストパラメータ解析を行っている部分を標準のものから、別のリクエスト情報を読取り、「ユーザID」を取得し、強制的にログインをさせるものに置き換えることで対応が可能です。

intra-martのServerManagerがインストールされているサーバの
<imart>/conf/access-security.xml を
<user-security>
<initial-request-analyzer>
<request-analyzer-class>jp.co.intra_mart.foundation.security.certification.StandardRequestAnalyzer </request-analyzer-class>
</initial-request-analyzer>
<login-request-analyzer>
<request-analyzer-class>jp.co.intra_mart.foundation.security.certification.StandardRequestAnalyzer </request-analyzer-class>
</login-request-analyzer>
<user-security>
<initial-request-analyzer>
<request-analyzer-class>jp.co.intra_mart.foundation.security.certification.SSORequestAnalyzer </request-analyzer-class>
</initial-request-analyzer>
<login-request-analyzer>
<request-analyzer-class>jp.co.intra_mart.foundation.security.certification.SSORequestAnalyzer </request-analyzer-class>
</login-request-analyzer>
public LoginRequestInfo parseRequest(LoginRequestInfo loginInfo, HttpServletRequest request) {
// 情報初期化
//loginInfo.setUser(StringUtil.EMPTY_STRING);
loginInfo.setPassword(StringUtil.EMPTY_STRING);
Cookie[] cookies = request.getCookies();
String cookie = null;
for (int i = 0; cookies != null && i < cookies.length; i++) {
if (cookies[i].getName().equals(this.authCookieName)) {
cookie = cookies[i].getValue();
Pattern pattern = Pattern.compile(this.loginKey + "=([^&]*)");
Matcher matcher = pattern.matcher(cookie);
if (!matcher.find()) {
// 情報がない
break;
}
// 括弧の中を取得する。
String comid = matcher.group(1);
try {
// ログイン情報のデコード
comid = URLDecoder.decode(comid, "UTF-8");
} catch (UnsupportedEncodingException e) {
// コーディング上この例外は発生しない。
// 変換に失敗した場合でもそのまま処理を続行
}
// ユーザIDとログイングループの切り出し(user/logingroup形式)
String[] comids = comid.split(ID_SEPARATOR);
if (comids.length > 0) {
loginInfo.setUser(comids[0]);
}
if (comids.length > 1) {
loginInfo.setLoginGroup(comids[1]);
}
// ここに来れば認証は終了しています。
loginInfo.setDoneCertification(true);
// SSOログアウトURLが存在するなら、初期URLに設定します。
if(this.ssoLogoutUrl.length() > 0) {
loginInfo.setInitialUrl(this.ssoLogoutUrl);
}
break;
}
}
return loginInfo;
}
上記サンプルは、IM-SSOを利用時のサンプルコードで、この場合、クッキー情報から「ユーザーID」を取得して、UserInfo情報へ「ユーザID」を設定します。(5行目~32行目まで)
認証元のシステムから「ユーザID」が「httpクッキー」で送られてくる場合は、上記処理を参考に修正してください。
「リクエスト・パラメータ」の場合は、request.getParamter()で「ユーザID」を取得して、UserInfo情報へ「ユーザID」を設定してください。
「リクエスト・ヘッダ」の場合は、request.getHeader()で「ユーザID」を取得して、UserInfo情報へ「ユーザID」を設定してください。
※上記サンプルは、製品情報ダンロードページの「アクセスセキュリティ機能のソース」に含まれています。
このように、SSO認証用の専用のモジュールに置き換えることにより、SSO対応ができるようになります。ログイン認証の処理は、いろいろと工夫することにより、SSOだけでなく、各システムのいろいろな要件に対応することができますので、いろいろと試してみてください。
コメント