Пример аннотации Spring Security + Hibernate
В этом руководстве предыдущий примерSpring Security + Hibernate4 XML будет повторно использован и преобразован в пример на основе аннотаций.
Используемые технологии:
-
Весна 3.2.8. ВЫПУСК
-
Spring Security 3.2.3.RELEASE
-
Hibernate 4.2.11.Final
-
MySQL Server 5.6
-
Tomcat 7 (контейнер Servlet 3.x)
Быстрое примечание:
-
Создайте фабрику сеансов с
LocalSessionFactoryBuilder
-
Вставить фабрику сеанса в UserDao
-
Интегрируйте UserDao в пользовательский
UserDetailsService
, чтобы загружать пользователей из базы данных.
1. Каталог проектов
Конечная структура каталогов проекта.
2. Модель пользователя + файл сопоставления
Классы моделей и их файл отображения на основе аннотаций.
User.java
package com.example.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 SetuserRole = new HashSet (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) { 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 getUserRole() { return this.userRole; } public void setUserRole(Set userRole) { this.userRole = userRole; } }
UserRole.java
package com.example.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; } }
3. DAO Class
Классы DAO для загрузки данных из базы данных через Hibernate.
UserDao.java
package com.example.users.dao; import com.example.users.model.User; public interface UserDao { User findByUserName(String username); }
UserDaoImpl.java
package com.example.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.example.users.model.User; @Repository public class UserDaoImpl implements UserDao { @Autowired private SessionFactory sessionFactory; @SuppressWarnings("unchecked") public User findByUserName(String username) { Listusers = new ArrayList (); users = sessionFactory.getCurrentSession() .createQuery("from User where username=?") .setParameter(0, username) .list(); if (users.size() > 0) { return users.get(0); } else { return null; } } }
4. UserDetailsService
Использует@Transactional
для объявления метода транзакции.
MyUserDetailsService.java
package com.example.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.example.users.dao.UserDao; import com.example.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.example.users.model.User user = userDao.findByUserName(username); Listauthorities = buildUserAuthority(user.getUserRole()); return buildUserForAuthentication(user, authorities); } // Converts com.example.users.model.User user to // org.springframework.security.core.userdetails.User private User buildUserForAuthentication(com.example.users.model.User user, List authorities) { return new User(user.getUsername(), user.getPassword(), user.isEnabled(), true, true, true, authorities); } private List buildUserAuthority(Set userRoles) { Set setAuths = new HashSet (); // Build user's authorities for (UserRole userRole : userRoles) { setAuths.add(new SimpleGrantedAuthority(userRole.getRole())); } List Result = new ArrayList (setAuths); return Result; } }
5. Spring Security Annotation
Объявляйте и связывайте все с аннотациями, читайте комментарии, это должно быть само за себя.
SecurityConfig.java
package com.example.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.example.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.example.*" }) @EnableTransactionManagement @Import({ SecurityConfig.class }) public class AppConfig { @Bean public SessionFactory sessionFactory() { LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource()); builder.scanPackages("com.example.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 database login. Поскольку этот учебник генерирует тот же вывод, поэтому демонстрационная версия видео используется повторно.
6.1 Access a password protected page : http://localhost:8080/spring-security-hibernate-annotation/admin , a login page is displayed.
6.2 Enter user “example” and password “123456”.
6.3 Try access /admin
page with user “alex” and password “123456”, a 403 page will be displayed.
Скачать исходный код
Скачать -spring-security-hibernate-annotation.zip (35 КБ)