In our
previous
tutorial, we learned how to configure a custom login page with pre-defined
hard-cored user credentials in place of the built-in login page of Spring
Security. In this tutorial, we'll learn how to secure a Spring MVC application
using Jdbc Authentication along with a custom login page. So in this case,
user credentials would not be configured in any configuration file, but rather
those would be stored in the database table.
In the basic Spring Security tutorial, we configured user credentials and
roles in the ApplicationSecutiryConfiguration class. But now we are
going to put user credentials and roles in the database. So we need to tell
Spring Security to read that information from the database and on the other hand, Spring Security also can read that information from the database.
So, we must follow Spring Security's predefined table schema to fulfill
our requirement. Now we need to create the appropriate tables in the database,
write some JDBC code to read information from the database, and make some configuration, and
then Spring Security will do the rest of the work for us.
Create Maven project
So, first, we will create a simple Maven project. To create a project in
Eclipse, click on the File menu, then choose
New→Maven Project.
Then choose the project location and click Next.
Now enter Group Id and Artifact Id and select packaging type
as war (Web Archive) as shown:
Click Finish to create the project.
POM.XML
Update pom.xml with required dependencies:
Spring Framework version is 5.3.21 and Spring Security version is
5.6.6 for this application. We have added Spring MVC,
Servlet, JSP, Security, and MySQL connector for JAVA and DBCP2 connection pool-related dependencies in pom.xml. We are using war as the packaging type, which is why we use the maven-war-plugin to build the
application.
Database Tables
As we've discussed earlier, we need to create some database tables. Below is
the SQL script snippet to set up tables:
PasswordEncoder
In the previous section, we've used the phrase {noop} in the
password column value in the users table - in Spring
5.0 and onward if we want to store passwords in the database table, we've to
store them in encoded format. So the format for a password is -
{id}encodedPassword - here
id is the identifier for the PasswordEncoder.
One of the PasswordEncoder is NoOpPasswordEncoder
which is used when we want to store plain text as our password and its
id value is noop.
Here are some PasswordEncoders with their id values:
- id value of NoOpPasswordEncoder is noop
- id value of BCryptPasswordEncoder is bcrypt
- id value of SCryptPasswordEncoder is scrypt
- id value of Pbkdf2PasswordEncoder is pbkdf2
- id value of StandardPasswordEncoder is sha256
As we're going to store passwords as plain text, that is why we've used
{noop} with our password string. So, when Spring gets password
value with {noop} phrase, it'll understand that the password is in
plain text.
Connect to Database
In the app-db.properties file under the resource directory, we've
configured Jdbc connection properties to connect MySQL
database, secure_spring_mvc_db_auth:
Application Configuration
From the previous tutorial, we've copied the ApplicationConfiguration
class in the config package and this class will act as Spring configuration.
Here we're going to define our data source:
Here, we've mapped our app-db.properties file
using @PropertySource annotation. So this property file
will be automatically copied to classpath during Maven build. We've
autowired the Environment class, a Spring Helper class - with it, we
can access the property values in the application.
We've also defined a bean using @Bean annotation to configure our
datasource using the property values.
This class also contains the configuration of ViewResolver using Java
configuration, which is required for Spring Web MVC applications. We are
using JSP as our view technology.
Initialize Dispatcher Servlet
The dispatcher servlet is responsible for forwarding/dispatching the request to the appropriate controller method. To initialize our Spring WebMVC application
in the Servlet container environment using JAVA configuration, we create the ApplicationDispatherServletInitializer class in the config package
which will extend the AbstractAnnotationConfigDispatcherServletInitializer class.
Initialize Application Security
Now, we need to create a security initializer class that will extend
AbstractSecurityWebApplicationInitializer. Here is our
ApplicationSecurityInitializer class which will reside config package:
AbstractSecurityWebApplicationInitializer helps us to register the
DelegatingFilterProxy to use the Spring Security Filter.
Configure Application Security
As we are going to customize the security configuration, we will disable
auto security configuration and specify the user name and its password - that is
why we need to create a custom security configuration class by extending the WebSecurityConfigurerAdapter class. So, create the ApplicationSecutiryConfiguration class in the config package:
So, first of all, we've injected
our jdbcDataSource here, and then in the
configure(AuthenticationManagerBuilder auth), we are telling AuthenticationManagerBuilder that we'll
use JDBC Authentication and assign our datasource to it. We've also configured
HttpSecurity for our custom login page and logout functionality.
Controller
Create a HomeController class in the controller package:
Our showHome() method will return home, and based on our configuration, the view resolver will look for
home.jsp (as we are using JSP as our view technology) in
/WEB-INF/view/. So we need to create home.jsp in
/WEB-INF/view/.
Now create the CustomLoginController class controller package. Here
it is:
Our showCustomLoginPage() method will return customLoginForm,
and based on our configuration, view resolver will search for
customLoginForm.jsp in /WEB-INF/view/. So we need to create
customLoginForm.jsp in /WEB-INF/view/.
View Page
To create the view page, first, create a view directory under
/WEB-INF. Then create a home.jsp in the view directory:
So this page is the same as our previous tutorial with logout functionality.
Now create a customLoginForm.jsp in the view directory in
/WEB-INF/:
OK, this is our custom login page. We've used the
Bootstrap
framework and some custom CSS to design this page. Along with these we've also
used the Spring MVC form tag to POST user credentials. We've mapped
/authenticateTheUser with the action value of the form tag - so that
the Spring framework will do the rest of the job for us.
Test the Application
Now run this application and put this URL -
http://localhost:8080/secure-spring-mvc-db-auth/, in the browser:
Now enter admin as username and admin123 as password as we had
stored in the database and press LOG IN to submit the page and the request
will be redirected to the home page:
Here, on the home page, we can see the logout button and you can press the
logout button to check the logout functionality.
As we've logged out from the application, a logout status message is given to
the user.
So in this tutorial, we set up Spring Security recommended DB tables,
configure the JDBC data source, and use that data source to authenticate the user.
You can download the source code from
here.
Happy coding!!! 😊
References
- PasswordEncoder - CodeMonk, Baeldung
- DataSource Configure - Connection Pool
No comments:
Post a Comment