認証情報(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&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