2012年5月7日月曜日

Anonymous 認証とポートマッピング

ある URL では http、別の URL では https で接続したいときがあります。今回は Spring Security を使って、その辺の機能を追加します。

準備 - Spring Security
Spring Security のサイトから spring-security-[version].RELEASE.zip をダウンロード後、解凍し、必要なファイルを /WEB-INF/lib にコピーし、ビルドパスにも追加します(現時点の最新バージョンは spring-security-3.1.0.RELEASE です)。

今回 cas, ldap, openid, remoting は明らかに使いませんし、samples も必要ないので、それら以外を上記の要領で環境に追加します。

名前空間
まず“Security Namespace Configuration”に従い、コンテキストファイルに Spring Security の設定を記述するための名前空間を追加します。私の場合 springSecurityConf.xml というファイルを作成し、/WEB-INF/conf に置くことにしました。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:security="http://www.springframework.org/schema/security"
     xsi:schemaLocation="
         http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/security 
         http://www.springframework.org/schema/security/spring-security-3.1.xsd">

Authentication Manager の構成
Spring Security の機能を使うためには Authentication Manager が構成されていなければなりません。今回は Anonymous 認証で行きたいと考えているので“Anonymous Authentication”の解説と名前空間リファレンス <security:authentication-manager/> を参考に Authentication Manager を構成します。

すると、こんな感じです。
  <!-- Authentication Manager-->
  <security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="anonymousAuthenticationProvider"/>
  </security:authentication-manager>
  
  <!-- Anonymous Authentication -->
  <bean id="anonymousAuthenticationProvider"
    class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
    <property name="key" value="psid"/>
  </bean>
  
  <bean id="anonymousAuthenticationFilter"
    class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
    <property name="key" value="psid"/>
    <property name="userAttribute" value="anonymousUser, ROLE_ANONYMOUS"/>
  </bean>

Anonymous Authentication
これでも動きます。ただ、AnonymousAuthenticationFilter に関しては、API ドキュメントを見ると setKey と setUserAttribute は Deprecated use constructor injection instead となっています。気になったので以下のように constructor injection を使う方法でも試してみたら <property/> で設定した時と「同じように」動きました。
  <bean id="anonymousAuthenticationFilter"
    class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
    <constructor-arg index="0" type="java.lang.String" value="psid"/>
  </bean>

リファレンスと GrepCode を見ると Spring Security の Anonymous 認証では、..Filter が ..Token の生成と SecurityContextHolder への追加、..Provider が ..Token の認証を行います(..の箇所は"AnonymousAuthentication")。つまり、SecurityContextHolder を見れば Anonymous 認証の内容が確かめられるということになります。で、確かめてみました。

 ..core.context.SecurityContextImpl@90572420:
  Authentication:
   ..authentication.AnonymousAuthenticationToken@90572420:
    Principal: anonymousUser; 
    Credentials: [PROTECTED]; 
    Authenticated: true; 
    Details:
     ..web.authentication.WebAuthenticationDetails@255f8:
      RemoteIpAddress: 127.0.0.1; 
      SessionId: A1B2C3...XYZ; 
      Granted Authorities: ROLE_ANONYMOUS


<property/>, <constructor-arg/> いずれの方法でも上と同じような内容になりました。

<security:http/> の設定
Authentication Manager が構成できたら、いよいよ本丸です。<security:http/> を参考に、URL パターンとポートをマッピングします。シナリオは

 ・/welcome は http
 ・/account は https

という単純なものにしました。
  <security:http pattern="/style/**" security="none"/>
  
  <security:http auto-config="true">
    
    <!-- account service -->
    <security:intercept-url pattern="/account/**" requires-channel="https" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    
    <!-- welcome service -->
    <security:intercept-url pattern="/welcome/**" requires-channel="http" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    
    <!-- http/https port mappings -->
    <security:port-mappings>
      <security:port-mapping http="8080" https="8443"/>
    </security:port-mappings>
    
  </security:http>

<security:intercept-url/>pattern で URL パターン、それに対応するチャネル(http/https)とアクセス属性をそれぞれ requires-channel, access で指定しています。

そして <security:port-mappings/> で、http, https のそれぞれについて使用するポート番号を指定します。

これで完了です。私の場合、残る作業は、作成した springSecurityConf.xml を以下のように web.xml に登録するだけです。
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
    /WEB-INF/applicationContext.xml
    /WEB-INF/conf/springSecurityConf.xml
    </param-value>
  </context-param>

今回は割りと単純な例でしたが、Spring Sucurity にはまだまだ沢山の機能があります。単純でも一度設定作業に慣れておけば、そうした機能を使いたい時の閾がある程度は低くなると思います。個人的には DB との連動や Spring Social を使ったソーシャルメディアへの接続に興味が沸いてきました。いずれ...というより、(おそらく)次回からは、その辺に挑戦してみたいと思います。

0 件のコメント:

コメントを投稿