diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/CustomAuthenticationProvider.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/CustomAuthenticationProvider.java new file mode 100644 index 0000000000..d7195ac358 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/CustomAuthenticationProvider.java @@ -0,0 +1,38 @@ +package org.baeldung.rolesauthorities; + +import org.baeldung.rolesauthorities.model.User; +import org.baeldung.rolesauthorities.persistence.UserRepository; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetailsService; + +public class CustomAuthenticationProvider extends DaoAuthenticationProvider { + + private final UserRepository userRepository; + @SuppressWarnings("unused") + private UserDetailsService userDetailsService; + + public CustomAuthenticationProvider(UserRepository userRepository, UserDetailsService userDetailsService){ + super(); + this.setUserDetailsService(userDetailsService); + this.userRepository = userRepository; + } + + @Override + public Authentication authenticate(Authentication auth) throws AuthenticationException { + final User user = userRepository.findByEmail(auth.getName()); + if ((user == null)) { + throw new BadCredentialsException("Invalid username or password"); + } + final Authentication result = super.authenticate(auth); + return new UsernamePasswordAuthenticationToken(user, result.getCredentials(), result.getAuthorities()); + } + + @Override + public boolean supports(Class authentication) { + return authentication.equals(UsernamePasswordAuthenticationToken.class); + } +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/MyLogoutSuccessHandler.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/MyLogoutSuccessHandler.java new file mode 100644 index 0000000000..b0dc0b7537 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/MyLogoutSuccessHandler.java @@ -0,0 +1,26 @@ +package org.baeldung.rolesauthorities; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.stereotype.Component; + +@Component("myLogoutSuccessHandler") +public class MyLogoutSuccessHandler implements LogoutSuccessHandler { + + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + final HttpSession session = request.getSession(); + if (session != null) { + session.removeAttribute("user"); + } + + response.sendRedirect("/"); + } +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/MyUserDetailsService.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/MyUserDetailsService.java new file mode 100644 index 0000000000..5749c6194c --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/MyUserDetailsService.java @@ -0,0 +1,60 @@ +package org.baeldung.rolesauthorities; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.baeldung.rolesauthorities.model.Privilege; +import org.baeldung.rolesauthorities.model.Role; +import org.baeldung.rolesauthorities.model.User; +import org.baeldung.rolesauthorities.persistence.UserRepository; +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.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; + +@Service("userDetailsService") +@Transactional +public class MyUserDetailsService implements UserDetailsService { + + @Autowired + private UserRepository userRepository; + + public MyUserDetailsService() { + super(); + } + + // API + + @Override + public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException { + + try { + final User user = userRepository.findByEmail(email); + if (user == null) { + throw new UsernameNotFoundException("No user found with username: " + email); + } + org.springframework.security.core.userdetails.User userDetails = new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), user.isEnabled(), true, true, true, getAuthorities(user.getRoles())); + return userDetails; + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + // UTIL + + private final Collection getAuthorities(final Collection roles) { + final List authorities = new ArrayList(); + for (Role role: roles) { + authorities.add(new SimpleGrantedAuthority(role.getName())); + for (Privilege privilege: role.getPrivileges()) { + authorities.add(new SimpleGrantedAuthority(privilege.getName())); + } + } + return authorities; + } +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/RolesAuthoritiesApplication.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/RolesAuthoritiesApplication.java new file mode 100644 index 0000000000..1c55c145b3 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/RolesAuthoritiesApplication.java @@ -0,0 +1,17 @@ +package org.baeldung.rolesauthorities; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableAutoConfiguration +@ComponentScan("org.baeldung.rolesauthorities") +public class RolesAuthoritiesApplication extends SpringBootServletInitializer { + public static void main(String[] args) { + System.setProperty("spring.profiles.default", "rolesauthorities"); + SpringApplication.run(RolesAuthoritiesApplication.class, args); + } +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/config/MvcConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/config/MvcConfig.java new file mode 100644 index 0000000000..d2edfed749 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/config/MvcConfig.java @@ -0,0 +1,47 @@ +package org.baeldung.rolesauthorities.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + // + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Override + public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/home"); + registry.addViewController("/protectedbynothing").setViewName("rolesauthorities/protectedbynothing"); + registry.addViewController("/protectedbyrole").setViewName("rolesauthorities/protectedbyrole"); + registry.addViewController("/protectedbyauthority").setViewName("rolesauthorities/protectedbyauthority"); + registry.addViewController("/login").setViewName("rolesauthorities/login"); + registry.addViewController("/home").setViewName("rolesauthorities/home"); + registry.addViewController("/logout"); + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/config/SecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/config/SecurityConfig.java new file mode 100644 index 0000000000..cadd477e5e --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/config/SecurityConfig.java @@ -0,0 +1,90 @@ +package org.baeldung.rolesauthorities.config; + +import org.baeldung.rolesauthorities.CustomAuthenticationProvider; +import org.baeldung.rolesauthorities.persistence.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +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.builders.WebSecurity; +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; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; + +@Configuration +@ComponentScan(basePackages = { "org.baeldung.rolesauthorities" }) +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private UserRepository userRepository; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private LogoutSuccessHandler myLogoutSuccessHandler; + + public SecurityConfig() { + super(); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.authenticationProvider(authProvider()); + } + + @Override + public void configure(final WebSecurity web) throws Exception { + web.ignoring() + .antMatchers("/resources/**"); + } + + + @Override + protected void configure(final HttpSecurity http) throws Exception { + + // @formatter:off + http + .csrf().disable() + .authorizeRequests() + .antMatchers("/login*", "/logout*", "/protectedbynothing*", "/home*").permitAll() + .antMatchers("/protectedbyrole").hasRole("USER") + .antMatchers("/protectedbyauthority").hasAuthority("READ_PRIVILEGE") + .and() + .formLogin() + .loginPage("/login") + .failureUrl("/login?error=true") + .permitAll() + .and() + .logout() + .logoutSuccessHandler(myLogoutSuccessHandler) + .invalidateHttpSession(false) + .logoutSuccessUrl("/logout.html?logSucc=true") + .deleteCookies("JSESSIONID") + .permitAll(); + // @formatter:on + } + + // beans + + @Bean + public DaoAuthenticationProvider authProvider() { + final CustomAuthenticationProvider authProvider + = new CustomAuthenticationProvider(userRepository, userDetailsService); + authProvider.setPasswordEncoder(encoder()); + return authProvider; + } + + @Bean + public PasswordEncoder encoder() { + return new BCryptPasswordEncoder(11); + } + +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/model/Privilege.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/model/Privilege.java new file mode 100644 index 0000000000..5165429b5a --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/model/Privilege.java @@ -0,0 +1,89 @@ +package org.baeldung.rolesauthorities.model; + +import java.util.Collection; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToMany; + +@Entity +public class Privilege { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @ManyToMany(mappedBy = "privileges") + private Collection roles; + + public Privilege() { + super(); + } + + public Privilege(final String name) { + super(); + this.name = name; + } + + // + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public Collection getRoles() { + return roles; + } + + public void setRoles(final Collection roles) { + this.roles = roles; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Privilege other = (Privilege) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Privilege [name=").append(name).append("]").append("[id=").append(id).append("]"); + return builder.toString(); + } +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/model/Role.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/model/Role.java new file mode 100644 index 0000000000..9216abe470 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/model/Role.java @@ -0,0 +1,104 @@ +package org.baeldung.rolesauthorities.model; + +import java.util.Collection; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; + +@Entity +public class Role { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @ManyToMany(mappedBy = "roles") + private Collection users; + + @ManyToMany + @JoinTable(name = "roles_privileges", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "privilege_id", referencedColumnName = "id")) + private Collection privileges; + + private String name; + + public Role() { + super(); + } + + public Role(final String name) { + super(); + this.name = name; + } + + // + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public Collection getUsers() { + return users; + } + + public void setUsers(final Collection users) { + this.users = users; + } + + public Collection getPrivileges() { + return privileges; + } + + public void setPrivileges(final Collection privileges) { + this.privileges = privileges; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Role role = (Role) obj; + if (!role.equals(role.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Role [name=").append(name).append("]").append("[id=").append(id).append("]"); + return builder.toString(); + } +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/model/User.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/model/User.java new file mode 100644 index 0000000000..dd5b90e3b2 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/model/User.java @@ -0,0 +1,147 @@ +package org.baeldung.rolesauthorities.model; + +import java.util.Collection; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.Table; + + +@Entity +@Table(name = "user_account") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String firstName; + + private String lastName; + + private String email; + + @Column(length = 60) + private String password; + + private boolean enabled; + + private boolean isUsing2FA; + + // + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) + private Collection roles; + + public User() { + super(); + this.enabled = false; + } + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(final String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(final String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(final String username) { + this.email = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(final String password) { + this.password = password; + } + + public Collection getRoles() { + return roles; + } + + public void setRoles(final Collection roles) { + this.roles = roles; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(final boolean enabled) { + this.enabled = enabled; + } + + public boolean isUsing2FA() { + return isUsing2FA; + } + + public void setUsing2FA(boolean isUsing2FA) { + this.isUsing2FA = isUsing2FA; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + ((email == null) ? 0 : email.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final User user = (User) obj; + if (!email.equals(user.email)) { + return false; + } + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("User [id=").append(id).append(", firstName=") + .append(firstName).append(", lastName=").append(lastName).append(", email=").append(email).append(", password=").append(password).append(", enabled=").append(enabled).append(", roles=").append(roles).append("]"); + return builder.toString(); + } + +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/IUserService.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/IUserService.java new file mode 100644 index 0000000000..2c508cbd20 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/IUserService.java @@ -0,0 +1,9 @@ +package org.baeldung.rolesauthorities.persistence; + +import org.baeldung.rolesauthorities.model.User; + +public interface IUserService { + + User findUserByEmail(String email); + +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/PersistenceJPAConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/PersistenceJPAConfig.java new file mode 100644 index 0000000000..45e47ecb4a --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/PersistenceJPAConfig.java @@ -0,0 +1,77 @@ +package org.baeldung.rolesauthorities.persistence; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence.properties" }) +@ComponentScan({ "org.baeldung.rolesauthorities.persistence" }) +@EnableJpaRepositories(basePackages = "org.baeldung.rolesauthorities.persistence") +public class PersistenceJPAConfig { + + @Autowired + private Environment env; + + public PersistenceJPAConfig() { + super(); + } + + // + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "org.baeldung.rolesauthorities" }); + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); + dataSource.setUrl(env.getProperty("jdbc.url")); + dataSource.setUsername(env.getProperty("jdbc.user")); + dataSource.setPassword(env.getProperty("jdbc.pass")); + return dataSource; + } + + @Bean + public JpaTransactionManager transactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + protected Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + return hibernateProperties; + } + +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/PrivilegeRepository.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/PrivilegeRepository.java new file mode 100644 index 0000000000..05d5f2b870 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/PrivilegeRepository.java @@ -0,0 +1,12 @@ +package org.baeldung.rolesauthorities.persistence; + +import org.baeldung.rolesauthorities.model.Privilege; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PrivilegeRepository extends JpaRepository { + + Privilege findByName(String name); + + void delete(Privilege privilege); + +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/RoleRepository.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/RoleRepository.java new file mode 100644 index 0000000000..25e3b3a1f6 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/RoleRepository.java @@ -0,0 +1,12 @@ +package org.baeldung.rolesauthorities.persistence; + +import org.baeldung.rolesauthorities.model.Role; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RoleRepository extends JpaRepository { + + Role findByName(String name); + + void delete(Role role); + +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/SetupDataLoader.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/SetupDataLoader.java new file mode 100644 index 0000000000..6c1c7d87ef --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/SetupDataLoader.java @@ -0,0 +1,97 @@ +package org.baeldung.rolesauthorities.persistence; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.baeldung.rolesauthorities.model.Privilege; +import org.baeldung.rolesauthorities.model.Role; +import org.baeldung.rolesauthorities.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + + +@Component +public class SetupDataLoader implements ApplicationListener { + + private boolean alreadySetup = false; + + @Autowired + private UserRepository userRepository; + + @Autowired + private RoleRepository roleRepository; + + @Autowired + private PrivilegeRepository privilegeRepository; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Override + @Transactional + public void onApplicationEvent(final ContextRefreshedEvent event) { + if (alreadySetup) { + return; + } + + // == create initial privileges + final Privilege readPrivilege = createPrivilegeIfNotFound("READ_PRIVILEGE"); + final Privilege writePrivilege = createPrivilegeIfNotFound("WRITE_PRIVILEGE"); + + // == create initial roles + final List adminPrivileges = Arrays.asList(readPrivilege, writePrivilege); + createRoleIfNotFound("ROLE_ADMIN", adminPrivileges); + List rolePrivileges = new ArrayList<>(); + createRoleIfNotFound("ROLE_USER", rolePrivileges); + + final Role adminRole = roleRepository.findByName("ROLE_ADMIN"); + final User user = new User(); + user.setFirstName("Admin"); + user.setLastName("Admin"); + user.setEmail("admin@test.com"); + user.setPassword(passwordEncoder.encode("admin")); + user.setRoles(Arrays.asList(adminRole)); + user.setEnabled(true); + userRepository.save(user); + + final Role basicRole = roleRepository.findByName("ROLE_USER"); + final User basicUser = new User(); + basicUser.setFirstName("User"); + basicUser.setLastName("User"); + basicUser.setEmail("user@test.com"); + basicUser.setPassword(passwordEncoder.encode("user")); + basicUser.setRoles(Arrays.asList(basicRole)); + basicUser.setEnabled(true); + userRepository.save(basicUser); + + alreadySetup = true; + } + + @Transactional + private final Privilege createPrivilegeIfNotFound(final String name) { + Privilege privilege = privilegeRepository.findByName(name); + if (privilege == null) { + privilege = new Privilege(name); + privilegeRepository.save(privilege); + } + return privilege; + } + + @Transactional + private final Role createRoleIfNotFound(final String name, final Collection privileges) { + Role role = roleRepository.findByName(name); + if (role == null) { + role = new Role(name); + role.setPrivileges(privileges); + roleRepository.save(role); + } + return role; + } + +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/UserRepository.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/UserRepository.java new file mode 100644 index 0000000000..bca2953153 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/UserRepository.java @@ -0,0 +1,12 @@ +package org.baeldung.rolesauthorities.persistence; + +import org.baeldung.rolesauthorities.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + + User findByEmail(String email); + + void delete(User user); + +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/UserService.java b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/UserService.java new file mode 100644 index 0000000000..bdea674057 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/rolesauthorities/persistence/UserService.java @@ -0,0 +1,19 @@ +package org.baeldung.rolesauthorities.persistence; + +import javax.transaction.Transactional; + +import org.baeldung.rolesauthorities.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@Transactional +public class UserService implements IUserService { + + @Autowired + private UserRepository repository; + + public User findUserByEmail(final String email) { + return repository.findByEmail(email); + } +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/application-rolesauthorities.properties b/spring-security-mvc-boot/src/main/resources/application-rolesauthorities.properties new file mode 100644 index 0000000000..030c79c542 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/application-rolesauthorities.properties @@ -0,0 +1,10 @@ +server.port=8082 +server.context-path=/ +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:security_permission;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE +spring.datasource.username=sa +spring.datasource.password= +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.database=H2 +spring.jpa.show-sql=false +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/persistence.properties b/spring-security-mvc-boot/src/main/resources/persistence.properties new file mode 100644 index 0000000000..b2255cd479 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/persistence.properties @@ -0,0 +1,11 @@ +####### H2 +#################### DataSource Configuration ########################## +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:registration_02;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE +jdbc.user=sa +jdbc.pass= +init-db=false +#################### Hibernate Configuration ########################## +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/home.html b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/home.html new file mode 100644 index 0000000000..a302721570 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/home.html @@ -0,0 +1,25 @@ + + + + + +Role vs Granted Authority Example + + + + + + + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/login.html b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/login.html new file mode 100644 index 0000000000..eacde18459 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/login.html @@ -0,0 +1,57 @@ + + + + +Login + + + + + + +
+
+

Login

+

+ +
+ + + + +

+ + + +

+ + +
+
+
+ + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/protectedbyauthority.html b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/protectedbyauthority.html new file mode 100644 index 0000000000..c62a111ebc --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/protectedbyauthority.html @@ -0,0 +1,24 @@ + + + + +Protected By Authority + + + +
+

Protected By Authority

+
+ + + + diff --git a/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/protectedbynothing.html b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/protectedbynothing.html new file mode 100644 index 0000000000..a6cd0666db --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/protectedbynothing.html @@ -0,0 +1,21 @@ + + + + +Protected By Nothing + + + +
+

Protected By Nothing

+
+ + + + diff --git a/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/protectedbyrole.html b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/protectedbyrole.html new file mode 100644 index 0000000000..f4bac55b55 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/rolesauthorities/protectedbyrole.html @@ -0,0 +1,24 @@ + + + + +Protected By Role + + + +
+

Protected By Role

+
+ + + +