開発者ドキュメント

SpringセキュリティHibernate XMLの例


spring-hibernate-logo、width = 514、height = 115

このチュートリアルでは、Hibernate 4をSpring Security、XMLの設定例に統合する方法について説明します。

使用される技術:

  1. Spring 3.2.8.RELEASE

  2. 春のセキュリティ3.2.3.RELEASE

  3. Hibernate 4.2.11.最終

  4. MySQLサーバ5.6

  5. JDK 1.6

  6. Maven 3

  7. Eclipse 4.3

クイックノート

  1. `hibernate4.LocalSessionFactoryBean`でセッションファクトリを作成します.

  2. セッションファクトリをUserDaoに注入する

  3. Spring Securityと統合するには、そのクラスを実装するクラスを作成します.

`UserDetailsS​​ervice`インターフェースを呼び出し、UserDaoでUserを読み込みます
。トランザクションマネージャが宣言されていなければなりません。そうでなければ、Hibernateは動作しません

1.プロジェクトディレクトリ

最終的なプロジェクトディレクトリ構造。



プロジェクトの依存関係

POMファイル内のプロジェクトの依存関係のリスト。

pom.xml

    <properties>
        <spring.version>3.2.8.RELEASE</spring.version>
        <spring.security.version>3.2.3.RELEASE</spring.security.version>
        <jstl.version>1.2</jstl.version>
        <mysql.connector.version>5.1.30</mysql.connector.version>
        <logback.version>1.1.2</logback.version>
        <slf4j.version>1.7.6</slf4j.version>
        <hibernate.version>4.2.11.Final</hibernate.version>
        <dbcp.version>1.4</dbcp.version>
        <servletapi.version>2.5</servletapi.version>
    </properties>

    <dependencies>

        <!-- database pool -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>${dbcp.version}</version>
        </dependency>

        <!-- Hibernate ORM -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <!-- Spring 3 dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
            <exclusions>
              <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
              </exclusion>
            </exclusions>
        </dependency>

        <!-- Spring MVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Spring + aspects -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- ORM integration, e.g Hibernate -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${spring.security.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${spring.security.version}</version>
        </dependency>

        <!-- Spring Security JSP Taglib -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>${spring.security.version}</version>
        </dependency>

        <!-- jstl for jsp page -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>

        <!-- MySql Driver -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.connector.version}</version>
        </dependency>

        <!-- logging, slf4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>${servletapi.version}</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

3.ユーザーテーブル

ユーザーとユーザーの役割を格納するテーブルを作成するSQLスクリプト。

mysql.sql

CREATE  TABLE users (
  username VARCHAR(45) NOT NULL ,
  password VARCHAR(60) NOT NULL ,
  enabled TINYINT NOT NULL DEFAULT 1 ,
  PRIMARY KEY (username));

CREATE TABLE user__roles (
  user__role__id int(11) NOT NULL AUTO__INCREMENT,
  username varchar(45) NOT NULL,
  role varchar(45) NOT NULL,
  PRIMARY KEY (user__role__id),
  UNIQUE KEY uni__username__role (role,username),
  KEY fk__username__idx (username),
  CONSTRAINT fk__username FOREIGN KEY (username) REFERENCES users (username));

INSERT INTO users(username,password,enabled)
VALUES ('mkyong','$2a$10$04TVADrR6/SPLBjsK0N30.Jf5fNjBugSACeGv1S69dZALR7lSov0y', true);
INSERT INTO users(username,password,enabled)
VALUES ('alex','$2a$10$04TVADrR6/SPLBjsK0N30.Jf5fNjBugSACeGv1S69dZALR7lSov0y', true);

INSERT INTO user__roles (username, role)
VALUES ('mkyong', 'ROLE__USER');
INSERT INTO user__roles (username, role)
VALUES ('mkyong', 'ROLE__ADMIN');
INSERT INTO user__roles (username, role)
VALUES ('alex', 'ROLE__USER');

4.ユーザモデルのHibernate XMLマッピング

モデルクラスとその ‘XMLマッピングファイル。

User.java

package com.mkyong.users.model;

import java.util.HashSet;
import java.util.Set;

public class User {

    private String username;
    private String password;
    private boolean enabled;
    private Set<UserRole> userRole = new HashSet<UserRole>(0);

   //getter and setter methods
}

UserRole.java

package com.mkyong.users.model;

public class UserRole{

    private Integer userRoleId;
    private User user;
    private String role;

   //getter and setter methods
}

Users.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.mkyong.users.model.User" table="users" catalog="test">
        <id name="username" type="string">
            <column name="username" length="45"/>
            <generator class="assigned"/>
        </id>
        <property name="password" type="string">
            <column name="password" length="60" not-null="true"/>
        </property>
        <property name="enabled" type="boolean">
            <column name="enabled" not-null="true"/>
        </property>
        <set name="userRole" table="user__roles" inverse="true" lazy="true" fetch="select">
            <key>
                <column name="username" length="45" not-null="true"/>
            </key>
            <one-to-many class="com.mkyong.users.model.UserRole"/>
        </set>
    </class>
</hibernate-mapping>

UserRoles.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.mkyong.users.model.UserRole" table="user__roles" catalog="test">
        <id name="userRoleId" type="java.lang.Integer">
            <column name="user__role__id"/>
            <generator class="identity"/>
        </id>
        <many-to-one name="user" class="com.mkyong.users.model.User" fetch="select">
            <column name="username" length="45" not-null="true"/>
        </many-to-one>
        <property name="role" type="string">
            <column name="role" length="45" not-null="true"/>
        </property>
    </class>
</hibernate-mapping>

5. DAOクラス

Hibernateを介してデータベースからユーザをロードするための `UserDao`クラスを作成します。

UserDao.java

package com.mkyong.users.dao;

import com.mkyong.users.model.User;

public interface UserDao {

    User findByUserName(String username);

}

UserDaoImpl.java

package com.mkyong.users.dao;

import java.util.ArrayList;
import java.util.List;
import org.hibernate.SessionFactory;

import com.mkyong.users.model.User;

public class UserDaoImpl implements UserDao {

    private SessionFactory sessionFactory;

    @SuppressWarnings("unchecked")
    public User findByUserName(String username) {

        List<User> users = new ArrayList<User>();

        users = getSessionFactory().getCurrentSession()
            .createQuery("from User where username=?")
            .setParameter(0, username).list();

        if (users.size() > 0) {
            return users.get(0);
        } else {
            return null;
        }

    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

}

6. UserDetailsS​​ervice

カスタム

UserDetailsS​​ervice`を作成し、

UserDao`からユーザーをロードし、ユーザーの権限を作成します。

  • 注意** 例はこのSpringのリンクからの参照です:org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl[JdbcDaoImpl]

MyUserDetailsS​​ervice.java

package com.mkyong.users.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.mkyong.users.dao.UserDao;
import com.mkyong.users.model.UserRole;

public class MyUserDetailsService implements UserDetailsService {

    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(final String username)
               throws UsernameNotFoundException {

        com.mkyong.users.model.User user = userDao.findByUserName(username);
        List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole());

        return buildUserForAuthentication(user, authorities);


    }

   //Converts com.mkyong.users.model.User user to
   //org.springframework.security.core.userdetails.User
    private User buildUserForAuthentication(com.mkyong.users.model.User user,
        List<GrantedAuthority> authorities) {
        return new User(user.getUsername(),
            user.getPassword(), user.isEnabled(),
                        true, true, true, authorities);
    }

    private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {

        Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

       //Build user's authorities
        for (UserRole userRole : userRoles) {
            setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
        }

        List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);

        return Result;
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

}

7.春のセキュリティXML

コメントを読んで、それは自明であるべきです。

spring-security.xml

<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.2.xsd">

    <!-- enable use-expressions -->
    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/admin** ** " access="hasRole('ROLE__ADMIN')"/>

        <!-- access denied page -->
        <access-denied-handler error-page="/403"/>
        <form-login
            login-page="/login"
            default-target-url="/welcome"
            authentication-failure-url="/login?error"
            username-parameter="username"
            password-parameter="password"/>
        <logout logout-success-url="/login?logout"/>
        <!-- enable csrf protection -->
        <csrf/>
    </http>

    <authentication-manager>
        <authentication-provider user-service-ref="myUserDetailsService" >
            <password-encoder hash="bcrypt"/>
        </authentication-provider>
    </authentication-manager>

</beans:beans>

spring-database.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

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

        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>

    <!-- Hibernate session factory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingResources">
            <list>
                <value>orm/Users.hbm.xml</value>
                <value>orm/UserRoles.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
            <prop key="hibernate.dialect">
                           org.hibernate.dialect.MySQL5Dialect
                        </prop>
            <prop key="hibernate.format__sql">true</prop>
            <prop key="hibernate.show__sql">true</prop>
            </props>
        </property>
    </bean>

    <bean id="userDao" class="com.mkyong.users.dao.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="myUserDetailsService"
                class="com.mkyong.users.service.MyUserDetailsService">
        <property name="userDao" ref="userDao"/>
    </bean>

    <!-- MUST have transaction manager, using aop and aspects  -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
        <tx:method name="get** " read-only="true"/>
        <tx:method name="find** " read-only="true"/>
        <tx:method name="** "/>
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="userServicePointCut"
        expression="execution(**  com.mkyong.users.service.** Service.** (..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointCut"/>
    </aop:config>

</beans>

完了しました。

  • 注意** これらのJSP、web.xml、コントローラファイルは省略されていますが、それはかなり標準的なコードです。興味があれば、記事の末尾にある完全なソースコードをダウンロードしてください。

8.プロジェクトデモ

次のビデオデモは、//spring-security/spring-security-form-login-using-database/[Springセキュリティデータベースログインwith JDBC]チュートリアルのリンクです。このチュートリアルでは同じ出力を生成していますが、Hibernateを使用してユーザーをロードするので、ビデオデモが再利用されるためです。

8.1パスワードで保護されたページにアクセスする:



8.2ユーザ “mkyong”とパスワード “123456”を入力します。



8.3ユーザー “alex”とパスワード “123456”で `/admin`ページにアクセスしようとすると、403ページが表示されます。



ソースコードをダウンロードする

ダウンロードする –

spring-security-hibernate.zip

(30 KB)

参考文献

トランザクション管理]。

Hibernate ORM documentation

  1. リンク://spring-security/spring-security-form-login-using-database/[Spring

データベースを使用したセキュリティフォームのログイン、JDBC付き]。リンク://spring/spring-hibernate-no-session-found-for-current-thread/[Hibernate

: No Session Found For Current Thread]

モバイルバージョンを終了