読者です 読者をやめる 読者になる 読者になる

Spring Security 3.0.x

概要

Wicketで作っているアプリにSpring Securityのログイン機能を追加する方法を調査中しています。WicketがURLを自動生成するのに対し、Spring SecurityはURLのパターンでアクセス制御をするので、このアンマッチがまだうまく解決できていませんが、Spring Securityの基本的な設定自体はできたので途中経過を書いておきます。

Spring Security http://static.springsource.org/spring-security/site/index.html

リファレンス http://static.springsource.org/spring-security/site/docs/3.0.x/reference/springsecurity.html

Spring Securityの設定手順

pom.xmlに追加
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-web</artifactId>
  <version>3.0.0.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-config</artifactId>
  <version>3.0.0.RELEASE</version>
</dependency>

※手元の環境ではとりあえずこの2つを追記しておけば、Spring Securityが動きました。


web.xmlの冒頭に追加
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext-security.xml</param-value>
</context-param>

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>



applicationContext-security.xmlファイルを作成して、WEB-INFに配置
<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  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.0.xsd">

  <http auto-config='true'>
    <intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
    <intercept-url pattern="/user/**" access="ROLE_USER" />
    <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
  </http>

   <authentication-manager>
    <authentication-provider>
      <user-service>
        <user name="adminUser" password="abc" authorities="ROLE_USER, ROLE_ADMIN" />
        <user name="normalUser" password="xyz" authorities="ROLE_USER" />
      </user-service>
    </authentication-provider>
  </authentication-manager>
</beans:beans>



結果

・「http://サーバ名/コンテキスト名/spring_security_login」でログイン画面の表示
・「http://サーバ名/コンテキスト名/admin/以下全て」には、adminUserでログインしていないとアクセス不可(強制的にログイン画面に遷移)
・「http://サーバ名/コンテキスト名/user/以下全て」には、adminUserかnormalUserでログインしていないとアクセス不可(強制的にログイン画面に遷移)
・「http://サーバ名/コンテキスト名/上記以外」はログインなしでもアクセス可能

特に何も設定していないので、ログイン画面はSpringが用意した簡単な画面が表示されますが、設定を追加すればオリジナルのログイン画面やURLが使用できます。設定の追加でユーザ情報をDBから取得するようなことも可能です。

ここまでの設定はWicketとは関係していないSpring Securityのみの設定です。またMavenがspring-coreを自動的に落としてきたので裏では使っているかもしれませんが、SpringのDIも直接は使用していません。簡単な認証機能をWebアプリに追加するだけなら、これだけの機能でも結構よさそうです。

Wicketとの連携

まだ、調査中の段階です。WicketはURLを自動生成ですが、mountBookmarkablePageとsetEnforceMounts(true)の組み合わせで、/admin/xxxといったURLを指定すればいいかもしれません。

リファレンスを見ていると、ログイン情報はJavaの中から参照可能なので、当座の対応としてコード内でチェックするルーチンを試作してみました。getPrincipal()の辺りが複数ユーザの同時ログインに対応できていなさそうですが、続きはまた後日

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

public class LoginCheck {
  private final static String ROLE_ADMIN = "ROLE_ADMIN";
  private final static String ROLE_USER = "ROLE_USER";

  public static boolean isAdmin() {
    return check(ROLE_ADMIN);
  }

  public static boolean isUser() {
    return check(ROLE_USER);
  }

  private static boolean check(String role) {
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    boolean login = false;
    if (principal instanceof UserDetails) {
      UserDetails user = ((UserDetails) principal);
      for (GrantedAuthority authority : user.getAuthorities()) {
        if (authority.getAuthority().equals(role)) {
          login = true;
        }
      }
    } else {
      login = false;
    }

    return login;
  }
}

TODO

こんなページがあった
http://cwiki.apache.org/WICKET/spring-security-and-wicket-auth-roles.html

2010/04/13追記
Wicket認証機能編を追加しました。