├── .DS_Store ├── .classpath ├── .project ├── .settings ├── .jsdtscope ├── org.eclipse.jdt.core.prefs ├── org.eclipse.m2e.core.prefs ├── org.eclipse.wst.common.component ├── org.eclipse.wst.common.project.facet.core.xml ├── org.eclipse.wst.jsdt.ui.superType.container ├── org.eclipse.wst.jsdt.ui.superType.name └── org.eclipse.wst.validation.prefs ├── README.md ├── pom.xml ├── sql-scripts ├── .DS_Store └── spring_security_custom_user_registration_demo.sql ├── src ├── .DS_Store ├── main │ ├── .DS_Store │ ├── java │ │ ├── .DS_Store │ │ └── com │ │ │ └── brane │ │ │ └── security │ │ │ └── user │ │ │ └── reg │ │ │ └── form │ │ │ ├── config │ │ │ ├── CustomAuthenticationSuccessHandler.java │ │ │ ├── DemoAppConfig.java │ │ │ ├── DemoSecurityConfig.java │ │ │ ├── MySpringMvcDispatcherServletInitializer.java │ │ │ └── SecurityWebApplicationInitializer.java │ │ │ ├── controller │ │ │ ├── DemoController.java │ │ │ ├── LoginController.java │ │ │ └── RegistrationController.java │ │ │ ├── dao │ │ │ ├── RoleDao.java │ │ │ ├── RoleDaoImpl.java │ │ │ ├── UserDao.java │ │ │ └── UserDaoImpl.java │ │ │ ├── entity │ │ │ ├── Role.java │ │ │ └── User.java │ │ │ ├── service │ │ │ ├── UserService.java │ │ │ └── UserServiceImpl.java │ │ │ ├── user │ │ │ └── CrmUser.java │ │ │ └── validation │ │ │ ├── EmailValidator.java │ │ │ ├── FieldMatch.java │ │ │ ├── FieldMatchValidator.java │ │ │ └── ValidEmail.java │ ├── resources │ │ └── persistence-mysql.properties │ └── webapp │ │ ├── .DS_Store │ │ └── WEB-INF │ │ ├── .DS_Store │ │ └── view │ │ ├── access-denied.jsp │ │ ├── fancy-login.jsp │ │ ├── home.jsp │ │ ├── leaders.jsp │ │ ├── registration-confirmation.jsp │ │ ├── registration-form.jsp │ │ └── systems.jsp └── test │ ├── .DS_Store │ └── java │ ├── .DS_Store │ └── com │ ├── .DS_Store │ └── luv2code │ ├── .DS_Store │ └── springsecurity │ ├── .DS_Store │ └── demo │ └── AppTest.java └── target ├── classes ├── .DS_Store ├── com │ └── brane │ │ └── security │ │ └── user │ │ └── reg │ │ └── form │ │ ├── config │ │ ├── CustomAuthenticationSuccessHandler.class │ │ ├── DemoAppConfig.class │ │ ├── DemoSecurityConfig.class │ │ ├── MySpringMvcDispatcherServletInitializer.class │ │ └── SecurityWebApplicationInitializer.class │ │ ├── controller │ │ ├── DemoController.class │ │ ├── LoginController.class │ │ └── RegistrationController.class │ │ ├── dao │ │ ├── RoleDao.class │ │ ├── RoleDaoImpl.class │ │ ├── UserDao.class │ │ └── UserDaoImpl.class │ │ ├── entity │ │ ├── Role.class │ │ └── User.class │ │ ├── service │ │ ├── UserService.class │ │ └── UserServiceImpl.class │ │ ├── user │ │ └── CrmUser.class │ │ └── validation │ │ ├── EmailValidator.class │ │ ├── FieldMatch$List.class │ │ ├── FieldMatch.class │ │ ├── FieldMatchValidator.class │ │ └── ValidEmail.class └── persistence-mysql.properties ├── m2e-wtp └── web-resources │ └── META-INF │ ├── MANIFEST.MF │ └── maven │ └── com.luv2code │ └── spring-security-custom-user-registration-demo │ ├── pom.properties │ └── pom.xml └── test-classes ├── .DS_Store └── com ├── .DS_Store └── luv2code ├── .DS_Store └── springsecurity ├── .DS_Store └── demo └── AppTest.class /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/.DS_Store -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | security-user-reg-form-custom-user-details-jdbc-bcrypt-auth 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.wst.common.project.facet.core.builder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.validation.validationbuilder 20 | 21 | 22 | 23 | 24 | org.eclipse.m2e.core.maven2Builder 25 | 26 | 27 | 28 | 29 | 30 | org.eclipse.jem.workbench.JavaEMFNature 31 | org.eclipse.wst.common.modulecore.ModuleCoreNature 32 | org.eclipse.jdt.core.javanature 33 | org.eclipse.m2e.core.maven2Nature 34 | org.eclipse.wst.common.project.facet.core.nature 35 | org.eclipse.wst.jsdt.core.jsNature 36 | 37 | 38 | -------------------------------------------------------------------------------- /.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 4 | org.eclipse.jdt.core.compiler.compliance=11 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 7 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 8 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 9 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning 10 | org.eclipse.jdt.core.compiler.release=disabled 11 | org.eclipse.jdt.core.compiler.source=11 12 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.validation.prefs: -------------------------------------------------------------------------------- 1 | disabled=06target 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SPRING CRM with custom LOGIN PAGE and REGISTRATION FORM(custom user details) with SPRING SECURITY and JDBC AUTHENTICATION and AUTHORIZATION using BCRYPT algorithm 2 | 3 | In this project I used Spring Security for JDBC authentication and authorization with custom login page. 4 | I applied authorization for appropriate user roles (EMPLOYEE, MANAGER or ADMIN). 5 | 6 | ![1](https://user-images.githubusercontent.com/61464267/133894398-2ad95442-8f03-4ef2-a26e-7156fa538c54.PNG) 7 | 8 | I also made registration form, so we can register a new user and save it to the database.Every new user which we registered have EMPLOYEE role by default.In database we have already stored some users with role MANAGER and ADMIN, these users have also role EMPLOYEE. 9 | 10 | This registration form have validation rules, because in this example we used Hibernate Validator.We made our custom validation rules, ie. custom java annoations.On the next picture we can see how registration form looks like, but first we will break this validations to see all error messages. 11 | 12 | ![2](https://user-images.githubusercontent.com/61464267/133895376-e52b2dea-e073-4ade-8ff0-8b8ae8d87bca.PNG) 13 | 14 | Username field, can't have null value and must have min 1 char.I also checked the case if we enterd the username which already exists in the database, to show as an error message:"User name already exists". 15 | 16 | Password field, can't have null value and must have min 1 char. 17 | 18 | Confirm Password field, can't have null value and must have min 1 char also. 19 | For these two fields, I made my custom validation rule and my custom annotation, because these two fields must match.If they don't match we will get an error message:"The password fields must match". 20 | 21 | First name field, can't have null value and must have min 1 char. 22 | 23 | Last name field, can't have null value and must have min 1 char. 24 | 25 | Email field, can't have null value and must have min 1 char.Here I also made my custom validation rule and my custom annotation, for this field I used regular expressions for email. 26 | 27 | When we enter a valid data in registration form, and when we press button register, then we saved all that user information into the database.In this case we made one database with following tables:user, role and user_role. 28 | 29 | ![2](https://user-images.githubusercontent.com/61464267/133896298-41d9d68a-8361-4182-8687-e73bc9dee8bd.PNG)![3](https://user-images.githubusercontent.com/61464267/133896310-a2e52a6b-580c-4d88-bde7-434e75ed8993.PNG)![4](https://user-images.githubusercontent.com/61464267/133896322-9ff1d7b6-9466-4768-a046-d2166f5e087f.PNG) 30 | 31 | In this project as we can see I used bcrypt algorithm for password encryption, this is one-way encrypted hashing, so the password in the database can never be decrypted. To protect against CSRF attacks I used additional authentication data/token into all HTML forms.On this way we can prevent evil website to tricks us into executing an action on a web application that you are currently logged in.For each request we have randomly generated token and Spring Security verifies token before processing. 32 | 33 | On the next picture we can see relationships between the tables.We made N:M-MANY TO MANY relationship between the tables user and role, because one user can have many roles and one role can have many users.To achieve this I made one more table, link table called user_role. 34 | 35 | ![5](https://user-images.githubusercontent.com/61464267/133896678-60110a13-30a7-4d89-802d-c9325958c656.PNG) 36 | 37 | When we are logged in our app with appropriate username and password, we have security authorization, so the user with role EMPLOYEE can only see this page with all information about user, such is:username, role, first name, last name and email. 38 | 39 | ![6](https://user-images.githubusercontent.com/61464267/133896944-6283aad7-3328-4435-a6f8-9702927bc30b.PNG) 40 | 41 | The user with role MANAGER have access some additional page Leadership Meeting. 42 | 43 | ![7](https://user-images.githubusercontent.com/61464267/133897121-245b2e7f-b973-464c-a194-fa5e8cf81572.PNG) 44 | 45 | When we enter on that page we can see some additional information. 46 | 47 | ![8](https://user-images.githubusercontent.com/61464267/133897190-dff6ce06-554d-4ae4-9126-b45739742704.PNG) 48 | 49 | The user with role ADMIN also have access some additional page IT Systems Meeting. 50 | 51 | ![9](https://user-images.githubusercontent.com/61464267/133897223-d2495a70-76c6-4cf9-a68a-be5cd5202392.PNG) 52 | 53 | When we enter on that page we can see some following additional information. 54 | 55 | ![10](https://user-images.githubusercontent.com/61464267/133897271-fed5c538-814b-41f2-a742-a6fb0e86beff.PNG) 56 | 57 | I also added logout button, because we want to logout the user from the system, on that way we also removing http session, cookies, etc… 58 | 59 | If some other user which is not authorized trys to access some additional information and pages, he will get access denied page with message. 60 | 61 | ![11](https://user-images.githubusercontent.com/61464267/133897329-3aabc3c5-6e90-4a40-a77c-646727740664.PNG) 62 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.luv2code 6 | spring-security-custom-user-registration-demo 7 | 1.0.0 8 | war 9 | 10 | spring-security-custom-user-registration-demo 11 | 12 | 13 | 5.0.2.RELEASE 14 | 5.0.0.RELEASE 15 | 16 | 5.5.0.Final 17 | 8.0.20 18 | 0.9.5.2 19 | 20 | 1.11 21 | 1.11 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.springframework 29 | spring-webmvc 30 | ${springframework.version} 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.springframework.security 38 | spring-security-web 39 | ${springsecurity.version} 40 | 41 | 42 | 43 | org.springframework.security 44 | spring-security-config 45 | ${springsecurity.version} 46 | 47 | 48 | 49 | 50 | org.springframework.security 51 | spring-security-taglibs 52 | ${springsecurity.version} 53 | 54 | 55 | 56 | 57 | javax.servlet 58 | javax.servlet-api 59 | 3.1.0 60 | 61 | 62 | 63 | javax.servlet.jsp 64 | javax.servlet.jsp-api 65 | 2.3.1 66 | 67 | 68 | 69 | 70 | taglibs 71 | standard 72 | 1.1.2 73 | 74 | 75 | 76 | javax.servlet 77 | jstl 78 | 1.2 79 | 80 | 81 | 82 | 83 | org.springframework 84 | spring-tx 85 | ${springframework.version} 86 | 87 | 88 | 89 | 90 | org.springframework 91 | spring-orm 92 | ${springframework.version} 93 | 94 | 95 | 96 | 97 | org.hibernate 98 | hibernate-core 99 | ${hibernate.version} 100 | 101 | 102 | 103 | 104 | 105 | mysql 106 | mysql-connector-java 107 | ${mysql.connector.version} 108 | 109 | 110 | 111 | 112 | com.mchange 113 | c3p0 114 | ${c3po.version} 115 | 116 | 117 | 118 | 119 | org.hibernate 120 | hibernate-validator 121 | 6.1.7.Final 122 | 123 | 124 | 125 | junit 126 | junit 127 | 3.8.1 128 | test 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | spring-security-custom-user-registration-demo 137 | 138 | 139 | 140 | 141 | org.apache.maven.plugins 142 | maven-war-plugin 143 | 3.2.0 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /sql-scripts/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/sql-scripts/.DS_Store -------------------------------------------------------------------------------- /sql-scripts/spring_security_custom_user_registration_demo.sql: -------------------------------------------------------------------------------- 1 | DROP DATABASE IF EXISTS `spring_security_custom_user_demo`; 2 | 3 | CREATE DATABASE IF NOT EXISTS `spring_security_custom_user_demo`; 4 | USE `spring_security_custom_user_demo`; 5 | 6 | -- 7 | -- Table structure for table `user` 8 | -- 9 | 10 | DROP TABLE IF EXISTS `user`; 11 | 12 | CREATE TABLE `user` ( 13 | `id` int(11) NOT NULL AUTO_INCREMENT, 14 | `username` varchar(50) NOT NULL, 15 | `password` char(80) NOT NULL, 16 | `first_name` varchar(50) NOT NULL, 17 | `last_name` varchar(50) NOT NULL, 18 | `email` varchar(50) NOT NULL, 19 | PRIMARY KEY (`id`) 20 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; 21 | 22 | -- 23 | -- Dumping data for table `user` 24 | -- 25 | -- NOTE: The passwords are encrypted using BCrypt 26 | -- 27 | -- A generation tool is avail at: http://www.luv2code.com/generate-bcrypt-password 28 | -- 29 | -- Default passwords here are: fun123 30 | -- 31 | 32 | INSERT INTO `user` (username,password,first_name,last_name,email) 33 | VALUES 34 | ('john','$2a$04$eFytJDGtjbThXa80FyOOBuFdK2IwjyWefYkMpiBEFlpBwDH.5PM0K','John','Doe','john@luv2code.com'), 35 | ('mary','$2a$04$eFytJDGtjbThXa80FyOOBuFdK2IwjyWefYkMpiBEFlpBwDH.5PM0K','Mary','Public','mary@luv2code.com'), 36 | ('susan','$2a$04$eFytJDGtjbThXa80FyOOBuFdK2IwjyWefYkMpiBEFlpBwDH.5PM0K','Susan','Adams','susan@luv2code.com'); 37 | 38 | 39 | -- 40 | -- Table structure for table `role` 41 | -- 42 | 43 | DROP TABLE IF EXISTS `role`; 44 | 45 | CREATE TABLE `role` ( 46 | `id` int(11) NOT NULL AUTO_INCREMENT, 47 | `name` varchar(50) DEFAULT NULL, 48 | PRIMARY KEY (`id`) 49 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; 50 | 51 | -- 52 | -- Dumping data for table `roles` 53 | -- 54 | 55 | INSERT INTO `role` (name) 56 | VALUES 57 | ('ROLE_EMPLOYEE'),('ROLE_MANAGER'),('ROLE_ADMIN'); 58 | 59 | -- 60 | -- Table structure for table `users_roles` 61 | -- 62 | 63 | DROP TABLE IF EXISTS `users_roles`; 64 | 65 | CREATE TABLE `users_roles` ( 66 | `user_id` int(11) NOT NULL, 67 | `role_id` int(11) NOT NULL, 68 | 69 | PRIMARY KEY (`user_id`,`role_id`), 70 | 71 | KEY `FK_ROLE_idx` (`role_id`), 72 | 73 | CONSTRAINT `FK_USER_05` FOREIGN KEY (`user_id`) 74 | REFERENCES `user` (`id`) 75 | ON DELETE NO ACTION ON UPDATE NO ACTION, 76 | 77 | CONSTRAINT `FK_ROLE` FOREIGN KEY (`role_id`) 78 | REFERENCES `role` (`id`) 79 | ON DELETE NO ACTION ON UPDATE NO ACTION 80 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 81 | 82 | SET FOREIGN_KEY_CHECKS = 1; 83 | 84 | -- 85 | -- Dumping data for table `users_roles` 86 | -- 87 | 88 | INSERT INTO `users_roles` (user_id,role_id) 89 | VALUES 90 | (1, 1), 91 | (2, 1), 92 | (2, 2), 93 | (3, 1), 94 | (3, 3) -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/.DS_Store -------------------------------------------------------------------------------- /src/main/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/main/.DS_Store -------------------------------------------------------------------------------- /src/main/java/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/main/java/.DS_Store -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/config/CustomAuthenticationSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.config; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import javax.servlet.http.HttpSession; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.security.core.Authentication; 12 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 13 | import org.springframework.stereotype.Component; 14 | 15 | import com.brane.security.user.reg.form.entity.User; 16 | import com.brane.security.user.reg.form.service.UserService; 17 | 18 | //we are going to add @Component annotation so we can automatically register bean 19 | //customAuthenticationSuccessHandler, because we need to inject that bean in class DemoSecurityConfig. 20 | @Component 21 | //This is a strategy used to handle a successful user authentication. 22 | //After a user has logged in by submitting a login form, 23 | //the application needs to decide where they should be redirected. 24 | public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler { 25 | 26 | //We are going to do dependency injection here, so we can call findByUserName method 27 | //from the UserServiceImpl class. 28 | @Autowired 29 | private UserService userService; 30 | 31 | 32 | @Override 33 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) 34 | throws IOException, ServletException { 35 | 36 | System.out.println("\n\nIn customAuthenticationSuccessHandler\n\n"); 37 | 38 | //Authentication interface extends interface Principal and Principal interface have method getName. 39 | //Principal is actually username. 40 | String userName = authentication.getName(); 41 | 42 | System.out.println("userName=" + userName); 43 | 44 | //We here delegate calls from the SERVICE layer to the DAO layer. 45 | //We have now single object user, because in DAO layer we are using method getSingleResult(). 46 | //It is designed to retrieve single result when there is truly a single result. 47 | User theUser = userService.findByUserName(userName); 48 | 49 | //now place object theUser in the session 50 | HttpSession session = request.getSession(); 51 | //user is string name, theUser is object value 52 | session.setAttribute("user", theUser); 53 | 54 | //forward user to home page (redirect user) 55 | response.sendRedirect(request.getContextPath() + "/"); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/config/DemoAppConfig.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.config; 2 | 3 | import java.beans.PropertyVetoException; 4 | import java.util.Properties; 5 | import java.util.logging.Logger; 6 | 7 | import javax.sql.DataSource; 8 | 9 | import org.hibernate.SessionFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.ComponentScan; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.context.annotation.PropertySource; 15 | import org.springframework.core.env.Environment; 16 | import org.springframework.orm.hibernate5.HibernateTransactionManager; 17 | import org.springframework.orm.hibernate5.LocalSessionFactoryBean; 18 | import org.springframework.transaction.annotation.EnableTransactionManagement; 19 | import org.springframework.web.servlet.ViewResolver; 20 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 21 | import org.springframework.web.servlet.view.InternalResourceViewResolver; 22 | 23 | import com.mchange.v2.c3p0.ComboPooledDataSource; 24 | 25 | //THIS IS JAVA CONFIG CLASS.WE ARE USING PURE JAVA CONFIG, NO XML 26 | @Configuration 27 | //with this annotation we enable Spring MVC 28 | @EnableWebMvc 29 | //so we can do hibernate transaction in the background(@Transactional) 30 | @EnableTransactionManagement 31 | //base package where to scan components for Controller class,Service class,Reporistory class... 32 | @ComponentScan(basePackages="com.brane.security.user.reg.form") 33 | //Classpath is a parameter in the Java Virtual Machine or the Java compiler 34 | //that specifies the location of user-defined classes and packages. 35 | //The parameter may be set either on the command-line, or through an environment variable. 36 | @PropertySource("classpath:persistence-mysql.properties") 37 | public class DemoAppConfig { 38 | 39 | //this variable env holds properties from the persistence-mysql.properties file 40 | //THIS IS GLOBAL ENVIRONMENT VARIABLE 41 | //Annotation @PropertySource READS DATA FROM THE PROPERTIES FILE AND 42 | //WE ARE GOING TO INJECT THAT DATA INTO VARIABLE env 43 | //ENVIRONMENT INTERFACE REPRESENTS THE ENVIRONMENT IN WHICH THE CURRENT APPLICATION IS LAUNCHED 44 | //we are going to inject Environment object so we can get properties from the files 45 | //persistence-mysql.properties and security-persistence-mysql.properties 46 | @Autowired 47 | private Environment env; 48 | 49 | //we are going to set logger just for diagnostics 50 | private Logger logger = Logger.getLogger(getClass().getName()); 51 | 52 | 53 | //define a bean for ViewResolver, because we are using JSP pages 54 | @Bean 55 | public ViewResolver viewResolver() { 56 | 57 | InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); 58 | 59 | //set prefix 60 | viewResolver.setPrefix("/WEB-INF/view/"); 61 | 62 | //set suffix 63 | viewResolver.setSuffix(".jsp"); 64 | 65 | return viewResolver; 66 | } 67 | 68 | 69 | //DataSource for database spring_security_custom_user_demo 70 | //we created a method which returns DataSource object 71 | //in this method we set all our props for our spring_security_custom_user_demo 72 | @Bean 73 | public DataSource securityDataSource() { 74 | 75 | // create connection pool, this class is from c3p0 package 76 | ComboPooledDataSource securityDataSource= new ComboPooledDataSource(); 77 | 78 | // set the jdbc driver 79 | try { 80 | securityDataSource.setDriverClass("com.mysql.jdbc.Driver"); 81 | } catch (PropertyVetoException exc) { 82 | throw new RuntimeException(exc); 83 | } 84 | 85 | //let's log url and user ... just to make sure we are reading the data 86 | logger.info("jdbc.url=" + env.getProperty("jdbc.url")); 87 | logger.info("jdbc.user=" + env.getProperty("jdbc.user")); 88 | 89 | 90 | // set database connection props 91 | securityDataSource.setJdbcUrl(env.getProperty("jdbc.url")); 92 | securityDataSource.setUser(env.getProperty("jdbc.user")); 93 | securityDataSource.setPassword(env.getProperty("jdbc.password")); 94 | 95 | // set connection pool props 96 | securityDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize")); 97 | securityDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize")); 98 | securityDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize")); 99 | securityDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime")); 100 | 101 | return securityDataSource; 102 | } 103 | 104 | 105 | 106 | //need a helper method, read environment property and convert to int 107 | private int getIntProperty(String propName) { 108 | 109 | String propVal = env.getProperty(propName); 110 | 111 | // now convert to int 112 | int intPropVal = Integer.parseInt(propVal); 113 | 114 | return intPropVal; 115 | } 116 | 117 | 118 | 119 | 120 | //this method contains all what we have in myDataSource() method 121 | @Bean 122 | public LocalSessionFactoryBean sessionFactory(){ 123 | 124 | //create session factory 125 | LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 126 | 127 | // set the properties 128 | //this sessionFactory object now contains all what we have in securityDataSource() method 129 | sessionFactory.setDataSource(securityDataSource()); 130 | 131 | //we are going to set package for all our entity classes which need to be scaned (com.luv2code.springdemo.entity) 132 | sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan")); 133 | 134 | //we are calling method for hibernate dialect and hibernate show sql 135 | sessionFactory.setHibernateProperties(getHibernateProperties()); 136 | 137 | return sessionFactory; 138 | } 139 | 140 | 141 | //this method will load 2 props and this method we calling in sessionFactory() method 142 | private Properties getHibernateProperties() { 143 | 144 | // set hibernate properties 145 | Properties props = new Properties(); 146 | 147 | //set property for hibernate.dialect and hibernate.show_sql 148 | props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); 149 | props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql")); 150 | 151 | return props; 152 | } 153 | 154 | 155 | 156 | @Bean 157 | @Autowired 158 | //WE ARE GOING TO DO HERE DEPENDENCY INJECTION, BECAUSE OF THAT WE CREATE ABOVE SPRING BEAN OBJECTS 159 | //WE WANT TO HAVE ALL WHAT WE CREATED HERE IN OUR METHOD transactionManager() 160 | //ALL WHAT WE CREATED FOR NOW WE HAVE IN METHOD sessionFactory() AND NOW WE INJECT THAT BEAN ID 161 | //IN OUR transactionManager() METHOD LIKE ARGUMENT 162 | 163 | //THIS METHOD WILL USE US FOR TRANSACTION,EVERY CHANGE ON DB IS TRANSACTION(CREATE,UPDATE,DELETE) 164 | //THIS METHOD WILL TAKE CARE OF @TRANSACTIONAL ANNOTATION, SO WE DON'T NEED TO 165 | public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) { 166 | 167 | // setup transaction manager based on session factory 168 | HibernateTransactionManager txManager = new HibernateTransactionManager(); 169 | txManager.setSessionFactory(sessionFactory); 170 | 171 | return txManager; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/config/DemoSecurityConfig.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/main/java/com/brane/security/user/reg/form/config/DemoSecurityConfig.java -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/config/MySpringMvcDispatcherServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.config; 2 | 3 | import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 4 | 5 | //THIS IS JAVA CONFIG CLASS.WE ARE USING PURE JAVA CONFIG, NO XML 6 | //This config class Servlet Initializer, allows us starting the APPLICATION CONTEXT (DemoAppConfig.class) 7 | //and also starting root application context which we don't have now. 8 | 9 | //OUR CONFIG CODE IN CLASS DemoAppConfig.class IS AUTOMATICALLY DETECTED AND IT IS USING FOR INITIALIZATION 10 | //SERVLET OBJECT WHICH IS STORED IN SPRING CONTAINER.WE ARE USING THIS METHOD getServletConfigClasses() FOR THAT. 11 | public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 12 | 13 | 14 | //WE DON'T HAVE ROOT CONFIG CLASS, ONLY SERVLET CONFIG CLASS 15 | @Override 16 | protected Class[] getRootConfigClasses() { 17 | // TODO Auto-generated method stub 18 | return null; 19 | } 20 | 21 | //BECAUSE OF THIS METHOD, WE AUTOMATICALLY DETECTED OUR CONFIG CLASS DemoAppConfig.class. APPLICATION CONTEXT 22 | //AND THIS METHOD IS USING FOR INITIALIZATION SERVLET OBJECT WHICH IS STORED IN SPRING CONTAINER. 23 | @Override 24 | protected Class[] getServletConfigClasses() { 25 | 26 | return new Class[] { DemoAppConfig.class }; 27 | } 28 | 29 | 30 | 31 | //SERVLET MAPPING-pattern "/" root of application 32 | @Override 33 | protected String[] getServletMappings() { 34 | 35 | return new String[] { "/" }; 36 | } 37 | 38 | } 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/config/SecurityWebApplicationInitializer.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.config; 2 | 3 | import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; 4 | 5 | //This class includes SPRING SECURITY FILTERS FOR WEB APP, THIS CLASS REGISTER SPRING SECURITY FILTERS. 6 | //SecurityWebApplicationInitializer class need to extend AbstractSecurityWebApplicationInitializer class, 7 | //if we want to enable filters. 8 | 9 | //THIS CLASS PROVIDES US SUPPORT FOR SECURITY INITIALIZATION, for INITIALIZATION SERVLET OBJECT. 10 | public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/controller/DemoController.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | 6 | @Controller 7 | public class DemoController { 8 | 9 | 10 | //Request mapping for root of our application to show home page when we are logged in. 11 | //THIS CAN SEE ONLY USERS WITH EMPLOYEE ROLE 12 | @GetMapping("/") 13 | public String showHome() { 14 | 15 | return "home"; 16 | } 17 | 18 | 19 | //Request mapping /leaders for MENAGER ROLE 20 | @GetMapping("/leaders") 21 | public String showLeaders() { 22 | 23 | return "leaders"; 24 | } 25 | 26 | 27 | //request mapping /systems for ADMIN ROLE 28 | @GetMapping("/systems") 29 | public String showSystems() { 30 | 31 | return "systems"; 32 | } 33 | 34 | } 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | 6 | @Controller 7 | public class LoginController { 8 | 9 | 10 | //our custom login page 11 | @GetMapping("/showMyLoginPage") 12 | public String showMyLoginPage() { 13 | 14 | return "fancy-login"; 15 | } 16 | 17 | 18 | //If some user which is not authorized trys to access some additional page such is /systems or 19 | // /leaders, he will get this access denied page. 20 | @GetMapping("/access-denied") 21 | public String showAccessDenied() { 22 | 23 | return "access-denied"; 24 | 25 | } 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/controller/RegistrationController.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.controller; 2 | 3 | import java.util.logging.Logger; 4 | 5 | import javax.validation.Valid; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.propertyeditors.StringTrimmerEditor; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.ui.Model; 11 | import org.springframework.validation.BindingResult; 12 | import org.springframework.web.bind.WebDataBinder; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.InitBinder; 15 | import org.springframework.web.bind.annotation.ModelAttribute; 16 | import org.springframework.web.bind.annotation.PostMapping; 17 | import org.springframework.web.bind.annotation.RequestMapping; 18 | 19 | import com.brane.security.user.reg.form.entity.User; 20 | import com.brane.security.user.reg.form.service.UserService; 21 | import com.brane.security.user.reg.form.user.CrmUser; 22 | 23 | //THIS IS CONTROLLER LAYER 24 | @Controller 25 | @RequestMapping("/register") 26 | public class RegistrationController { 27 | 28 | //we need to inject UserService object, so we can do dependency injection, 29 | //because we want to delegate calls from controller layer to service layer. 30 | @Autowired 31 | private UserService userService; 32 | 33 | //logger just for debugging 34 | private Logger logger = Logger.getLogger(getClass().getName()); 35 | 36 | 37 | 38 | //We have a problem here, for example, if we try to enter for the username Brane and 39 | //for the password all white spaces, this will work and we will process the form, which is wrong. 40 | //1.@InitBinder pre-process all web requests coming into our Controller. 41 | //2.This method removes all whitespaces, from the left and from the right side. 42 | //3.If string only have white space, trim it to null. 43 | @InitBinder 44 | public void initBinder(WebDataBinder dataBinder) { 45 | 46 | //This object removes whitespace from the left and from the right side. 47 | //true value means trim string to null if is all whitespace. 48 | StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true); 49 | 50 | //And we need to register this as a custom editor. 51 | //For every string class, apply StringTrimmerEditor. 52 | dataBinder.registerCustomEditor(String.class, stringTrimmerEditor); 53 | } 54 | 55 | 56 | //method for showing the form, with parameter Model 57 | @GetMapping("/showRegistrationForm") 58 | public String showMyLoginPage(Model theModel) { 59 | 60 | //add CrmUser object (object for form registration) to the model 61 | theModel.addAttribute("crmUser", new CrmUser()); 62 | 63 | return "registration-form"; 64 | } 65 | 66 | 67 | 68 | //controller method for processing the form for registration-form.jsp 69 | //We are going to validate the CrmUser object here with annotation @Valid 70 | //and we are using BindingResult object to store results of validation into this object. 71 | @PostMapping("/processRegistrationForm") 72 | public String processRegistrationForm( 73 | @Valid @ModelAttribute("crmUser") CrmUser theCrmUser, 74 | BindingResult theBindingResult, 75 | Model theModel) { 76 | 77 | //GET USERNAME WHICH WE ENTERED 78 | String userName = theCrmUser.getUserName(); 79 | 80 | //Just for debugging, we are going to print out this information. 81 | logger.info("Processing registration form for: " + userName); 82 | 83 | 84 | //form validation 85 | //We are using now BindingResult object to see if we had errors, if we had 86 | //return us to the registration-form again. 87 | //For validation rules we have only 1 rule and that is:username or password can't have null value. 88 | //If we had error (null value), we want to create a new CrmUser object 89 | //and to add that object to the model attribute. 90 | //We also want to create one more model attribute registrationError for showing the error 91 | //message "User name/password can not be empty." if username or password have null value. 92 | if (theBindingResult.hasErrors()){ 93 | 94 | return "registration-form"; 95 | 96 | } 97 | 98 | //check the database if user already exists with the same username 99 | User existing = userService.findByUserName(userName); 100 | 101 | //If user with this username exits in the database, return us to the registration-form again. 102 | //And again create a new CrmUser object and add that object to the model attribute. 103 | //We also want to create one more model attribute registrationError for showing the error 104 | //message "User name already exists." if username alredy exists in the database. 105 | if (existing != null){ 106 | 107 | //we want to have a new user object,if we delete this line we will have populated 108 | //old object(username,password,email,firstname,lastname...) 109 | theModel.addAttribute("crmUser", new CrmUser()); 110 | 111 | //Print out this error message from the model in our jsp page registration-form. 112 | //we will call this model attribute registrationError in our registration-form.jsp to show an error message. 113 | theModel.addAttribute("registrationError", "User name already exists."); 114 | 115 | logger.warning("User name already exists."); 116 | 117 | return "registration-form"; 118 | } 119 | 120 | 121 | //If everything is ok, save theCrmUser to the database. 122 | userService.save(theCrmUser); 123 | 124 | logger.info("Successfully created user: " + userName); 125 | 126 | //now when user is successfully created, return us to the registration-confirmation page 127 | return "registration-confirmation"; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/dao/RoleDao.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.dao; 2 | 3 | import com.brane.security.user.reg.form.entity.Role; 4 | 5 | //We created interface with 1 methods for role DAO (Data Access Object), to access data from the database. 6 | //We need a method to find role for some user. 7 | public interface RoleDao { 8 | 9 | public Role findRoleByName(String theRoleName); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/dao/RoleDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.dao; 2 | 3 | import org.hibernate.Session; 4 | import org.hibernate.SessionFactory; 5 | import org.hibernate.query.Query; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import com.brane.security.user.reg.form.entity.Role; 10 | 11 | //THIS IS DAO LAYER 12 | @Repository 13 | public class RoleDaoImpl implements RoleDao { 14 | 15 | //private field sessionFactory, so we can do dependency injection on this field 16 | //to get data from database.This sessionFactory object we created in xml config file. 17 | @Autowired 18 | private SessionFactory sessionFactory; 19 | 20 | 21 | 22 | //We are going to use this method to find a role for some user. 23 | @Override 24 | public Role findRoleByName(String theRoleName) { 25 | 26 | //get the current hibernate session 27 | Session currentSession = sessionFactory.getCurrentSession(); 28 | 29 | //now retrieve/read from database using name 30 | //WE ARE USING HERE HIBERNATE API with HQL 31 | //first we need to define parameter roleName 32 | Query theQuery = currentSession.createQuery("from Role where name=:roleName", Role.class); 33 | 34 | //and then we need to set the parameter to role name, theRoleName 35 | theQuery.setParameter("roleName", theRoleName); 36 | 37 | //at the beginning object User have null value 38 | Role theRole = null; 39 | 40 | try { 41 | 42 | //We have now single object user, because we are using method getSingleResult(). 43 | //It is designed to retrieve single result when there is truly a single result. 44 | theRole = theQuery.getSingleResult(); 45 | 46 | } catch (Exception e) { 47 | 48 | theRole = null; 49 | } 50 | 51 | return theRole; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.dao; 2 | 3 | import com.brane.security.user.reg.form.entity.User; 4 | 5 | //We created interface with 2 methods for user DAO (Data Access Object), to access data from the database. 6 | //We need method to find user by username and to save user to the database. 7 | public interface UserDao { 8 | 9 | User findByUserName(String userName); 10 | 11 | void save(User user); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/dao/UserDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.dao; 2 | 3 | import org.hibernate.Session; 4 | import org.hibernate.SessionFactory; 5 | import org.hibernate.query.Query; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import com.brane.security.user.reg.form.entity.User; 10 | 11 | //THIS IS DAO LAYER 12 | @Repository 13 | public class UserDaoImpl implements UserDao { 14 | 15 | 16 | //private field sessionFactory, so we can do dependency injection on this field 17 | //to get data from database.This sessionFactory object we created in xml config file. 18 | @Autowired 19 | private SessionFactory sessionFactory; 20 | 21 | 22 | 23 | //We are going to use this method to retreve single User object by username. 24 | @Override 25 | public User findByUserName(String theUserName) { 26 | 27 | //get the current hibernate session 28 | Session currentSession = sessionFactory.getCurrentSession(); 29 | 30 | //now retrieve/read from database using username 31 | //WE ARE USING HERE HIBERNATE API with HQL 32 | //first we need to define parameter uName 33 | Query theQuery = currentSession.createQuery("from User where userName=:uName", User.class); 34 | 35 | //and then we need to set the parameter to user name theUserName 36 | theQuery.setParameter("uName", theUserName); 37 | 38 | //at the beginning object User have null value 39 | User theUser = null; 40 | 41 | try { 42 | 43 | //We have now single object user, because we are using method getSingleResult(). 44 | //It is designed to retrieve single result when there is truly a single result. 45 | theUser = theQuery.getSingleResult(); 46 | 47 | } catch (Exception e) { 48 | 49 | theUser = null; 50 | } 51 | 52 | return theUser; 53 | } 54 | 55 | 56 | 57 | //We are going to use this method to save User object to the database. 58 | @Override 59 | public void save(User theUser) { 60 | 61 | //get current hibernate session 62 | Session currentSession = sessionFactory.getCurrentSession(); 63 | 64 | //create the user (save) 65 | currentSession.saveOrUpdate(theUser); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/entity/Role.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.entity; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.Table; 9 | 10 | //mapping this entity class to table employee from database 11 | @Entity 12 | @Table(name = "role") 13 | public class Role { 14 | 15 | @Id//primary key 16 | @GeneratedValue(strategy = GenerationType.IDENTITY)//auto increment 17 | @Column(name = "id")//mapping column from db 18 | private Long id; 19 | 20 | @Column(name = "name") 21 | private String name; 22 | 23 | 24 | //default constructor 25 | public Role() { 26 | } 27 | 28 | 29 | //constructor with this 1 field 30 | public Role(String name) { 31 | this.name = name; 32 | } 33 | 34 | 35 | //getter and setter methods 36 | public Long getId() { 37 | return id; 38 | } 39 | 40 | public void setId(Long id) { 41 | this.id = id; 42 | } 43 | 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | 53 | //adding to string method for debugging 54 | @Override 55 | public String toString() { 56 | return "Role{" + "id=" + id + ", name='" + name + '\'' + '}'; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.entity; 2 | 3 | import javax.persistence.*; 4 | import java.util.Collection; 5 | 6 | 7 | //mapping this entity class to table employee from database 8 | @Entity 9 | @Table(name = "user") 10 | public class User { 11 | 12 | @Id//primary key 13 | @GeneratedValue(strategy = GenerationType.IDENTITY)//auto increment 14 | @Column(name = "id")//mapping column from db 15 | private Long id; 16 | 17 | @Column(name = "username") 18 | private String userName; 19 | 20 | @Column(name = "password") 21 | private String password; 22 | 23 | @Column(name = "first_name") 24 | private String firstName; 25 | 26 | @Column(name = "last_name") 27 | private String lastName; 28 | 29 | @Column(name = "email") 30 | private String email; 31 | 32 | 33 | 34 | @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 35 | @JoinTable(name = "users_roles", //join this table 36 | joinColumns = @JoinColumn(name = "user_id"), //owning side 37 | inverseJoinColumns = @JoinColumn(name = "role_id"))//inverse side 38 | private Collection roles;//the collection he uses the most is ArrayList and LinkedHashMap 39 | 40 | 41 | //default constructor 42 | public User() { 43 | } 44 | 45 | 46 | //constructor with all fields 47 | public User(String userName, String password, String firstName, String lastName, String email) { 48 | this.userName = userName; 49 | this.password = password; 50 | this.firstName = firstName; 51 | this.lastName = lastName; 52 | this.email = email; 53 | } 54 | 55 | 56 | //constructor with all fields and one more filed for roles 57 | public User(String userName, String password, String firstName, String lastName, String email, 58 | Collection roles) { 59 | this.userName = userName; 60 | this.password = password; 61 | this.firstName = firstName; 62 | this.lastName = lastName; 63 | this.email = email; 64 | this.roles = roles; 65 | } 66 | 67 | 68 | //getter and setter methods for all fields 69 | public Long getId() { 70 | return id; 71 | } 72 | 73 | public void setId(Long id) { 74 | this.id = id; 75 | } 76 | 77 | public String getUserName() { 78 | return userName; 79 | } 80 | 81 | public void setUserName(String userName) { 82 | this.userName = userName; 83 | } 84 | 85 | public String getPassword() { 86 | return password; 87 | } 88 | 89 | public void setPassword(String password) { 90 | this.password = password; 91 | } 92 | 93 | public String getFirstName() { 94 | return firstName; 95 | } 96 | 97 | public void setFirstName(String firstName) { 98 | this.firstName = firstName; 99 | } 100 | 101 | public String getLastName() { 102 | return lastName; 103 | } 104 | 105 | public void setLastName(String lastName) { 106 | this.lastName = lastName; 107 | } 108 | 109 | public String getEmail() { 110 | return email; 111 | } 112 | 113 | public void setEmail(String email) { 114 | this.email = email; 115 | } 116 | 117 | public Collection getRoles() { 118 | return roles; 119 | } 120 | 121 | public void setRoles(Collection roles) { 122 | this.roles = roles; 123 | } 124 | 125 | 126 | //adding to string method for debugging 127 | @Override 128 | public String toString() { 129 | return "User{" + "id=" + id + ", userName='" + userName + '\'' + ", password='" + "*********" + '\'' 130 | + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' 131 | + ", roles=" + roles + '}'; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/service/UserService.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/main/java/com/brane/security/user/reg/form/service/UserService.java -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/service/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.service; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.stream.Collectors; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.core.GrantedAuthority; 9 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 12 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | import com.brane.security.user.reg.form.dao.RoleDao; 17 | import com.brane.security.user.reg.form.dao.UserDao; 18 | import com.brane.security.user.reg.form.entity.Role; 19 | import com.brane.security.user.reg.form.entity.User; 20 | import com.brane.security.user.reg.form.user.CrmUser; 21 | 22 | //THIS IS SERVICE LAYER 23 | @Service 24 | public class UserServiceImpl implements UserService { 25 | 26 | 27 | //need to inject userDao, so we can do dependency injection on this field 28 | //to delegate calls from SERVICE LAYER TO THE DAO LAYER 29 | @Autowired 30 | private UserDao userDao; 31 | 32 | //need to inject role dao 33 | @Autowired 34 | private RoleDao roleDao; 35 | 36 | //need to inject passwordEncoder from DemoSecurityConfig class 37 | @Autowired 38 | private BCryptPasswordEncoder passwordEncoder; 39 | 40 | 41 | 42 | //We are going to use this method to retreve single User object by username. 43 | @Override 44 | //annotation for "begin transaction" and "commit transaction" 45 | @Transactional 46 | public User findByUserName(String userName) { 47 | 48 | //Check the database if the user already exists 49 | //DELEGATE CALLS FROM SERVICE LAYER TO DAO LAYER 50 | return userDao.findByUserName(userName); 51 | } 52 | 53 | 54 | 55 | //We are going to use this method to save CrmUser object to the database. 56 | //This is CrmUser object from the registration form with validation rules. 57 | //User object is entity object for mapping database table user. 58 | @Override 59 | //annotation for "begin transaction" and "commit transaction" 60 | @Transactional 61 | public void save(CrmUser crmUser) { 62 | 63 | //We creating a new object User,because we are going to put in this object all information 64 | //which we entered in our registration form(CrmUser object),we will do this with setter methods. 65 | User user = new User(); 66 | 67 | //assign user details to the User object 68 | user.setUserName(crmUser.getUserName()); 69 | user.setPassword(passwordEncoder.encode(crmUser.getPassword())); 70 | user.setFirstName(crmUser.getFirstName()); 71 | user.setLastName(crmUser.getLastName()); 72 | user.setEmail(crmUser.getEmail()); 73 | 74 | //give user default role of "employee" 75 | //This setter method setRoles for parameter takes Collection roles. 76 | //The collection he uses the most is ArrayList and LinkedHashMap. 77 | //we can do this also: 78 | //1.List authorities = AuthorityUtils.createAuthorityList("ROLE_EMPLOYEE"); 79 | //2.List authorities = AuthorityUtils.createAuthorityList(); 80 | //authorities.add(new SimpleGrantedAuthority("ROLE_EMPLOYEE")); 81 | user.setRoles(Arrays.asList(roleDao.findRoleByName("ROLE_EMPLOYEE"))); 82 | 83 | //save user in the database 84 | userDao.save(user); 85 | } 86 | 87 | 88 | 89 | 90 | //This method is from interface UserDetailsService and gets back the UserDetails object 91 | //containing all the data of the user. 92 | //If no user is found with the given user name, a UsernameNotFoundException 93 | //is thrown in the method loadUserByUsername. 94 | @Override 95 | //annotation for "begin transaction" and "commit transaction" 96 | @Transactional 97 | public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { 98 | 99 | //delegate calls from service layer todao layer to find user by username 100 | User user = userDao.findByUserName(userName); 101 | 102 | //if user with that username don't exist, UsernameNotFoundException is thrown. 103 | if (user == null) { 104 | 105 | //UsernameNotFoundException is thrown. 106 | throw new UsernameNotFoundException("Invalid username or password."); 107 | } 108 | 109 | //If is not null and user with that username exist in the database, 110 | //use getter methods to take username, password and authorities for that user object. 111 | //Class User implements UserDetails interface, so we can do this. 112 | //Every user which we register only have one role by default ant it is EMPLOYEE role. 113 | //Here we want to add all roles for user, for example roles:EMPLOYEE and ADMIN. 114 | return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassword(), 115 | mapRolesToAuthorities(user.getRoles())); 116 | } 117 | 118 | 119 | 120 | //This methods returns Collection of roles and takes for parameter Collection roles. 121 | //1.List authorities = AuthorityUtils.createAuthorityList("ROLE_EMPLOYEE"); 122 | //2.List authorities = AuthorityUtils.createAuthorityList(); 123 | //authorities.add(new SimpleGrantedAuthority("ROLE_EMPLOYEE")); 124 | private Collection mapRolesToAuthorities(Collection roles) { 125 | 126 | return roles.stream() 127 | .map(role -> new SimpleGrantedAuthority(role.getName())) 128 | .collect(Collectors.toList()); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/user/CrmUser.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.user; 2 | 3 | import javax.validation.constraints.NotNull; 4 | import javax.validation.constraints.Size; 5 | 6 | import com.brane.security.user.reg.form.validation.FieldMatch; 7 | import com.brane.security.user.reg.form.validation.ValidEmail; 8 | 9 | //ADDING VALIDATION RULES 10 | 11 | //This is our custom annotation to make sure that the password and matching password fields match up. 12 | //We will now make an array of @FieldMatch annotations to check if fields matching. 13 | @FieldMatch.List({ 14 | @FieldMatch(first = "password", second = "matchingPassword", message = "The password fields must match") 15 | //@FieldMatch(first = "email", second = "confirmEmail", message = "The email fields must match") 16 | }) 17 | 18 | public class CrmUser { 19 | 20 | //Can't have null value and must have min 1 char 21 | @NotNull(message = "is required") 22 | @Size(min = 1, message = "is required") 23 | private String userName; 24 | 25 | //Can't have null value and must have min 1 char 26 | @NotNull(message = "is required") 27 | @Size(min = 1, message = "is required") 28 | private String password; 29 | 30 | //Can't have null value and must have min 1 char 31 | @NotNull(message = "is required") 32 | @Size(min = 1, message = "is required") 33 | private String matchingPassword; 34 | 35 | //Can't have null value and must have min 1 char 36 | @NotNull(message = "is required") 37 | @Size(min = 1, message = "is required") 38 | private String firstName; 39 | 40 | //Can't have null value and must have min 1 char 41 | @NotNull(message = "is required") 42 | @Size(min = 1, message = "is required") 43 | private String lastName; 44 | 45 | //This is our custom annotation for email validation using regulat expressions 46 | @ValidEmail 47 | @NotNull(message = "is required") 48 | @Size(min = 1, message = "is required") 49 | private String email; 50 | 51 | 52 | 53 | //default constructor 54 | public CrmUser() { 55 | 56 | } 57 | 58 | 59 | ////getters and setters 60 | public String getUserName() { 61 | return userName; 62 | } 63 | 64 | public void setUserName(String userName) { 65 | this.userName = userName; 66 | } 67 | 68 | public String getPassword() { 69 | return password; 70 | } 71 | 72 | public void setPassword(String password) { 73 | this.password = password; 74 | } 75 | 76 | public String getMatchingPassword() { 77 | return matchingPassword; 78 | } 79 | 80 | public void setMatchingPassword(String matchingPassword) { 81 | this.matchingPassword = matchingPassword; 82 | } 83 | 84 | public String getFirstName() { 85 | return firstName; 86 | } 87 | 88 | public void setFirstName(String firstName) { 89 | this.firstName = firstName; 90 | } 91 | 92 | public String getLastName() { 93 | return lastName; 94 | } 95 | 96 | public void setLastName(String lastName) { 97 | this.lastName = lastName; 98 | } 99 | 100 | public String getEmail() { 101 | return email; 102 | } 103 | 104 | public void setEmail(String email) { 105 | this.email = email; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/validation/EmailValidator.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.validation; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | import javax.validation.ConstraintValidator; 7 | import javax.validation.ConstraintValidatorContext; 8 | 9 | //CUSTOM EMAIL VALIDATOR 10 | 11 | //This is helper class EmailValidator, that contains business rules/validation logic. 12 | //This class implements ConstraintValidator interface. 13 | //ValidEmail is our annotation and String is type of data to validate against. 14 | public class EmailValidator implements ConstraintValidator { 15 | 16 | 17 | //Compiles the given regex and returns the instance of the Pattern. 18 | //Creates a matcher that matches the given input with the pattern. 19 | private Pattern pattern; 20 | 21 | //Matcher class is used to search through a text for multiple occurrences of a regular expression. 22 | private Matcher matcher; 23 | 24 | //Regular expression-marjanovicbrane93@gmail.com 25 | private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" 26 | + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; 27 | 28 | 29 | //Spring MVC will call this method at runtime to check is this data valid. 30 | //If is string valid it will return us true value, if is not it will return false value. 31 | //This method have 2 parameters, first is String, HTML form data entered by the user and 32 | //second is ConstraintValidatorContext, that is helper class for additional error messages. 33 | @Override 34 | public boolean isValid(final String email, final ConstraintValidatorContext context) { 35 | // compile method is used to create a pattern from the regular expression passed as parameter to method. 36 | pattern = Pattern.compile(EMAIL_PATTERN); 37 | 38 | if (email == null) { 39 | return false; 40 | } 41 | //The matcher() method is used to search for the pattern in a string. 42 | //It returns a Matcher object which contains information about the search that was performed. 43 | //Matcher method checks if pattern email match email which we entered in HTML form. 44 | matcher = pattern.matcher(email); 45 | 46 | //If matcher matches return true, if is not return false. 47 | return matcher.matches(); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/validation/FieldMatch.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.validation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Documented; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import javax.validation.Constraint; 10 | import javax.validation.Payload; 11 | 12 | 13 | //THIS IS CUSTOM ANNOTATION TOMAKE SURE THAT THE PASSWORD AND MATCHING PASSWORD FIELDS MATCH UP. 14 | 15 | //This is helper class FieldMatchValidator, that contains business rules/validation logic. 16 | @Constraint(validatedBy = FieldMatchValidator.class) 17 | 18 | //We can apply our annotation to: 19 | //1.ElementType.TYPE->class,interface or enum, for example 20 | //@YourAnnotation 21 | //public class SomeClass {..} 22 | 23 | //2.ElementType.ANNOTATION_TYPE->on other annotations, for example 24 | //@YourAnnotation 25 | //public @interface AnotherAnnotation {..} 26 | @Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) 27 | 28 | //Keep this annotation in the compiled java bytecode, so we can use it during RUNTIME. 29 | @Retention(RetentionPolicy.RUNTIME) 30 | 31 | //@Documented is a meta-annotation. You apply @Documented when defining an annotation, 32 | //to ensure that classes using your annotation show this in their generated JavaDoc. 33 | @Documented 34 | //first annotation @FieldMatch.Inside this annotation,we have 1 more annotation @List 35 | public @interface FieldMatch { 36 | 37 | //This annotation it's gonna have 3 parameter message, first and second 38 | 39 | //Third parameter for error message. 40 | String message() default ""; 41 | 42 | //we are not going to use groups 43 | Class[] groups() default {}; 44 | 45 | //we are not going to use payload 46 | Class[] payload() default {}; 47 | 48 | //first parameter for password 49 | String first(); 50 | 51 | //second parameter for matching password 52 | String second(); 53 | 54 | 55 | 56 | //Second annotation @List, to make array of FieldMatch annotations. 57 | //This annotation have 1 method called value() 58 | 59 | //We can also applay this annotation to class and to another annotations 60 | @Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) 61 | 62 | //Keep this annotation in the compiled java bytecode, so we can use it during RUNTIME. 63 | @Retention(RetentionPolicy.RUNTIME) 64 | 65 | //@Documented is a meta-annotation. You apply @Documented when defining an annotation, 66 | //to ensure that classes using your annotation show this in their generated JavaDoc. 67 | @Documented 68 | @interface List 69 | { 70 | //This annotation it's gonna have 1 parameter value 71 | FieldMatch[] value(); 72 | } 73 | } -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/validation/FieldMatchValidator.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.validation; 2 | 3 | import javax.validation.ConstraintValidator; 4 | import javax.validation.ConstraintValidatorContext; 5 | 6 | import org.springframework.beans.BeanWrapperImpl; 7 | 8 | 9 | //CUSTOM VALIDATOR FOR PASSWORD,TO MAKE SURE THAT THE PASSWORD AND MATCHING PASSWORD FIELDS MATCH UP. 10 | 11 | //This is helper class FieldMatchValidator, that contains business rules/validation logic. 12 | //This class implements ConstraintValidator interface. 13 | //FieldMatch is our annotation and Object is type of data to validate against. 14 | public class FieldMatchValidator implements ConstraintValidator { 15 | 16 | //fields 17 | private String firstFieldName; 18 | private String secondFieldName; 19 | private String message; 20 | 21 | 22 | //Now we have all 3 parameteres from the FieldMatch annotation 23 | //password,matching password and error message 24 | @Override 25 | public void initialize(final FieldMatch constraintAnnotation) { 26 | 27 | firstFieldName = constraintAnnotation.first(); 28 | secondFieldName = constraintAnnotation.second(); 29 | message = constraintAnnotation.message(); 30 | } 31 | 32 | 33 | 34 | //Spring MVC will call this method at runtime to check is this data valid. 35 | //If is string valid it will return us true value, if is not it will return false value. 36 | //This method have 2 parameters, first is Object value, 37 | //because we will apply this annotation @FieldMatch on the class CrmUser and 38 | //second is ConstraintValidatorContext, that is helper class for additional error messages. 39 | @Override 40 | public boolean isValid(final Object value, final ConstraintValidatorContext context) { 41 | 42 | boolean valid = true; 43 | 44 | try 45 | { 46 | //BeanWrapper wraps a bean to perform actions on that bean, like retrieving properties. 47 | final Object firstObj = new BeanWrapperImpl(value).getPropertyValue(firstFieldName);//password 48 | final Object secondObj = new BeanWrapperImpl(value).getPropertyValue(secondFieldName);//matching password 49 | 50 | //both equals null, or first not equal null and first equals second 51 | valid = firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj); 52 | } 53 | 54 | catch (final Exception ignore) 55 | { 56 | //we can ignore 57 | } 58 | 59 | //if is not true 60 | if (!valid){ 61 | //ConstraintValidatorContext, that is helper class for additional error messages. 62 | context.buildConstraintViolationWithTemplate(message)//error message 63 | .addPropertyNode(firstFieldName)//password 64 | .addConstraintViolation()//adds the new ConstraintViolation to be generated if the constraint validator marks the value as invalid. 65 | .disableDefaultConstraintViolation();//disables the default ConstraintViolation 66 | } 67 | 68 | return valid; 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /src/main/java/com/brane/security/user/reg/form/validation/ValidEmail.java: -------------------------------------------------------------------------------- 1 | package com.brane.security.user.reg.form.validation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import javax.validation.Constraint; 10 | import javax.validation.Payload; 11 | 12 | //CUSTOM ANNOTATION FOR EMAIL VALIDATION 13 | 14 | 15 | //This is helper class EmailValidator, that contains business rules/validation logic. 16 | @Constraint(validatedBy = EmailValidator.class) 17 | 18 | //We can apply our annotation to: 19 | //1.ElementType.TYPE->class,interface or enum, for example 20 | //@YourAnnotation 21 | //public class SomeClass {..} 22 | 23 | //2.ElementType.FIELD->fields 24 | //3.ElementType.ANNOTATION_TYPE->on other annotations, for example 25 | //@YourAnnotation 26 | //public @interface AnotherAnnotation {..} 27 | @Target({ ElementType.TYPE, ElementType.FIELD, ElementType.ANNOTATION_TYPE }) 28 | 29 | //Keep this annotation in the compiled java bytecode, so we can use it during RUNTIME. 30 | @Retention(RetentionPolicy.RUNTIME) 31 | 32 | //@Documented is a meta-annotation. You apply @Documented when defining an annotation, 33 | //to ensure that classes using your annotation show this in their generated JavaDoc. 34 | @Documented 35 | public @interface ValidEmail { 36 | 37 | //This annotation it's gonna have 1 parameter message 38 | String message() default "Invalid email"; 39 | 40 | //we are not going to use groups 41 | Class[] groups() default {}; 42 | 43 | //we are not going to use payload 44 | Class[] payload() default {}; 45 | } 46 | -------------------------------------------------------------------------------- /src/main/resources/persistence-mysql.properties: -------------------------------------------------------------------------------- 1 | 2 | # JDBC connection properties 3 | 4 | jdbc.driver=com.mysql.jdbc.Driver 5 | jdbc.url=jdbc:mysql://localhost:3306/spring_security_custom_user_demo?useSSL=false 6 | jdbc.user=springstudent 7 | jdbc.password=springstudent 8 | 9 | 10 | # Connection pool properties 11 | 12 | connection.pool.initialPoolSize=5 13 | connection.pool.minPoolSize=5 14 | connection.pool.maxPoolSize=20 15 | connection.pool.maxIdleTime=3000 16 | 17 | 18 | # Hibernate properties 19 | 20 | hibernate.dialect=org.hibernate.dialect.MySQLDialect 21 | hibernate.show_sql=true 22 | hibernate.packagesToScan=com.brane.security.user.reg.form.entity 23 | -------------------------------------------------------------------------------- /src/main/webapp/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/main/webapp/.DS_Store -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/main/webapp/WEB-INF/.DS_Store -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/view/access-denied.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Access Denied 5 | 6 | 7 | 8 | 9 |

Access Denied - You are not authorized to access this resource.

10 | 11 |
12 | 13 | Back to Home Page 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/view/fancy-login.jsp: -------------------------------------------------------------------------------- 1 | 3 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 4 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | Login Page 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
31 | 32 |
33 | 34 |
35 |
Sign In
36 |
37 | 38 |
39 | 40 | 41 | 42 | 43 | 44 |
45 |
46 |
47 | 48 | 49 | 50 | 51 | 52 |
53 | Invalid username and password. 54 |
55 | 56 |
57 | 58 | 59 | 60 | 61 | 62 |
63 | You have been logged out. 64 |
65 | 66 |
67 | 68 |
69 |
70 |
71 | 72 | 73 |
74 | 75 | 76 | 77 |
78 | 79 | 80 |
81 | 82 | 83 | 84 |
85 | 86 | 87 |
88 |
89 | 90 |
91 |
92 | 93 | 95 | 96 | 97 |
98 | 99 |
100 | 101 |
102 | 103 |
104 | 111 | Register New User 112 |
113 | 114 |
115 | 116 |
117 | 118 | 119 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/view/home.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 4 | 5 | 7 | <%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %> 8 | 9 | 10 | 12 | 13 | 14 | BM Company Home Page 15 | 16 | 17 | 18 |

BM Company Home Page

19 |
20 | 21 |

22 | Welcome to the BM company home page! 23 |

24 | 25 |
26 | 27 | 28 |

29 | User: 30 |

31 | Role(s): 32 |

33 | 34 | 38 | First name: ${user.firstName}, Last name: ${user.lastName}, Email: ${user.email} 39 |

40 | 41 | 42 | 44 | 45 | 46 |

47 | 48 | 50 | Leadership Meeting 51 | (Only for Manager) 52 |

53 | 54 |
55 | 56 | 57 | 58 | 59 | 60 |

61 | IT Systems Meeting 62 | (Only for Admin) 63 |

64 | 65 |
66 | 67 |
68 | 69 | 70 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/view/leaders.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LEADERS Home Page 5 | 6 | 7 | 8 | 9 |

LEADERS Home Page

10 | 11 |
12 | 13 |

14 | This page can only see users with MANAGER ROLE. 15 |
16 | Try to log in the system with some other role. 17 |

18 | 19 |
20 | 21 | Back to Home Page 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/view/registration-confirmation.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Registration Confirmation 5 | 6 | 7 | 8 | 9 |

User registered successfully!

10 | 11 |
12 | 13 | 14 | Login with new user 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/view/registration-form.jsp: -------------------------------------------------------------------------------- 1 | 3 | 4 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 5 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 6 | 7 | 8 | 9 | 10 | 11 | 12 | Register New User Form 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | 35 |
37 | 38 |
39 | 40 |
41 |
Register New User
42 |
43 | 44 |
45 | 46 | 47 | 50 | 51 | 52 |
53 |
54 |
55 | 56 | 60 | 61 | 62 |
63 | ${registrationError} 64 |
65 | 66 |
67 | 68 |
69 |
70 |
71 | 72 | 73 | 75 |
76 | 77 | 78 | 79 |
80 | 81 | 82 |
83 | 84 | 85 | 86 |
87 | 88 | 89 |
90 | 91 | 92 | 93 |
94 | 95 | 96 | 97 |
98 | 99 | 100 | 101 |
102 | 103 | 104 |
105 | 106 | 107 | 108 |
109 | 110 | 111 |
112 | 113 | 114 | 115 |
116 | 117 | 118 | 119 | 120 |
121 |
122 | 123 |
124 |
125 | 126 |
127 | 128 |
129 | 130 |
131 | 132 |
133 | 134 |
135 | 136 | 137 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/view/systems.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SYSTEMS Home Page 5 | 6 | 7 | 8 | 9 |

SYSTEMS Home Page

10 | 11 |
12 | 13 |

14 | This page can only see users with ADMIN ROLE. 15 |
16 | Try to log in the system with some other role. 17 |

18 | 19 |
20 | 21 | Back to Home Page 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/test/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/test/.DS_Store -------------------------------------------------------------------------------- /src/test/java/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/test/java/.DS_Store -------------------------------------------------------------------------------- /src/test/java/com/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/test/java/com/.DS_Store -------------------------------------------------------------------------------- /src/test/java/com/luv2code/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/test/java/com/luv2code/.DS_Store -------------------------------------------------------------------------------- /src/test/java/com/luv2code/springsecurity/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/src/test/java/com/luv2code/springsecurity/.DS_Store -------------------------------------------------------------------------------- /src/test/java/com/luv2code/springsecurity/demo/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.luv2code.springsecurity.demo; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /target/classes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/.DS_Store -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/config/CustomAuthenticationSuccessHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/config/CustomAuthenticationSuccessHandler.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/config/DemoAppConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/config/DemoAppConfig.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/config/DemoSecurityConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/config/DemoSecurityConfig.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/config/MySpringMvcDispatcherServletInitializer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/config/MySpringMvcDispatcherServletInitializer.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/config/SecurityWebApplicationInitializer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/config/SecurityWebApplicationInitializer.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/controller/DemoController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/controller/DemoController.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/controller/LoginController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/controller/LoginController.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/controller/RegistrationController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/controller/RegistrationController.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/dao/RoleDao.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/dao/RoleDao.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/dao/RoleDaoImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/dao/RoleDaoImpl.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/dao/UserDao.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/dao/UserDao.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/dao/UserDaoImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/dao/UserDaoImpl.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/entity/Role.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/entity/Role.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/entity/User.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/entity/User.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/service/UserService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/service/UserService.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/service/UserServiceImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/service/UserServiceImpl.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/user/CrmUser.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/user/CrmUser.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/validation/EmailValidator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/validation/EmailValidator.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/validation/FieldMatch$List.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/validation/FieldMatch$List.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/validation/FieldMatch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/validation/FieldMatch.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/validation/FieldMatchValidator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/validation/FieldMatchValidator.class -------------------------------------------------------------------------------- /target/classes/com/brane/security/user/reg/form/validation/ValidEmail.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/classes/com/brane/security/user/reg/form/validation/ValidEmail.class -------------------------------------------------------------------------------- /target/classes/persistence-mysql.properties: -------------------------------------------------------------------------------- 1 | 2 | # JDBC connection properties 3 | 4 | jdbc.driver=com.mysql.jdbc.Driver 5 | jdbc.url=jdbc:mysql://localhost:3306/spring_security_custom_user_demo?useSSL=false 6 | jdbc.user=springstudent 7 | jdbc.password=springstudent 8 | 9 | 10 | # Connection pool properties 11 | 12 | connection.pool.initialPoolSize=5 13 | connection.pool.minPoolSize=5 14 | connection.pool.maxPoolSize=20 15 | connection.pool.maxIdleTime=3000 16 | 17 | 18 | # Hibernate properties 19 | 20 | hibernate.dialect=org.hibernate.dialect.MySQLDialect 21 | hibernate.show_sql=true 22 | hibernate.packagesToScan=com.brane.security.user.reg.form.entity 23 | -------------------------------------------------------------------------------- /target/m2e-wtp/web-resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Built-By: BRANE 3 | Build-Jdk: 11 4 | Created-By: Maven Integration for Eclipse 5 | 6 | -------------------------------------------------------------------------------- /target/m2e-wtp/web-resources/META-INF/maven/com.luv2code/spring-security-custom-user-registration-demo/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Thu Sep 16 09:43:53 CEST 2021 3 | m2e.projectLocation=C\:\\Users\\BRANE\\eclipse-workspace\\security-user-reg-form-custom-user-details-jdbc-bcrypt-auth 4 | m2e.projectName=security-user-reg-form-custom-user-details-jdbc-bcrypt-auth 5 | groupId=com.luv2code 6 | artifactId=spring-security-custom-user-registration-demo 7 | version=1.0.0 8 | -------------------------------------------------------------------------------- /target/m2e-wtp/web-resources/META-INF/maven/com.luv2code/spring-security-custom-user-registration-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.luv2code 6 | spring-security-custom-user-registration-demo 7 | 1.0.0 8 | war 9 | 10 | spring-security-custom-user-registration-demo 11 | 12 | 13 | 5.0.2.RELEASE 14 | 5.0.0.RELEASE 15 | 16 | 5.5.0.Final 17 | 8.0.20 18 | 0.9.5.2 19 | 20 | 1.11 21 | 1.11 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.springframework 29 | spring-webmvc 30 | ${springframework.version} 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.springframework.security 38 | spring-security-web 39 | ${springsecurity.version} 40 | 41 | 42 | 43 | org.springframework.security 44 | spring-security-config 45 | ${springsecurity.version} 46 | 47 | 48 | 49 | 50 | org.springframework.security 51 | spring-security-taglibs 52 | ${springsecurity.version} 53 | 54 | 55 | 56 | 57 | javax.servlet 58 | javax.servlet-api 59 | 3.1.0 60 | 61 | 62 | 63 | javax.servlet.jsp 64 | javax.servlet.jsp-api 65 | 2.3.1 66 | 67 | 68 | 69 | 70 | taglibs 71 | standard 72 | 1.1.2 73 | 74 | 75 | 76 | javax.servlet 77 | jstl 78 | 1.2 79 | 80 | 81 | 82 | 83 | org.springframework 84 | spring-tx 85 | ${springframework.version} 86 | 87 | 88 | 89 | 90 | org.springframework 91 | spring-orm 92 | ${springframework.version} 93 | 94 | 95 | 96 | 97 | org.hibernate 98 | hibernate-core 99 | ${hibernate.version} 100 | 101 | 102 | 103 | 104 | 105 | mysql 106 | mysql-connector-java 107 | ${mysql.connector.version} 108 | 109 | 110 | 111 | 112 | com.mchange 113 | c3p0 114 | ${c3po.version} 115 | 116 | 117 | 118 | 119 | org.hibernate 120 | hibernate-validator 121 | 6.1.7.Final 122 | 123 | 124 | 125 | junit 126 | junit 127 | 3.8.1 128 | test 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | spring-security-custom-user-registration-demo 137 | 138 | 139 | 140 | 141 | org.apache.maven.plugins 142 | maven-war-plugin 143 | 3.2.0 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /target/test-classes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/test-classes/.DS_Store -------------------------------------------------------------------------------- /target/test-classes/com/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/test-classes/com/.DS_Store -------------------------------------------------------------------------------- /target/test-classes/com/luv2code/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/test-classes/com/luv2code/.DS_Store -------------------------------------------------------------------------------- /target/test-classes/com/luv2code/springsecurity/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/test-classes/com/luv2code/springsecurity/.DS_Store -------------------------------------------------------------------------------- /target/test-classes/com/luv2code/springsecurity/demo/AppTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marjanovicbrane/spring-security-user-reg-form-custom-user-details-jdbc-bcrypt-auth/0368817041eea23c2c16a81015a9904e67c16042/target/test-classes/com/luv2code/springsecurity/demo/AppTest.class --------------------------------------------------------------------------------