今回は、SpringSecurityを使っての同時ログイン制御について説明します。
SpringSecurityを使った場合、セッションの作成や制御はSpringSecurityが自動でやってくれますが、「applicationSecurity.xml」で然るべき定義をおこなえば、同時ログイン制御も簡単におこなうことができます。
同時ログイン制御は、システムによって仕様が異なるかと思います。
同じユーザIDで複数ユーザでのログインを許可しているシステムもあれば、同じユーザIDで複数ユーザでのログインを許可しないシステムもあります。
こういった制御は、自前で制御を作るのではなく、「applicationSecurity.xml」の定義で制御可能です。
目次
SpringSecurityの基本的な使い方
SpringSecurityの基本的な使い方については、以下の記事を参照してください。
SpringSecurityを使えば、ログイン機能があるシステムで必要な以下の制御が可能になります。
- ログイン認証
- セッション管理
- 不正アクセスに対する制御
- ワンタイムトークン
同時ログイン制御で必要な「applicationSecurity.xml」の定義
基本的な「applicationSecurity.xml」の定義は以下になります。
同時ログインを許可していないシステムでの定義例になります。
<bean id="sessionStrategy" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy" > <constructor-arg index="0"> <list> <bean class="jp.co.xxx.MyConcurrentSessionControlAuthenticationStrategy"> <constructor-arg index="0" ref="sessionRegistry" /> <property name="maximumSessions" value="1" /> <property name="exceptionIfMaximumExceeded" value="false"/> </bean> </list> </constructor-arg> </bean>
同時ログインを許可しないために必要なプロパティ設定について解説していきます。
最大セッション数 – maximumSessions
1ユーザが許可する最大セッション数になります。
ここを1にすると、1ユーザが許可する最大セッション数は1になるので、同時ログインは許可しないということになります。
例えば、この値に「100」を定義すると、同じユーザIDでログインを許可する最大セッション数は100になります。
つまり、同時ログインを100セッションまで許可する、ということになります。
セッション数が最大を超えた場合に例外を発生させる – exceptionIfMaximumExceeded
「maximumSessions」の数を超えた場合、例外を発生させるかどうか?の定義になります。
trueだと例外を発生させ、falseだと例外を発生させない。
上記の「applicationSecurity.xml」の定義では、例外は発生させたくないのでfalseにしています。
Javaで制御をおこなう – ConcurrentSessionControlAuthenticationStrategy
XMLに定義されていますが、「MyConcurrentSessionControlAuthenticationStrategy」で個別制御をおこなうことができます。
「MyConcurrentSessionControlAuthenticationStrategy」は「org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy」
を継承したクラスになります。
具体的には、以下のクラスを準備して個別制御をおこないます。
import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.security.core.Authentication; import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy; public class MyConcurrentSessionControlAuthenticationStrategy extends ConcurrentSessionControlAuthenticationStrategy { private SessionRegistry mySessionRegistry; public MyConcurrentSessionControlAuthenticationStrategy( SessionRegistry sessionRegistry) { super(sessionRegistry); this.mySessionRegistry = sessionRegistry; } @Override public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) { //-- 個別処理をこの中に書く --// } }
「onAuthentication」は、認証が成功した場合に実行されるメソッドになります。
個別処理が必要な場面とは以下になります。
全て、同時ログインを許可しない「applicationSecurity.xml」の定義をおこなった場合の制御です。
- ある条件に一致するユーザは、同時ログイン制御を許可させる。
- 『後勝ち』の制御をおこなう。
『後勝ち』の制御はスペシャルですね。
既にログインしているユーザのセッションを削除する処理が必要になります。
以下のような実装が必要になります。
// 同一ユーザでのセッションリストを取得 List<SessionInformation> sessions = this.mySessionRegistry .getAllSessions(authentication.getPrincipal(), false); // 許可するセッションの数を取得 int allowedNum = getMaximumSessionsForThisUser(authentication); // セッションリストのうち、ログインしたユーザだけを有効にし、 // 他セッションを無効にする allowableSessionsExceeded(sessions, allowedNum, this.mySessionRegistry);
まとめ
いかがでしたでしょうか?
SpringSecurityで同時ログイン制御が簡単におこなうことができることがわかって頂けたかと思います。
「applicationSecurity.xml」の定義だけではなく、SpringSecurityは必ずスペシャルな処理を個別に実装することが可能です。
「applicationSecurity.xml」の定義だけでやり切る(やり切れる)部分と、スペシャルに実装する部分を見極めて実装することが大事かと思います。
それではまた!