February 03, 2020

Spring Security-Part 3 : Spring Security with JPA authentication and MySQL

Example of Spring Security with JPA authentication and MySQL
We will build a Spring boot project with Spring Security that will do database authentication using JPA and connect with MYSQL database.

Let's say we have a mysql database locally with database instance with name 'springsecurity'. This database has a table with a name 'user'. 'roles' has comma separated roles.


create table user(
username varchar_ignorecase(50) not null primary key,
password varchar_ignorecase(50) not null,
active boolean not null,
roles varchar_ignorecase(100)
);

INSERT INTO user (username, password, active.roles) VALUES ('dbuser', 'pass', true. 'ROLE_USER');

Now let's create a spring boot project from https://start.spring.io/.
  • Group: com.scrutiny
  • Artifact: spring-security-jpa
  • Dependencies: 
Now we will create a controller class with name HomeResource, which has three rest services. All the users with 'admin' role can access all the API's including '/admin' web-service, all the users with 'user' role can access  all the API's including '/user' web-service and excluding '/admin' API. Other web-services can be accessed directly.

If you want to use JDBC, their is a JDBC authentication manager by which we can tell what the database is and what are the queries which need to executed for authentication. For LDAP, their is a LDAP provider, which can be easily configured. However for JPA their no out of the box implementation for authentication.

To perform authentication using JPA, we will have a Authentication Manager (with a method authenticate()), this will talk to Authentication Provider (which will have authenticate() and supports() methods). The Authentication Provider will talk to the User Details Service (which has method loadUserByUserName()).

The loadUserByUserName() will get the user details from database using JPA services based on the user name.

First we need to create MyUserDetails class which will implements UserDetails and Override a couple of methods. We will create a local variable with userName, and return it from getUsername(). As of now we are returning hardcoded password as 'pass' from getPassword() method.

From the getAuthorities() we will return the list of hardcoded roles.

Let us create a user details service class with name 'MyUserDetailsService' with loadUserByUserName() method in it, this will (as of now) return the hardcoded users. We also need to annotate this class with @Service.

For Authorization and Authorization we will create a security configuration class with name SecurityConfiguration which extends WebSecurityConfigurerAdapter, and annotate it with @EnableWebSecurity.

For Authorization let us override configure() method which takes HttpSecurity. We will set up hard coded authorization.

We need to override another configure() method, this will give us opportunity to get hold of AuthenticationManagerBuilder. We need to annotate our SecurityConfiguration class with @EnableWebSecurity, this let spring security to give us AuthenticationManagerBuilder object.

Now, we will start application and try to access http://localhost:8080/user. It will ask us to enter credentials, here if we can enter user name as anything, and password as 'pass' (since we have configured only the hard-coded password) we can access the API.

Setting Up JPA
Now we will make changes in MyUserDetailsService's loadUserByUsername() to load the user from MySql using JPA. But before that we will create an Entity class with name User.

Then we will create a Repository interface with name UserRepository

After that we need to modify MyUserDetailsService and MyUserDetails class.


After this we need to add below properties in application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/springsecurity
spring.datasource.username=root
spring.datasource.password =password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

And then we need to add @EnableJpaRepositories annotation in our main class.

After restarting the application, when we try to access any API, we need to enter the credentials, which were configured in database.

-K Himaanshu Shuklaa..

No comments:

Post a Comment