認証情報(Userのプロパティ)を簡単に増やす部品

Spring Securityで認証が成功すると、認証手形(Authentication)を取得できます。

認証手形にはUser情報が保持されています。

そして、User情報にはID/PWなどがプロパティとして保持され、自由に取得できます。

このUser情報に漢字氏名や住所など、もっといろいろな情報を持たせてJSPなど、様々な箇所で利用したくなることがままあります。

しかし、SpringSecurityでは自由にUserプロパティを増やせる機能が用意されておらず、自作する必要があります。

自作してもそれ程難しくはありませんが、できればそのようなクラスを利用し、設定ファイルの記述だけで実現したいものです。

ここで用意しましたFreePropertyUserDetailsManagerクラスはそんな希望をかなえてくれる部品です。

以下では、具体的に利用方法を見ていきます。

目標

まず、以下のサンプルの目標(ゴール)を示します。

User情報を拡張したAccountクラスを作成します。

Accountクラスには、漢字氏名、都道府県をプロパティに持つものとします。

また漢字氏名、都道府県の情報はDBに保存されているものとします。

認証成功時に、このAccountクラスをSpringSecurityから取得するできるようにすることを目標とします。

使用サンプル

<DBスキーマのサンプル>

CREATE TABLE SEC_OPE_ACCOUNT (

user_id VARCHAR(30) NOT NULL PRIMARY KEY,

user_pw VARCHAR(30) ,

name_kanji VARCHAR(100),

address VARCHAR(32),

authority VARCHAR(100)

) ;

<SpringSecurity設定ファイル: security.xml>

<?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:util="http://www.springframework.org/schema/util"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:sec="http://www.springframework.org/schema/security"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/util

http://www.springframework.org/schema/util/spring-util-2.5.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd

http://www.springframework.org/schema/security

http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">

<!-- DB接続情報。各自設定ください。 -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

<property name="driverClassName" value="org.postgresql.Driver"/>

<property name="url" value="jdbc:postgresql://localhost/test?useUnicode=true&amp;characterEncoding=utf-8" />

<property name="username" value="sa" />

<property name="password" value="" />

</bean>

<sec:http auto-config="true"

access-denied-page="/403.jsp" path-type="ant" >

<sec:intercept-url pattern="/css/*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>

<sec:intercept-url pattern="/error.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>

<sec:intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>

<sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>

<sec:form-login login-page="/login.jsp" default-target-url="/top.html" authentication-failure-url="/login.jsp?error=true"/>

<sec:logout logout-url="/logout" logout-success-url="/login.jsp" invalidate-session="true"/>

<sec:anonymous granted-authority="ROLE_ANONYMOUS"/>

</sec:http>

<!--

認証発行所の設定。

-->

<sec:authentication-provider user-service-ref="userService" />

<!-- 追加したクラスの設定 -->

<bean id="userService" class="jp.co.soracane.security.webapp.FreePropertyUserDetailsManager">

<property name="dataSource" ref="dataSource" />

<property name="usersByUsernameQuery" value=

"SELECT

user_id, user_pw,'true',name_kanji, address

FROM

sec_ope_account

WHERE user_id = ?"/>

<property name="authoritiesByUsernameQuery" value="

select user_id,authority from sec_ope_account

where user_id=?

" />

<property name="propertyNames" value="nameKanji,address" />

<property name="userClass" value="test.security.webapp.UserTestClass" />

</bean>

</beans>

追加したクラスは、プロパティが増えています。

propertyNames

userClass

設定したいAccountクラスのプロパティ名を指定します。

プロパティの型はString[]になっていますので、カンマ区切りで設定すればSpringが自動的に配列にしてくれます。

順番は、SQLのselectのフィールド取得の順になります。selectの先頭の3つは予約されていますので、4つ目からプロパティ名を指定します。

設定したいAccountクラスを指定します。

詳しくは、APIのFreePropertyUserDetailsManagerクラスをご覧ください。

<Accountクラスサンプル: Account.java>

Accountクラスのサンプルです。

SpringSecurityでは、認証ユーザのクラスはUserクラスを継承する必要があります。

public class Account extends User {

private String nameKanji;

private String address;

public UserTestClass(String username, String password, boolean enabled,

boolean accountNonExpired, boolean credentialsNonExpired,

boolean accountNonLocked, GrantedAuthority[] authorities

)

throws IllegalArgumentException {

super(username, password, enabled, accountNonExpired, credentialsNonExpired,

accountNonLocked, authorities);

}

public String getNameKanji() {

return nameKanji;

}

public void setNameKanji(String nameKanji) {

this.nameKanji = nameKanji;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

}

最後に

上記の設定だけで新しく作成したAccountクラスを取得できるようになります。

かなり簡単になったはずです。

追加方法を説明したWEBは結構ありますので、それと見比べてみていただければと思います。

以下はおまけです。

もし、Webのコントローラ内で値を取得したい場合は以下のようにすれば取得できます。

【Account取得の例】

SecurityContext securityContext

= (SecurityContext)request.getSession().getAttribute(HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY);

Account = (Account)securityContext.getAuthentication().getPrincipal();

また、JSP上で取得したい場合も通常通り、以下のようにすれば取得できます。

【SpringSecurityのtaglibを利用した値の取得】

<sec:authentication property="principal.nameKanji" />

Created Date: 2010/01/05