- Java 7+
- Maven 3.8.6
- MariaDB 10.3.4
-
Create resources/env.properties file. Required properties:
DB_URL=jdbc:mysql://ip:3306/dbName?&useSSL=false&serverTimezone=UTC
DB_USER=mariadbuser
DB_PASSWORD=mariadbuserpassword
-
Check application.properties file for other properties.
- Create entities in
com.example.demo.entities
package using JPA syntax- They are auto discovered and there is no persistence.xml thanks to spring boot
- Data projections through DTO is almost mandatory before jackson serialization because Jackson uses every getter, so it will serialize all the fields of the entity, even ones marked as lazy.
- Create DTOs in
com.example.demo.data.models.projections
package - Use ModelMapper to map entities to DTOs in controllers (a bean is already defined in the configuration)
- Repositories extends JpaRepository
- Create repositories in
com.example.demo.repository
package
- Services are used to implement business logic
- Services should extend BaseCrudService that provides basic CRUD operations
- Create services in
com.example.demo.services
package
- They are auto discovered and there is no web.xml thanks to spring boot
- Controllers should extend BaseSecuredController that provides basic CRUD operations
- Create controllers in
com.example.demo.controller
package
- If any exceptions are thrown, they are handled by class GlobalExceptionHandler
- Special care was needed to handle exception thrown by Spring Security :
- implemented interface
AuthenticationEntryPoint
in DelegatedAuthenticationEntryPoint to delegate authentication exception handling to GlobalExceptionHandler - implemented interface
AccessDeniedHandler
in CustomAccessDeniedHandler to delegate authorization exception handling to GlobalExceptionHandler
- implemented interface
- CORS is enabled with CorsConfigurationSource bean in MyWebSecurityConfig class
- CORS is enabled for all origins, methods, headers and paths
- CORS registers authorized headers
- CORS personalized conf is notified through following code in method filterChain
http.cors().and...
- SpringDoc is used to document the API
- Check route in
application.properties
filespringdoc.api-docs.path=/docs
springdoc.swagger-ui.path=/docs/swagger.html
- Use Operation annotation on controllers to add a custom description or document them as secured :
@Operation(summary="Get user by id",security = @SecurityRequirement(name = "basicAuth"))
security="basicAuth"
is used to document the security scheme, defined in application class as follows :@SecurityScheme( name = "basicAuth", type = SecuritySchemeType.HTTP, scheme = "bearer" )
- On login, Security process starts manually :
AuthenticationManager
is the entry point of the authentication process.AuthenticationProvider
is the interface that is responsible for authenticating the user.DaoAuthenticationProvider
is the implementation of theAuthenticationProvider
interface that is responsible for authenticating a user by using aUserDetailsService
implementation to retrieve the user details.- Since a
PasswordEncoder
bean is registered, Spring Security will use this one. - Same principle for
UserDetailsService
bean, spring will use the one exposed : CustomUserDetailsService.
- On
@PreAuthorized
requests :- JwtTokenVerifierFilter is called
- It verifies the token
- It creates an authentication object with the user email parsed in the token
- It sets the authentication in the SecurityContext
P.S. : JwtTokenVerifierFilter is not called on login request because it is not annotated with @PreAuthorized
annotation.
P.S. : UsernamePasswordAuthenticationFilter is never called but the JwtTokenVerifierFilter is registered before it in the filter chain because it's a good place.