{"id":206,"date":"2020-01-27T20:34:51","date_gmt":"2020-01-27T20:34:51","guid":{"rendered":"https:\/\/www.kindsonthegenius.com\/spring-boot\/?p=206"},"modified":"2020-07-26T08:15:00","modified_gmt":"2020-07-26T08:15:00","slug":"complete-application-with-spring-boot-part-3-add-spring-security","status":"publish","type":"post","link":"https:\/\/kindsonthegenius.com\/spring-boot\/complete-application-with-spring-boot-part-3-add-spring-security\/","title":{"rendered":"Complete Application with Spring Boot &#8211; Part 3 (Add Spring Security)"},"content":{"rendered":"<p>In this part, we would add Spring Security to our application. You can find Part 1 and 2 below.<\/p>\n<p><a href=\"https:\/\/kindsonthegenius.com\/spring-boot\/build-a-complete-spring-boot-application-from-the-scratch-step-by-step\/\">Part 1 &#8211; Getting Started and Setting up the Pages<\/a><\/p>\n<p><a href=\"https:\/\/kindsonthegenius.com\/spring-boot\/complete-application-part-2-showing-image-thumbnails\/\">Part 2 &#8211; Showing Images and Thumbnails<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>With Spring security we would allows users to login to the application using their username and password. As usual, we would take it step by step. I also recommend you follow the video lessons as well.<\/p>\n<p>To add Spring Security, we would follow these 7 steps:<\/p>\n<ol>\n<li><a href=\"#t1\">Add the Dependencies<\/a><\/li>\n<li><a href=\"#t2\">Write the Methods for \/login and \/logout<\/a><\/li>\n<li><a href=\"#t3\">Add Test Records<\/a><\/li>\n<li><a href=\"#t4\">Set up User Model and Repository<\/a><\/li>\n<li><a href=\"#t5\">Implement UserDetailsService<\/a><\/li>\n<li><a href=\"#t6\">Implement UserDetails Interface<\/a><\/li>\n<li><a href=\"#t7\">Extend the WebSecurityConfigurerAdapter<\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t1\">Step 1 &#8211; Add the dependencies<\/strong><\/h5>\n<p>You need to add the following two dependencies to enable spring security.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007700;\">&lt;dependency&gt;<\/span>\r\n    <span style=\"color: #007700;\">&lt;groupId&gt;<\/span>org.thymeleaf.extras<span style=\"color: #007700;\">&lt;\/groupId&gt;<\/span>\r\n     <span style=\"color: #007700;\">&lt;artifactId&gt;<\/span>thymeleaf-extras-springsecurity5<span style=\"color: #007700;\">&lt;\/artifactId&gt;<\/span>\r\n<span style=\"color: #007700;\">&lt;\/dependency&gt;<\/span>\r\n<span style=\"color: #007700;\">&lt;dependency&gt;<\/span>\r\n    <span style=\"color: #007700;\">&lt;groupId&gt;<\/span>org.springframework.boot<span style=\"color: #007700;\">&lt;\/groupId&gt;<\/span>\r\n    <span style=\"color: #007700;\">&lt;artifactId&gt;<\/span>spring-boot-starter-security<span style=\"color: #007700;\">&lt;\/artifactId&gt;<\/span>\r\n<span style=\"color: #007700;\">&lt;\/dependency&gt;<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t2\">Step 2 &#8211; Write the method for \/login and \/logout<\/strong><\/h5>\n<p>In the ApplicationController file, write a method to return the login page. The url mapping would be &#8220;\/login&#8221;.<\/p>\n<p>Do the same for \/logout<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t3\">Step 3 &#8211; Add test records<\/strong><\/h5>\n<p>For now, we would just manually add some records to MySQL database. So open MySQL command prompt and add two some records to the user table.<\/p>\n<p>(See the video for the procedure)<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t4\">Step 4 &#8211; Setup the User Model and Repository<\/strong><\/h5>\n<p>Check the the user model has the fields: id, username and password.<\/p>\n<p>In the repository write a method to find user by username<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t5\">Step 5 &#8211; Implement the UserDetailsService<\/strong><\/h5>\n<p>Create a class in the Services package and call it MyUserDetailsService. This class should implement UserDetailsService.<\/p>\n<p>Add the @Service annotation to this class.<\/p>\n<p>In the loadUserByUsername method, create a new user using the repository&#8217;s findByUsername method.<\/p>\n<p>Then instantiate an return a new UserPrincipal object using the user as an argument (watch the video)<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t6\">Step 6 &#8211; Implement the UserDetails Interfaces<\/strong><\/h5>\n<p>In the models package, create a class UserPrincipal that implements UserDetails interface.<\/p>\n<p>In this class create a private member variable of type User. Then generate the constructor.<\/p>\n<p>The modify the getUsername and getPassword to return user.getUsername and user.getPassword<\/p>\n<p>Also set the methods in this class to return true.<\/p>\n<p>Modify the getAuthorities method (see the video)<\/p>\n<p>&nbsp;<\/p>\n<h5><strong id=\"t7\">Step 7: Extend the WebSecurityConfiurerAdapter<\/strong><\/h5>\n<p>Create the AppSecurityConfig file to extend the WebSecurityConfigurerAdapter class.<\/p>\n<p>Add the @Configuration and @EnableWebSecurity to this class<\/p>\n<p>Then override the configure method.<\/p>\n<p>Create the PasswordEncoder bean and other methods.<\/p>\n<p>Autowire the UserDetailsService<\/p>\n<p>Then create a bean to return a DaoAuthenticationProvider<\/p>\n<p>The final content of this file is given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Configuration<\/span>\r\n<span style=\"color: #555555; font-weight: bold;\">@EnableWebSecurity<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">ApplicationSecurityConfig<\/span> \r\n<span style=\"color: #008800; font-weight: bold;\">extends<\/span> WebSecurityConfigurerAdapter  <span style=\"color: #333333;\">{<\/span>\r\n\t\r\n\t<span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\r\n\t<span style=\"color: #008800; font-weight: bold;\">protected<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">configure<\/span><span style=\"color: #333333;\">(<\/span>HttpSecurity http<span style=\"color: #333333;\">)<\/span> \r\n\t\t\t<span style=\"color: #008800; font-weight: bold;\">throws<\/span> Exception <span style=\"color: #333333;\">{<\/span>\r\n\t\thttp\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">csrf<\/span><span style=\"color: #333333;\">().<\/span><span style=\"color: #0000cc;\">disable<\/span><span style=\"color: #333333;\">()<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">authorizeRequests<\/span><span style=\"color: #333333;\">()<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">antMatchers<\/span><span style=\"color: #333333;\">(<\/span>\r\n\t\t\t\t<span style=\"background-color: #fff0f0;\">\"\/login\"<\/span><span style=\"color: #333333;\">,<\/span> \r\n\t\t\t\t<span style=\"background-color: #fff0f0;\">\"\/resources\/**\"<\/span><span style=\"color: #333333;\">,<\/span> \r\n\t\t\t\t<span style=\"background-color: #fff0f0;\">\"\/css\/**\"<\/span><span style=\"color: #333333;\">,<\/span> \r\n\t\t\t\t<span style=\"background-color: #fff0f0;\">\"\/fonts\/**\"<\/span><span style=\"color: #333333;\">,<\/span> \r\n\t\t\t\t<span style=\"background-color: #fff0f0;\">\"\/img\/**\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">permitAll<\/span><span style=\"color: #333333;\">()<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">anyRequest<\/span><span style=\"color: #333333;\">().<\/span><span style=\"color: #0000cc;\">authenticated<\/span><span style=\"color: #333333;\">()<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">and<\/span><span style=\"color: #333333;\">()<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">formLogin<\/span><span style=\"color: #333333;\">()<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">loginPage<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"\/login\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">permitAll<\/span><span style=\"color: #333333;\">()<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">and<\/span><span style=\"color: #333333;\">()<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">logout<\/span><span style=\"color: #333333;\">().<\/span><span style=\"color: #0000cc;\">invalidateHttpSession<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">true<\/span><span style=\"color: #333333;\">)<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">clearAuthentication<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">true<\/span><span style=\"color: #333333;\">)<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">logoutRequestMatcher<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> AntPathRequestMatcher<span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"\/logout\"<\/span><span style=\"color: #333333;\">))<\/span>\r\n\t\t<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">logoutSuccessUrl<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"\/login\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">permitAll<\/span><span style=\"color: #333333;\">();<\/span>\r\n\t<span style=\"color: #333333;\">}<\/span>\r\n\t\r\n\t<span style=\"color: #555555; font-weight: bold;\">@Bean<\/span>\r\n\t<span style=\"color: #008800; font-weight: bold;\">public<\/span> PasswordEncoder <span style=\"color: #0066bb; font-weight: bold;\">passwordEncoder<\/span><span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">{<\/span>\r\n\t\t<span style=\"color: #008800; font-weight: bold;\">return<\/span> NoOpPasswordEncoder<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getInstance<\/span><span style=\"color: #333333;\">();<\/span>\r\n\t<span style=\"color: #333333;\">}<\/span>\t\r\n\t\r\n\t<span style=\"color: #555555; font-weight: bold;\">@Autowired<\/span>\r\n\t<span style=\"color: #008800; font-weight: bold;\">private<\/span> UserDetailsService userDetailsService<span style=\"color: #333333;\">;<\/span>\r\n\t\r\n\t<span style=\"color: #555555; font-weight: bold;\">@Bean<\/span>\r\n\t<span style=\"color: #008800; font-weight: bold;\">public<\/span> AuthenticationProvider <span style=\"color: #0066bb; font-weight: bold;\">authenticationProvider<\/span><span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">{<\/span>\r\n\t\tDaoAuthenticationProvider provider <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">new<\/span> DaoAuthenticationProvider<span style=\"color: #333333;\">();<\/span>\t\t\r\n\t\tprovider<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">setUserDetailsService<\/span><span style=\"color: #333333;\">(<\/span>userDetailsService<span style=\"color: #333333;\">);<\/span>\t\r\n\t\tprovider<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">setPasswordEncoder<\/span><span style=\"color: #333333;\">(<\/span>passwordEncoder<span style=\"color: #333333;\">());<\/span>\r\n\t\t<span style=\"color: #008800; font-weight: bold;\">return<\/span> provider<span style=\"color: #333333;\">;<\/span>\r\n\t<span style=\"color: #333333;\">}<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>I recommend you watch the video for clarification. See video below<\/p>\n<p><iframe loading=\"lazy\" width=\"100%\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/nEDlG2J3XUA\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>In this part, we would add Spring Security to our application. You can find Part 1 and 2 below. Part 1 &#8211; Getting Started and &hellip; <!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":209,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2],"tags":[19,20,21],"class_list":["post-206","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-spring-boot-tutorials","tag-spring-security","tag-userdetails","tag-websecurityconfigureradapter"],"_links":{"self":[{"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/posts\/206","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/comments?post=206"}],"version-history":[{"count":5,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/posts\/206\/revisions"}],"predecessor-version":[{"id":245,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/posts\/206\/revisions\/245"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/media\/209"}],"wp:attachment":[{"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/media?parent=206"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/categories?post=206"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/tags?post=206"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}