2010年11月28日日曜日

Spring SecurityでDB接続してユーザ認証してみる

Springの認証機構Spring SecurityでのDBと繋いだログイン処理。

・環境
Spring 3.0.5
Roo 1.1.0

基本となる各種設定をSpring Rooでセットアップします。

roo> security setup

Managed ROOT\pom.xml [Adding property 'spring-security.version' to '3.0.2.RELEASE']
Managed ROOT\pom.xml [Added dependency org.springframework.security:spring-security-core:${spring-security.version}]
Managed ROOT\pom.xml [Added dependency org.springframework.security:spring-security-config:${spring-security.version}]
Managed ROOT\pom.xml [Added dependency org.springframework.security:spring-security-web:${spring-security.version}]
Managed ROOT\pom.xml [Added dependency org.springframework.security:spring-security-taglibs:${spring-security.version}]
Created SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-security.xml
Created SRC_MAIN_WEBAPP\WEB-INF\views\login.jspx
Managed SRC_MAIN_WEBAPP\WEB-INF\views\views.xml
Managed SRC_MAIN_WEBAPP\WEB-INF\web.xml
Managed SRC_MAIN_WEBAPP\WEB-INF\spring\webmvc-config.xml

Spring RooによってSpring Securityアドオンがインストールされ、web.xmlにプロキシが登録されたり、各種viewが作成されます。
(実行時のSpring Securityバージョンは3.0.2)

認証機構の定義ファイルとして
SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-security.xml
が生成されます。

<?xml version="1.0" encoding="UTF-8"?>

<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 security configurations -->
    <http auto-config="true" use-expressions="true">
     <form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t"/>
        <logout logout-url="/resources/j_spring_security_logout"/>
        
        <!-- Configure these elements to secure URIs in your application -->
        <intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')"/>
        <intercept-url pattern="/member/**" access="isAuthenticated()" />
        <intercept-url pattern="/resources/**" access="permitAll" />
        <intercept-url pattern="/**" access="permitAll" />
    </http>

 <!-- Configure Authentication mechanism -->
    <authentication-manager alias="authenticationManager">
     <!-- SHA-256 values can be produced using 'echo -n your_desired_password | sha256sum' (using normal *nix environments) -->
     <authentication-provider>
      <password-encoder hash="sha-256"/>
         <user-service>
             <user name="admin" password="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" authorities="ROLE_ADMIN"/>
          <user name="user" password="04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb" authorities="ROLE_USER"/>
      </user-service>
     </authentication-provider>
 </authentication-manager>

</beans:beans>

デフォルトのこの設定ファイルで、
"/choices/**"のURLは'ROLE_ADMIN'なロールを持っていること、
"/member/**"のURLは認証されていること、
その他のアクセスは無制限に許可、
のインターセプトがかかります。

また、User/Passがadmin/adminの場合はROLE_ADMIN、user/userの場合はROLE_USERな権限設定がXMLに直接記述されています。

これをDBに問い合わせ、ユーザ認証を行うように変更します。

<?xml version="1.0" encoding="UTF-8"?>

<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 security configurations -->
    <http auto-config="true" use-expressions="true">
     <form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t"/>
        <logout logout-url="/resources/j_spring_security_logout"/>
        
        <!-- Configure these elements to secure URIs in your application -->
        <!-- cssやimgなどWEBリソースは無制限 -->
        <intercept-url pattern="/resources/**" access="permitAll" />
        <!-- ログイン処理は無制限 -->
        <intercept-url pattern="/login/**" access="permitAll" />
        <!-- それ以外はadmin権限 -->
        <intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
    </http>

 <!-- Configure Authentication mechanism -->
    <authentication-manager alias="authenticationManager">
     <!-- SHA-256 values can be produced using 'echo -n your_desired_password | sha256sum' (using normal *nix environments) -->
     <authentication-provider>
      <!-- sha-256でパスワードをエンコーディングする -->
      <!-- "admin"文字列のハッシュ => "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" -->
      <!-- "user"文字列のハッシュ => "04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb" -->
      <password-encoder hash="sha-256"/>
      <!-- データソース指定。SQL指定。 -->
      <jdbc-user-service data-source-ref="dataSource"
      users-by-username-query="select users_id as username, password as password, true as enabled from users where users_id=?"
      authorities-by-username-query="select users_id as username, 'ROLE_ADMIN' as authority from users where users_id=?"/>
     </authentication-provider>
 </authentication-manager>
</beans:beans>

以下で記述されているスキーマを定義することが好ましいですが、上記の設定ではusersテーブル一つで処理を行っています。
http://static.springsource.org/spring-security/site/docs/2.0.x/reference/appendix-schema.html

usersテーブルにはusers_id、passwordの2つのフィールドが定義されているものとします。

users-by-username-query設定で以下のクエリを発行し、認証を許可するユーザを取得します。

select
    users_id as username,
    password as password,
    true     as enabled
from
    users
where
    users_id=?

authorities-by-username-query設定で実際の認証設定を取得する以下のクエリを発行します。
ユーザが存在し、users-by-username-queryでのユーザ取得が行えれば全てのリソースに接続可能とするため、'ROLE_ADMIN'な固定値をauthorityとして返却します。

select
    users_id     as username,
    'ROLE_ADMIN' as authority
from
    users
where
    users_id=?

usersテーブルに以下のデータを登録すればhoge/adminでログイン可能となります。
users_id:hoge
password:8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918

参考資料)

・Spring Securityの機能について
http://ameblo.jp/spring-beginner/entry-10234230466.html

・実際に認証と認可をWEBにつけるには?
http://ameblo.jp/spring-beginner/entry-10236817063.html

・Spring by Example - Simple Spring Security Webapp
http://www.springbyexample.org/examples/simple-spring-security-webapp-spring-config.html

・5 Minute Guide to Spring Security
http://www.mularien.com/blog/2008/07/07/5-minute-guide-to-spring-security/

・Using Spring-Security Database in Spring-Roo
http://roosbertl.blogspot.com/2010/06/using-spring-security-database-in.html

・Security Database Schema
http://static.springsource.org/spring-security/site/docs/2.0.x/reference/appendix-schema.html

・Security Namespace Configuration
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/ns-config.html#ns-auth-manager

・概説 Springプロダクト(3) - Spring Securityでユーザ認証/アクセス制御
http://journal.mycom.co.jp/articles/2010/03/25/spring3/index.html

・Spring Roo日本語リファレンス - 2.10 セキュアなアプリケーション
http://www.spring-roo.com/home/210

0 件のコメント:

コメントを投稿