開発者ドキュメント

春のセキュリティ+休止状態の注釈の例


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

このチュートリアルでは、以前のリンク://spring-security/spring-security-hibernate-xml-example/[Spring Security + Hibernate4 XML]の例を再利用して、アノテーションベースの例に変換します。

使用される技術:

  1. Spring 3.2.8.RELEASE

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

  3. Hibernate 4.2.11.最終

  4. MySQLサーバ5.6

  5. Tomcat 7(サーブレット3.xコンテナ)

クイックノート:

  1. `LocalSessionFactoryBuilder`を使ってセッションファクトリを作成する

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

  3. ユーザをロードするために、カスタム `UserDetailsS​​ervice`にUserDaoを統合する

データベースから。

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

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



2.ユーザーモデル+マッピングファイル

モデルクラスとそのアノテーションベースのマッピングファイル

User.java

package com.mkyong.users.model;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "users", catalog = "test")
public class User {

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

    public User() {
    }

    public User(String username, String password, boolean enabled) {
        this.username = username;
        this.password = password;
        this.enabled = enabled;
    }

    public User(String username, String password,
        boolean enabled, Set<UserRole> userRole) {
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.userRole = userRole;
    }

    @Id
    @Column(name = "username", unique = true,
        nullable = false, length = 45)
    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Column(name = "password",
        nullable = false, length = 60)
    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Column(name = "enabled", nullable = false)
    public boolean isEnabled() {
        return this.enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
    public Set<UserRole> getUserRole() {
        return this.userRole;
    }

    public void setUserRole(Set<UserRole> userRole) {
        this.userRole = userRole;
    }

}

UserRole.java

package com.mkyong.users.model;

import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "user__roles", catalog = "test",
    uniqueConstraints = @UniqueConstraint(
        columnNames = { "role", "username" }))
public class UserRole{

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

    public UserRole() {
    }

    public UserRole(User user, String role) {
        this.user = user;
        this.role = role;
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "user__role__id",
        unique = true, nullable = false)
    public Integer getUserRoleId() {
        return this.userRoleId;
    }

    public void setUserRoleId(Integer userRoleId) {
        this.userRoleId = userRoleId;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "username", nullable = false)
    public User getUser() {
        return this.user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Column(name = "role", nullable = false, length = 45)
    public String getRole() {
        return this.role;
    }

    public void setRole(String role) {
        this.role = role;
    }

}

DAOクラス

DAOクラスを使用して、Hibernateを介してデータベースからデータをロードします。

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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.mkyong.users.model.User;

@Repository
public class UserDaoImpl implements UserDao {

    @Autowired
    private SessionFactory sessionFactory;

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

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

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

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

    }

}

4. UserDetailsS​​ervice

`@ Transactional`を使ってトランザクションメソッドを宣言します。

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.beans.factory.annotation.Autowired;
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 org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

   //get user from the database, via Hibernate
    @Autowired
    private UserDao userDao;

    @Transactional(readOnly=true)
    @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;
    }

}

5.春のセキュリティ注釈

注釈ですべてを宣言してバインドし、コメントを読んで、それは自明でなければなりません。

SecurityConfig.java

package com.mkyong.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("userDetailsService")
    UserDetailsService userDetailsService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests().antMatchers("/admin/** ** ")
        .access("hasRole('ROLE__ADMIN')").and().formLogin()
        .loginPage("/login").failureUrl("/login?error")
        .usernameParameter("username")
        .passwordParameter("password")
        .and().logout().logoutSuccessUrl("/login?logout")
        .and().csrf()
        .and().exceptionHandling().accessDeniedPage("/403");
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder;
    }

}

`LocalSessionFactoryBuilder`を使用してセッションファクトリを作成します。

AppConfig.java

package com.mkyong.config;

import java.util.Properties;
import org.apache.commons.dbcp.BasicDataSource;
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@EnableWebMvc
@Configuration
@ComponentScan({ "com.mkyong.** " })
@EnableTransactionManagement
@Import({ SecurityConfig.class })
public class AppConfig {

        @Bean
        public SessionFactory sessionFactory() {
                LocalSessionFactoryBuilder builder =
            new LocalSessionFactoryBuilder(dataSource());
                builder.scanPackages("com.mkyong.users.model")
                      .addProperties(getHibernateProperties());

                return builder.buildSessionFactory();
        }

    private Properties getHibernateProperties() {
                Properties prop = new Properties();
                prop.put("hibernate.format__sql", "true");
                prop.put("hibernate.show__sql", "true");
                prop.put("hibernate.dialect",
                    "org.hibernate.dialect.MySQL5Dialect");
                return prop;
        }

    @Bean(name = "dataSource")
    public BasicDataSource dataSource() {

        BasicDataSource ds = new BasicDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/test");
        ds.setUsername("root");
        return ds;
    }

   //Create a transaction manager
    @Bean
        public HibernateTransactionManager txManager() {
                return new HibernateTransactionManager(sessionFactory());
        }

    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver
                             = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/pages/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

}

完了しました。

6.プロジェクトデモ

以下のビデオデモは、//spring-security/spring-security-form-login-using-database/[Spring Security database login]チュートリアルのリンクです。このチュートリアルでは同じ出力が生成されているので、ビデオデモは再利用されています。

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



http://localhost:8080/spring-security-hibernate-annotation/admin


、ログインページが表示されます。



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



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



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

ダウンロードする – リンク://wp-content/uploads/2014/05/spring-security-hibernate-annotation.zip[spring-security-hibernate-annotation.zip](35 KB)

参考文献

  1. リンク://spring-security/spring-security-hibernate-xml-example/[Spring

セキュリティ+ Hibernate XMLの例]。リンク://spring-security/spring-security-hello-world-annotation-example/[Spring

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

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]

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