View Javadoc
1   package org.imageconverter.config.security;
2   
3   import org.springframework.beans.factory.annotation.Value;
4   import org.springframework.context.annotation.Bean;
5   import org.springframework.context.annotation.Configuration;
6   import org.springframework.security.core.userdetails.User;
7   import org.springframework.security.core.userdetails.UserDetailsService;
8   import org.springframework.security.crypto.factory.PasswordEncoderFactories;
9   import org.springframework.security.provisioning.InMemoryUserDetailsManager;
10  import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
11  import org.springframework.security.web.csrf.CsrfTokenRepository;
12  import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
13  import org.springframework.security.web.firewall.HttpFirewall;
14  import org.springframework.security.web.firewall.StrictHttpFirewall;
15  import org.springframework.stereotype.Controller;
16  import org.springframework.web.bind.annotation.GetMapping;
17  import org.springframework.web.bind.annotation.ResponseBody;
18  
19  // https://freecontent.manning.com/five-awkward-things-about-spring-security-that-actually-make-sense/
20  
21  /**
22   * Project security's config.
23   * 
24   * @author Fernando Romulo da Silva
25   */
26  @Configuration
27  public class SecurityConfig {
28  
29      private final String applicationUser;
30  
31      private final String applicationPassword;
32  
33      /**
34       * Default constructor.
35       * 
36       * @param applicationUser     Default application user login
37       * @param applicationPassword Default application user password
38       */
39      SecurityConfig( //
40  		    @Value("${application.user_login}") //
41  		    final String applicationUser, //
42  		    //
43  		    @Value("${application.user_password}") //
44  		    final String applicationPassword) {
45  	super();
46  	this.applicationUser = applicationUser;
47  	this.applicationPassword = applicationPassword;
48      }
49  
50      /**
51       * Create a configured filter.
52       * 
53       * @return a {@link HttpFirewall} configured
54       */
55      @Bean
56      HttpFirewall allowUrlEncodedSlashHttpFirewall() {
57  	final var firewall = new StrictHttpFirewall();
58  	firewall.setAllowUrlEncodedSlash(true);
59  	firewall.setAllowSemicolon(true);
60  	return firewall;
61      }
62  
63      // https://www.baeldung.com/csrf-thymeleaf-with-spring-security
64      /**
65       * Create a session csrf token repository.
66       * 
67       * @return a {@link CsrfTokenRepository} configured
68       */
69      @Bean
70      CsrfTokenRepository httpSessionCsrfTokenRepository() {
71  	// repo.setParameterName("_csrf");
72  	// repo.setHeaderName("X-CSRF-TOKEN");
73  	return new HttpSessionCsrfTokenRepository();
74  
75      }
76  
77      /**
78       * Create a cookie csrf token repository.
79       * 
80       * @return a {@link CsrfTokenRepository} configured
81       */
82      @Bean
83      CsrfTokenRepository cookieCsrfTokenRepository() {
84          // X-XSRF-TOKEN
85  	// repo.setHeaderName("X-XSRF-TOKEN");
86          return CookieCsrfTokenRepository.withHttpOnlyFalse();	
87      }
88  
89      /**
90       * Create a user recorer.
91       * 
92       * @return a {@link UserDetailsService} configured
93       */
94      @Bean
95      UserDetailsService userDetailsService() {
96  
97  	final var encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
98  
99  	final var manager = new InMemoryUserDetailsManager();
100 
101 	final var adminUser = User//
102 			.withUsername(applicationUser) //
103 			.password(encoder.encode(applicationPassword)) //
104 			.roles("USER", "ADMIN") //
105 			.build();
106 
107 	manager.createUser(adminUser);
108 
109 	return manager;
110     }
111 
112 //    @Bean
113 //    public PasswordEncoder encoder(){
114 //        return new BCryptPasswordEncoder();
115 //    }
116 
117     /**
118      * Fix the Favicon problem.
119      * 
120      * @author Fernando Romulo da Silva
121      */
122     @Controller
123     public static class FaviconController {
124 
125 	@GetMapping("favicon.ico")
126 	@ResponseBody
127 	void returnNoFavicon() {
128 	    // just to fix favicon.ico problem
129 	}
130     }
131 }