Securing Angular 7 application with Spring Boot JWT Security

As we have secured our angular application using spring boot basic security. In this article , i will take you through all the steps to secure your angular application with spring boot JWT(JSON Web Token) security. Using Spring boot basic security , we can provide in token based authentication and authorization to our application.

We need to configure users and their roles in in separate configuration file. We are creating two projects here –

  1. Spring boot JWT security application – This will handle the authentication and authorization for our UI application.
  2. UI for Todo manager in angular – This is the Todo manager application which will leverage the spring boot security feature.

Part 1: Spring boot JWT security application

In this part , we will be creating a spring boot application which provides JWT security. Its basically a RESTful webservice which has endpoints to access and modify Todos information. To access the Todo information through API , user needs to authenticate himself. Below configuration enables basic security.

SecurityConfig.java

package com.myjavablog.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

	@Autowired
	private UserDetailsService jwtUserDetailsService;

	@Autowired
	private JwtRequestFilter jwtRequestFilter;

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		// configure AuthenticationManager so that it knows from where to load
		// user for matching credentials
		// Use BCryptPasswordEncoder
		auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	@Override
	protected void configure(HttpSecurity httpSecurity) throws Exception {
		// We don't need CSRF for this example
		httpSecurity.csrf().disable()
				// dont authenticate this particular request
				.authorizeRequests().antMatchers("/authenticate").permitAll().antMatchers(HttpMethod.OPTIONS, "/**")
				.permitAll().
				// all other requests need to be authenticated
				anyRequest().authenticated().and().
				// make sure we use stateless session; session won't be used to
				// store user's state.
				exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.STATELESS);

		// Add a filter to validate the tokens with every request
		httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
	}
}

JwtAuthenticationController.java

Below is JwtAuthenticationController.java which has API endpoint to authenticate the user and provides us with JWT. createAuthenticationToken() method validates the user and generated the token for us which has expiration of 5*60*60 (5 Hours).

package com.myjavablog.controller;

import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.myjavablog.config.JwtTokenUtil;
import com.myjavablog.model.JwtRequest;
import com.myjavablog.model.JwtResponse;

@RestController
@CrossOrigin
public class JwtAuthenticationController {

	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private JwtTokenUtil jwtTokenUtil;

	@Autowired
	private UserDetailsService jwtInMemoryUserDetailsService;

	@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
	public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest authenticationRequest)
			throws Exception {

		authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());

		final UserDetails userDetails = jwtInMemoryUserDetailsService
				.loadUserByUsername(authenticationRequest.getUsername());

		final String token = jwtTokenUtil.generateToken(userDetails);

		return ResponseEntity.ok(new JwtResponse(token));
	}

	private void authenticate(String username, String password) throws Exception {
		Objects.requireNonNull(username);
		Objects.requireNonNull(password);

		try {
			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
		} catch (DisabledException e) {
			throw new Exception("USER_DISABLED", e);
		} catch (BadCredentialsException e) {
			throw new Exception("INVALID_CREDENTIALS", e);
		}
	}
}

TodoController.java

Below is the Rest controller class for managing Todo’s information –

package com.myjavablog.controller;

import com.myjavablog.model.Todo;
import com.myjavablog.model.User;
import com.myjavablog.repository.TodoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api")
public class TodoController {

    //@Autowired
    //private TodoRepository todoRepository;

    static List<Todo> list = new ArrayList<>();

    @GetMapping(produces = "application/json")
    @RequestMapping({ "/validateLogin" })
    public User validateLogin()
    {
        return new User("User successfully authenticated");
    }

    @GetMapping(produces = "application/json")
    @RequestMapping("/todos")
    public List<Todo> getTodos(){
        return list;
    }

    TodoController(){

        list.add(new Todo(1l,"Badminton", "Badminton at 6 am", "Pending"));
        list.add(new Todo(2l,"Cricket", "Cricket at 7 am", "Pending"));
        list.add(new Todo(3l,"Football", "Football at 8 am", "Pending"));
        list.add(new Todo(4l,"Cards", "Cards at 6 am", "Pending"));
        list.add(new Todo(5l,"TT", "TT at 6 am", "Completed"));
        list.add(new Todo(6l,"Golf", "Golf at 6 am", "Pending"));
        list.add(new Todo(7l,"Running", "Running at 6 am", "Pending"));
        list.add(new Todo(8l,"Walking", "Walking at 6 am", "Pending"));
        list.add(new Todo(9l,"Swimming", "Swimming at 6 am", "Completed"));
        list.add(new Todo(10l,"Reading", "Reading at 6 am", "Pending"));

        //return list;
    }

    @GetMapping("/todo/{id}")
    public Todo getTodo(@PathVariable Long id)
    {
        //return todoRepository.findById(id);

        for(Todo todo : list){

            if(todo.getId() == id){
                return todo;
            }
        }

        return null;
    }

    @DeleteMapping("/todo/{id}")
    public boolean deleteTodo(@PathVariable Long id){
        //todoRepository.deleteById(id);

        for(Todo todo : list){

            if(todo.getId() == id){
                list.remove(todo);
            }
        }

        return true;
    }

    @PostMapping("/todo")
    public Todo createTodo(@RequestBody Todo todo){

        list.add(todo);
        return todo;
        //return todoRepository.save(todo);
    }

    @PutMapping("/todo")
    public Todo updateTodo(@RequestBody Todo todo){


        for(Todo t : list){

            if(todo.getId() == t.getId()){
                list.remove(t);
                list.add(todo);
                return todo;
            }
        }

        return null;
        //return todoRepository.save(todo);
    }
}

JwtTokenUtil.java – This class is responsible for token generation.

JwtRequestFilter.java – All request to REST API are filtered through this class. Token is validated in each request for user authorization.

We can call the webservice through POSTMAN as below –

Get the Authentication Token
Call to todo API using Authentication token

Source code can be downloaded from below link –

Part 2: UI for Todo manager in angular 7

All the REST service calls are authenticated and authorized using the spring boot JWT security. Before calling todo services , we need to pass authorization header with all requests from UI.

In JWT token based security , we pass on base 64 encoded string of username and password to server as authorization header in below format –

Authorization Header = “Bearer ” + Base64Encoder(username:password)

Step 1: Create new angular application

Refer below post for creating new angular application –

Angular Installation and Setup

Step 2: Create modules for material and primeng components

Create two modules for material(material.module.ts) and primeng( primeng.module.ts ) to define all the related components required in application. These two modules are also required to be imported in main module (app.module.ts)

Please refer below link for primeng and material configuration –

CRUD Operations using primeng datatable and Material Design

Step 3: Create components (Presentation layer)

Create components named header, footer, login,logout and todo components for Todo Manager application.

Todo manager application shows all todos in primeng datatable . Also we are allowed to perform CRUD operations on all todos. All CRUD operations are done in todo component as below –

Todo component –

  • components\todo\todo.component.html
  • components\todo\todo.component.ts

Step 4: Add the routing for application (Application Navigation/Routing)

We have to create a route for the application navigation. Below file contains routing configuration –

  • src\app\app-routing.module.ts
import { NgModule, ViewChildren } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { TodoComponent } from './components/todo/todo.component';
import { TodoAddComponent } from './components/todo-add/todo-add.component';
import { TodoEditComponent } from './components/todo-edit/todo-edit.component';
import { AuthGaurdService } from './services/auth-gaurd.service';
import { LogoutComponent } from './components/logout/logout.component';
import { LoginComponent } from './components/login/login.component';

const routes: Routes = [
  { path: 'todo-list', component: TodoComponent ,canActivate:[AuthGaurdService]},
  { path: 'todo-add', component: TodoAddComponent ,canActivate:[AuthGaurdService] },
  { path: 'todo-edit/:id', component: TodoEditComponent ,canActivate:[AuthGaurdService]},
  { path: '', component: TodoComponent,canActivate:[AuthGaurdService] },
  { path: 'login', component: LoginComponent },
  { path: 'logout', component: LogoutComponent,canActivate:[AuthGaurdService] }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

All the routes are guarded by auth guard service. AuthGuardService checks ,if user is logged in to the application and then only it activates those routes configured in app-routing.module.ts .

AuthGuardService has canActivate() method which returns true if user is already logged into the application. If user is not logged into the application then it returns false and redirect him to login page.

import { Injectable } from '@angular/core';
import { Router, ActivatedRouteSnapshot, RouterStateSnapshot, CanActivate } from '@angular/router';
import { AuthenticationService } from './authentication.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGaurdService implements CanActivate {

  constructor(private router: Router,
    private authService: AuthenticationService) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (this.authService.isUserLoggedIn())
      return true;

    this.router.navigate(['login']);
    return false;
  }
}

Step 5: Authentication and Todo service (Service Layer)

AuthenticationService (authentication.service.ts) – It handles user authentication into the application. It has authenticate( username, password ) method which receives username and password entered on login page and authenticate user using spring basic authentication method.

Whenever you hit webservice , SecurityConfig.java comes into picture. If you remember, we have configured JWT security in spring boot application created earlier . When we hit todo service then every the time we are authenticated against spring boot JWT security. We need to pass authorization header all the time while hitting webservice from UI. Authorization header contains user credentials and JSON Web Token which has some expiry value upto which we can make request to TODO API.

Also it stores user information in session for checking user logged in status.

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { map } from 'rxjs/operators';

export class User{
  constructor(
    public status:string,
     ) {}
  
}

export class JwtResponse{
  constructor(
    public jwttoken:string,
     ) {}
  
}

@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {
  
  constructor(private httpClient: HttpClient){
  }

  authenticate(username, password) {
    return this.httpClient.post<any>('http://localhost:8081/authenticate',{username,password}).pipe(
     map(
       userData => {
        sessionStorage.setItem('username',username);
        let tokenStr= 'Bearer '+userData.token;
        sessionStorage.setItem('token', tokenStr);
        return userData;
       }
     )

    );
  }

  isUserLoggedIn() {
    let user = sessionStorage.getItem('username')
    console.log('Is User Logged in: '+ !(user === null))
    return !(user === null)
  }

  logOut() {
    sessionStorage.removeItem('username')
  }
}

We also have TodoService (todo.service.ts) to perform various operations on Todo information.

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { map, catchError, tap, retry } from 'rxjs/operators';
import { Todo } from './../domain/Todo';

@Injectable({
  providedIn: 'root'
})
export class TodoService {

  endpoint = 'http://localhost:8081/api';

  username = 'myjavablog';
  password = 'password';

  constructor(private httpClient: HttpClient) {
  }

  // Http Options
  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  }
  
  public deleteTodo(todoId) {

    const headers = new HttpHeaders({ Authorization: 'Bearer ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.delete<Todo>("http://localhost:8081/api/todo" + "/" + todoId, { headers });
  }

  public createTodo(todo) {

    const headers = new HttpHeaders({ Authorization: 'Bearer ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.post<Todo>("http://localhost:8081/api/todo", todo, { headers });
  }

  // To Get List Of Todos
  getTodoList(): Observable<any> {
    
    const headers = new HttpHeaders({ Authorization: 'Bearer ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.get<Todo[]>('http://localhost:8081/api/todos', { headers });
  }

  // HttpClient API get() method => Fetch Todo
  getTodo(id): Observable<Todo> {

    const headers = new HttpHeaders({ Authorization: 'Bearer ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.get<Todo>(this.endpoint + '/todos/' + id, { headers });
  }
  
  // HttpClient API put() method => Update Todo
  updateTodo(id, todo): Observable<Todo> {
    
    const headers = new HttpHeaders({ Authorization: 'Bearer ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.put<Todo>(this.endpoint + '/todo' , JSON.stringify(todo), { headers });
      
  }
}

You can download source code for this application from below link –

Step 6: Run the application

ng serve

Login page

Login page

Home page

Home Page
Generated Token during login

Add todo –

Add Todo

Securing Angular 7 application with Spring Boot Basic Security

We need to configure users and their roles in in separate configuration file. We are creating two projects here –

In this article , i will take you through all the steps to secure your angular application with spring boot basic security. Using Spring boot basic security , we can provide in memory authentication and authorization to our application.

  1. Spring boot basic security application – This will handle the authentication and authorization for our UI application.
  2. UI for Todo manager in angular – This is the Todo manager application which will leverage the basic spring boot security feature.

Part 1: Spring boot basic security application

In this part , we will be creating a simple spring boot application which provides basic security. Its basically a RESTful webservice which has endpoints to access and modify Todos information. To access the Todo information through API , user needs to authenticate himself. Below configuration enables basic security.

SecurityConfig.java

package com.myjavablog;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().
                authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll().anyRequest().authenticated()
                .and().httpBasic();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("myjavablog").password("{noop}secure").roles("USER");
    }
}

Below is the Rest controller class (TodoController.java)-

package com.myjavablog.controller;

import com.myjavablog.model.Todo;
import com.myjavablog.model.User;
import com.myjavablog.repository.TodoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api")
public class TodoController {

    //@Autowired
    //private TodoRepository todoRepository;

    static List<Todo> list = new ArrayList<>();

    @GetMapping(produces = "application/json")
    @RequestMapping({ "/validateLogin" })
    public User validateLogin()
    {
        return new User("User successfully authenticated");
    }

    @GetMapping(produces = "application/json")
    @RequestMapping("/todos")
    public List<Todo> getTodos(){
        return list;
    }

    TodoController(){

        list.add(new Todo(1l,"Badminton", "Badminton at 6 am", "Pending"));
        list.add(new Todo(2l,"Cricket", "Cricket at 7 am", "Pending"));
        list.add(new Todo(3l,"Football", "Football at 8 am", "Pending"));
        list.add(new Todo(4l,"Cards", "Cards at 6 am", "Pending"));
        list.add(new Todo(5l,"TT", "TT at 6 am", "Completed"));
        list.add(new Todo(6l,"Golf", "Golf at 6 am", "Pending"));
        list.add(new Todo(7l,"Running", "Running at 6 am", "Pending"));
        list.add(new Todo(8l,"Walking", "Walking at 6 am", "Pending"));
        list.add(new Todo(9l,"Swimming", "Swimming at 6 am", "Completed"));
        list.add(new Todo(10l,"Reading", "Reading at 6 am", "Pending"));

        //return list;
    }

    @GetMapping("/todo/{id}")
    public Todo getTodo(@PathVariable Long id)
    {
        //return todoRepository.findById(id);

        for(Todo todo : list){

            if(todo.getId() == id){
                return todo;
            }
        }

        return null;
    }

    @DeleteMapping("/todo/{id}")
    public boolean deleteTodo(@PathVariable Long id){
        //todoRepository.deleteById(id);

        for(Todo todo : list){

            if(todo.getId() == id){
                list.remove(todo);
            }
        }

        return true;
    }

    @PostMapping("/todo")
    public Todo createTodo(@RequestBody Todo todo){

        list.add(todo);
        return todo;
        //return todoRepository.save(todo);
    }

    @PutMapping("/todo")
    public Todo updateTodo(@RequestBody Todo todo){


        for(Todo t : list){

            if(todo.getId() == t.getId()){
                list.remove(t);
                list.add(todo);
                return todo;
            }
        }

        return null;
        //return todoRepository.save(todo);
    }
}

Source code can be downloaded from below link –

Part 2: UI for Todo manager in angular 7

All the REST service calls are authenticated and authorized using the spring boot basic security. Before calling todo services , we need to pass authorization header with all requests from UI. All our requests to REST calls are intercepted encoded by base 64 encoding and then passed to REST API.

In basic security we pass on base 64 encoded string of username and password to server as authorization header in below format –

Authorization Header = “Basic” + Base64Encoder(username:password)

Step 1: Create new angular application

Refer below post for creating new angular application –

Angular Installation and Setup

Step 2: Create modules for material and primeng components

Create two modules for material(material.module.ts) and primeng( primeng.module.ts ) to define all the related components required in application. These two modules are also required to be imported in main module (app.module.ts)

Please refer below link for primeng and material configuration –

CRUD Operations using primeng datatable and Material Design

Step 3: Create components (Presentation layer)

Create components named header, footer, login,logout and todo components for Todo Manager application.

Todo manager application shows all todos in primeng datatable . Also we are allowed to perform CRUD operations on all todos. All CRUD operations are done in todo component as below –

Todo component –

  • components\todo\todo.component.html
  • components\todo\todo.component.ts

Step 4: Add the routing for application (Application Navigation/Routing)

We have to create a route for the application navigation. Below file contains routing configuration –

  • src\app\app-routing.module.ts
import { NgModule, ViewChildren } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { TodoComponent } from './components/todo/todo.component';
import { TodoAddComponent } from './components/todo-add/todo-add.component';
import { TodoEditComponent } from './components/todo-edit/todo-edit.component';
import { AuthGaurdService } from './services/auth-gaurd.service';
import { LogoutComponent } from './components/logout/logout.component';
import { LoginComponent } from './components/login/login.component';

const routes: Routes = [
  { path: 'todo-list', component: TodoComponent ,canActivate:[AuthGaurdService]},
  { path: 'todo-add', component: TodoAddComponent ,canActivate:[AuthGaurdService] },
  { path: 'todo-edit/:id', component: TodoEditComponent ,canActivate:[AuthGaurdService]},
  { path: '', component: TodoComponent,canActivate:[AuthGaurdService] },
  { path: 'login', component: LoginComponent },
  { path: 'logout', component: LogoutComponent,canActivate:[AuthGaurdService] }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

All the routes are guarded by auth guard service. AuthGuardService checks ,if user is logged in to the application and then only it activates those routes configured in app-routing.module.ts .

AuthGuardService has canActivate() method which returns true if user is already logged into the application. If user is not logged into the application then it returns false and redirect him to login page.

import { Injectable } from '@angular/core';
import { Router, ActivatedRouteSnapshot, RouterStateSnapshot, CanActivate } from '@angular/router';
import { AuthenticationService } from './authentication.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGaurdService implements CanActivate {

  constructor(private router: Router,
    private authService: AuthenticationService) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (this.authService.isUserLoggedIn())
      return true;

    this.router.navigate(['login']);
    return false;
  }
}

Step 5: Authentication and Todo service (Service Layer)

AuthenticationService (authentication.service.ts) – It handles user authentication into the application. It has authenticate( username, password ) method which receives username and password entered on login page and authenticate user using spring basic authentication method.

Whenever you hit webservice , SecurityConfig.java comes into picture. If you remember, we have configured basic security in spring boot application created earlier . When we hit todo service then all the time we are authenticated against spring boot basic security. We need to pass authorization header all the time while hitting webservice from UI.

Also it stores user information in session for checking user logged in status.

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { map } from 'rxjs/operators';

export class User {
  constructor(
    public status: string,
  ) { }
}

@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {
  
  constructor(private httpClient: HttpClient){
  }

  authenticate(username, password) {
    const headers = new HttpHeaders({ Authorization: 'Basic ' + btoa(username + ':' + password) });
    return this.httpClient.get<User>('http://localhost:8081/api/validateLogin', { headers }).pipe(
      map(
        userData => {
          sessionStorage.setItem('username', username);
          return userData;
        }
      )

    );
  }

  isUserLoggedIn() {
    let user = sessionStorage.getItem('username')
    console.log(!(user === null))
    return !(user === null)
  }

  logOut() {
    sessionStorage.removeItem('username')
  }
}

We also have TodoService (todo.service.ts) to perform various operations on Todo information.

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { map, catchError, tap, retry } from 'rxjs/operators';
import { Todo } from './../domain/Todo';

@Injectable({
  providedIn: 'root'
})
export class TodoService {

  endpoint = 'http://localhost:8081/api';

  username = 'myjavablog';
  password = 'secure';

  constructor(private httpClient: HttpClient) {
  }

  // Http Options
  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  }
  
  public deleteTodo(todoId) {

    const headers = new HttpHeaders({ Authorization: 'Basic ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.delete<Todo>("http://localhost:8081/api/todo" + "/" + todoId, { headers });
  }

  public createTodo(todo) {

    const headers = new HttpHeaders({ Authorization: 'Basic ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.post<Todo>("http://localhost:8081/api/todo", todo, { headers });
  }

  // To Get List Of Todos
  getTodoList(): Observable<any> {
    
    const headers = new HttpHeaders({ Authorization: 'Basic ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.get<Todo[]>('http://localhost:8081/api/todos', { headers });
  }

  // HttpClient API get() method => Fetch Todo
  getTodo(id): Observable<Todo> {

    const headers = new HttpHeaders({ Authorization: 'Basic ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.get<Todo>(this.endpoint + '/todos/' + id, { headers });
  }
  
  // HttpClient API put() method => Update Todo
  updateTodo(id, todo): Observable<Todo> {
    
    const headers = new HttpHeaders({ Authorization: 'Basic ' + btoa(this.username + ':' + this.password) });
    return this.httpClient.put<Todo>(this.endpoint + '/todo' , JSON.stringify(todo), { headers });
      
  }
}

You can download source code for this application from below link –

Step 6: Run the application

ng serve

Login page

Home page

Add todo –

Spring Boot + Spring Security + H2 Database

In this tutorial , we will see how to secure your web application by authenticating and authorizing users against database. User and role information is stored in database .

GitHub Link:Code for this example can be found on below gitHub link-

Tools :

  • Spring Boot 2.1.1.RELEASE
  • Spring MVC
  • Spring Security
  • Maven
  • IntelliJ IDEA
  • Lombok

Step 1:  Create a simple spring boot application in Intellij IDEA editor as shown in below link –

Our final Project structure will look like –

Step 2:Define all dependencies required in pom file as below –

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<pre><code><parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.myjavablog</groupId>
<artifactId>spring-boot-database-security</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-database-security</name>
<description>Demo project for Spring Boot</description>

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-jdbc</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <!--<scope>runtime</scope>-->
    </dependency>

    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
    </dependency>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>

</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build></code></pre>
</project>

In addition to spring-boot-starter-security dependency ,we will be using lombok third party library to reduce boilerplate code for model/data objects, e.g., it can generate getters and setters for those object automatically by using Lombok annotations. The easiest way is to use the @Data annotation.

Step3: Now create a configuration for creating beans for BCryptPasswordEncoder and H2 database . Also we need to configure security mechanism through database using configuration file –

package com.myjavablog.config;

import org.h2.server.web.WebServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class BeanConfiguration implements WebMvcConfigurer {
<pre><code>@Bean
public BCryptPasswordEncoder passwordEncoder() {
    BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
    return bCryptPasswordEncoder;
}

@Bean
ServletRegistrationBean h2servletRegistration() {
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(new WebServlet());
    registrationBean.addUrlMappings("/console/*");
    return registrationBean;
}</code></pre>
}

package com.myjavablog.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
<pre><code>@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;

@Autowired
private DataSource dataSource;

@Value("${spring.queries.users-query}")
private String usersQuery;

@Value("${spring.queries.roles-query}")
private String rolesQuery;

@Override
protected void configure(AuthenticationManagerBuilder auth)
        throws Exception {
    auth.
            jdbcAuthentication()
            .usersByUsernameQuery(usersQuery)
            .authoritiesByUsernameQuery(rolesQuery)
            .dataSource(dataSource)
            .passwordEncoder(bCryptPasswordEncoder);
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.
            authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/login").permitAll()
            .antMatchers("/registration").permitAll()
            .antMatchers("/admin/**").hasAuthority("ADMIN").anyRequest()
            .authenticated().and().csrf().disable().formLogin()
            .loginPage("/login").failureUrl("/login?error=true")
            .defaultSuccessUrl("/admin/adminHome")
            .usernameParameter("email")
            .passwordParameter("password")
            .and().logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/").and().exceptionHandling()
            .accessDeniedPage("/access-denied")

    ;
}

@Override
public void configure(WebSecurity web) throws Exception {

    web.ignoring()
            .antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**", "/console/**");
}</code></pre>
}

Step 4: Create a model classes for User and Role

As we are using lombok libarary , we dont need to create setter and getter in model class . Also it helps in building mock objects at runtime for unit testing.

package com.myjavablog.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import java.util.Set;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "USER")
public class User {
<pre><code>@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "USER_ID")
private int id;
@Column(name = "EMAIL")
@Email(message = "*Please provide a valid Email")
@NotEmpty(message = "*Please provide an email")
private String email;
@Column(name = "PASSWORD")
@Length(min = 5, message = "*Your password must have at least 5 characters")
@NotEmpty(message = "*Please provide your password")
private String password;
@Column(name = "NAME")
@NotEmpty(message = "*Please provide your name")
private String name;
@Column(name = "LAST_NAME")
@NotEmpty(message = "*Please provide your last name")
private String lastName;
@Column(name = "ACTIVE")
private int active;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "USER_ROLE", joinColumns = @JoinColumn(name = "USER_ID"), inverseJoinColumns = @JoinColumn(name = "ROLE_ID"))
private Set<Role> roles;</code></pre>
}

package com.myjavablog.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "ROLE")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ROLE_ID")
private int id;
@Column(name = "ROLE")
private String role;
}

Step 5: Create Service layer –

package com.myjavablog.service;

import com.myjavablog.model.User;
import org.springframework.stereotype.Service;

public interface UserService {
<pre><code>public User findUserByEmail(String email) ;
public User saveUser(User user);</code></pre>
}

package com.myjavablog.service;

import com.myjavablog.model.Role;
import com.myjavablog.model.User;
import com.myjavablog.repository.RoleRepository;
import com.myjavablog.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.HashSet;

@Service
public class UserServiceImpl implements UserService {
<pre><code>private UserRepository userRepository;
private RoleRepository roleRepository;
private BCryptPasswordEncoder bCryptPasswordEncoder;

@Autowired
public UserServiceImpl(UserRepository userRepository, RoleRepository roleRepository, BCryptPasswordEncoder bCryptPasswordEncoder) {
    this.userRepository = userRepository;
    this.roleRepository = roleRepository;
    this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}

@Override
public User findUserByEmail(String email) {
    return userRepository.findByEmail(email);
}

@Override
public User saveUser(User user) {
    user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
    user.setActive(1);
    Role userRole = roleRepository.findByRole("ADMIN");
    user.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
    return userRepository.save(user);
}</code></pre>
}

Step 6: Create JPA repositories for User and Role to interact with the databse –

package com.myjavablog.repository;

import com.myjavablog.model.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface RoleRepository extends JpaRepository<Role, Integer> {
public Role findByRole(String role);
}

package com.myjavablog.repository;

import com.myjavablog.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
public User findByEmail(String email);
}

Step 7: Create a controller to save the user and navigate

package com.myjavablog.controller;

import com.myjavablog.model.User;
import com.myjavablog.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.Valid;

@Controller
public class UserController {
<pre><code>@Autowired
private UserService userService;

@RequestMapping(value={"/", "/login"}, method = RequestMethod.GET)
public ModelAndView login(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("login");
    return modelAndView;
}

@RequestMapping(value="/registration", method = RequestMethod.GET)
public ModelAndView registration(){
    ModelAndView modelAndView = new ModelAndView();
    User user = new User();
    modelAndView.addObject("user", user);
    modelAndView.setViewName("registration");
    return modelAndView;
}

@RequestMapping(value = "/registration", method = RequestMethod.POST)
public ModelAndView createNewUser(@Valid User user, BindingResult bindingResult) {
    ModelAndView modelAndView = new ModelAndView();
    User userExists = userService.findUserByEmail(user.getEmail());
    if (userExists != null) {
        bindingResult
                .rejectValue("email", "error.user",
                        "There is already a user registered with the email provided");
    }
    if (bindingResult.hasErrors()) {
        modelAndView.setViewName("registration");
    } else {
        userService.saveUser(user);
        modelAndView.addObject("successMessage", "User has been registered successfully");
        modelAndView.addObject("user", new User());
        modelAndView.setViewName("registration");

    }
    return modelAndView;
}

@RequestMapping(value="/admin/adminHome", method = RequestMethod.GET)
public ModelAndView home(){
    ModelAndView modelAndView = new ModelAndView();
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    User user = userService.findUserByEmail(auth.getName());
    modelAndView.addObject("userName", "Welcome " + user.getName() + " " + user.getLastName() + " (" + user.getEmail() + ")");
    modelAndView.addObject("adminMessage","This Page is available to Users with Admin Role");
    modelAndView.setViewName("admin/adminHome");
    return modelAndView;
}

@RequestMapping(value="/user/userHome", method = RequestMethod.GET)
public ModelAndView user(){
    ModelAndView modelAndView = new ModelAndView();
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    User user = userService.findUserByEmail(auth.getName());
    modelAndView.addObject("userName", "Welcome " + user.getName() + " " + user.getLastName() + " (" + user.getEmail() + ")");
    modelAndView.addObject("userMessage","This Page is available to Users with User Role");
    modelAndView.setViewName("user/userHome");
    return modelAndView;
}</code></pre>
}

Step 8: Create a UI layer using Thymleaf templates .

Step 9: Run the application and go to H2 database console by navigating to http://localhost:8081/console

Once the application is up and running , H2 database will be automatically started. You can navigate to http://localhost:8081/console to see the tables created as shown below-

Also you need to insert few roles initially.

INSERT INTO ROLE VALUES (1, "ADMIN");
INSERT INTO ROLE VALUES (2, "USER");

Step 10: Now go to application http://localhost:8081/

You can navigate to registration page by clicking on “Go to registration page ” at the top .

Once you register , User details will be saved to USER table –

Now when you login with registered user details then you can see the admin page . As registered user is ADMIN role, Admin page will be displayed.

Spring boot + Spring security default authentication

You can secure your web applications using spring security. By using spring security with spring boot , you can minimize lot of configurations to be done for securing these applications.

Spring boot will automatically bootstrap your spring security jar (spring-boot-starter-security) added in your maven dependency and enable default security for your applications.

It will intercept all requests coming to application and asks user for authentication using spring security method used in our configuration. We can add security in different ways like inMemory, database, LDAP, OAUTH etc.

In this post, i will show a default security provided by spring boot security.

GitHub Link:

Tools :

  1. Tomcat Embed 8
  2. Maven 3.3
  3. Java 8
  4. IntelliJ IDEA
  5. Spring boot 2.1.1.RELEASE
  6. Spring Security 5.1.2.RELEASE

Step 1: Create a simple spring boot application in Intellij IDEA editor

Create new project using Spring Initializr as shown below –

Project Structure:

Step 2: Define all required dependencies for application

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<pre><code><groupId>com.myjavablog</groupId>
<artifactId>SpringBootSpringSecurityDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>SpringBootSpringSecurityDemo</name>
<description>Demo project for Spring Boot with spring security</description>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.3.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- JSTL for JSP -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>

    <!-- For JSP compilation -->
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.threeten/threetenbp -->
    <dependency>
        <groupId>org.threeten</groupId>
        <artifactId>threetenbp</artifactId>
        <version>0.7.2</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build></code></pre>
</project>

Step 3: Create a HomeController.java

package com.myjavablog.controller;

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController implements ErrorController {

@GetMapping("/")
public String homePage(){
return "Successfully logged in…";
}

final String PATH = "/error";
@RequestMapping(value = PATH)
public String error() {
return "Error handling";
}

@Override
public String getErrorPath() {
return PATH;
}
}

This is a controller class which has mapping for all the URLs .

Step 4: Create application.properties file to define application peroperties

server.port=8081
error.whitelabel.enabled=false

Step 5: SpringbootDefaultSecurityDemoApplication.java

This file will be automatically created by editor when you create the project. You have to run this file in order to bootstrap your spring boot application –

package com.myjavablog;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootDefaultSecurityDemoApplication {
<pre><code>public static void main(String[] args) {

    SpringApplication.run(SpringbootDefaultSecurityDemoApplication.class, args);
}</code></pre>
}

When you run the above class , application will be compiled and hosted on to embedded tomcat web server.

Step 6: Access the application

Now as the application is up and running , you can access the application from browser. You can make sure application is up and running from logs printed onto a console. If some error occurs then your application will not be launched.

When you try to access the application from http://localhost:8081/. Then your request will be intercepted by spring security automatically and you will be redirected to default login form as below –

You have to enter Username as ‘user‘ and password printed onto console logs . In my case password is –

Using generated security password: d58d9d78-7c80-4620-a92b-c93c68c780e7

Once you click on Sign in , you will be redirected to controller action –

Spring boot + Spring Security in memory authentication

We will use Spring boot with spring security as below –

We can secure spring application using spring security API provided by spring .

Github Link

Tools used for below project –

  1. Spring Boot 2.0.3.RELEASE
  2. Spring 5.0.7.RELEASE
  3. Tomcat Embed 8
  4. Maven 3.3
  5. Java 8
  6. Spring Tool Suite IDE (STS)

Step 1: Project Structure

This image has an empty alt attribute; its file name is sec_pjtstruc-291x300.jpg

Step 2: Create a project named SpringBootSpringSecurityDemo in STS (Refer Create new project in STS). Select web , security dependency from starter project  dependencies popup –

Step 3: Below pom.xml will be generated for you by STS . You need to add JSTL and Embeded tomcat dependency if it’s not present.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.myjavablog</groupId>
<artifactId>SpringBootSpringSecurityDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>SpringBootSpringSecurityDemo</name>
<description>Demo project for Spring Boot with spring security</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>

<!-- JSTL for JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>

<!-- For JSP compilation -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.threeten/threetenbp -->
<dependency>
<groupId>org.threeten</groupId>
<artifactId>threetenbp</artifactId>
<version>0.7.2</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

The spring-boot-starter-parent provides you all maven defaults required for any spring project.

Since we are developing a web application, we also need to add spring-boot-starter-web dependency. Additionally we need to include spring-boot-starter-security to provide security to this web application.
Let’s do security configuration first.

Conroller class- 

Step 4: Create “HelloController .java” file under com.myjavablog.controller package –

package com.myjavablog.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

/**
* @author anupb
*
*/

@Controller
public class HelloController {

@GetMapping("/hello")
public String getHomePage(Model model) {

model.addAttribute("message", "Lets make our app secure");

return "hello";

}

}

Its a simple controller with  only hello method inside it.

Below are the annotations used-

@Controller  –   @Controller is used to mark classes as Spring MVC Controller.

@GetMapping – This anootation is used map GET requests from browser to java methods.

If you run the application at this stage , spring boot will bootstrap spring security and default security will be provided. If you run the application and try to access http://localhost:8081/hello . This request will be intercepted by Spring security and will be redirected to login page as below –

This image has an empty alt attribute; its file name is defaultLogin-300x181.jpg

Login with default username : user and password generated by spring in below logs –

This image has an empty alt attribute; its file name is springPwd-300x141.jpg

Spring boot main file to bootstrap application –

Step 5: Create a  “SpringBootSpringSecurityDemoApplication.java”  file in package com.myjavablog

package com.myjavablog;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootSpringSecurityDemoApplication {

public static void main(String[] args) {
SpringApplication.run(SpringBootSpringSecurityDemoApplication.class, args);
}
}

This is the main file which bootstraps spring application.

We have just added @SpringBootApplication and it does all the work.
Let’s understand more about this annotation.
@SpringBootApplication is an annotation that adds all of the following:

@Configuration – It makes the class as a source of bean definitions for the application context.
@EnableAutoConfiguration – It enables Spring boot to add beans presents in classpath setting and various property setting.
Normally you would add @EnableWebMvc for a Spring MVC application, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath.
This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
@ComponentScan – It tells Spring to look for other components, configurations, and services in the default package, allowing it to find the controllers.
If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.

Step 6: Create a file named “WebSecurityConfiguaration.java” in package com.myjavablog

/**
*
*/
package com.myjavablog;

/**
* @author anupb
*
*/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguaration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests().antMatchers("/hello*").access("hasRole('ROLE_ADMIN')").and().formLogin();

}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).
withUser("myjavablog").password("secure").roles("ADMIN");
}
}

@EnableWebSecurity – Enables security for our application.

http.authorizeRequests().antMatchers(“/hello*”) – Secures all the URLs containing hello word in it.

http.authorizeRequests().antMatchers(“/hello*”).access(“hasRole(‘ROLE_ADMIN’)”).and().formLogin() – Allows role based access to these URLs . User with only admin can access this URL.

auth.inMemoryAuthentication().withUser(“myjavablog”).password(“secure”).roles(“ADMIN”) – We are using in Memory authentication to authenticate the user. User credentials are stored in memory for this example. We can store them either in database , LDAP etc.

When user provides myjavablog/secure credentials in login form then only he can access URLs with /hello  as this user has ADMIN role.

Step 7: Now create application.properties file inside /src/main/resources folder.

spring.mvc.view.prefix: /WEB-INF/views/
spring.mvc.view.suffix: .jsp
server.port=8081

This is simillar to dispatcher servlet in spring MVC to configure view resolution.

Step 8: Create index.jsp inside webapp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HelloWorld</title>
</head>
<body>
<a href="hello.html">Click here to read hello message </a>
</br>
<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>

Step 9: Create hello.jsp inside webapp/WEB-INF/views

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hello world Page</title>
</head>
<body>
${message}
</body>
</html>

Run the application

Step 10: Right Click on Project -> Debug As -> Maven Build

Step 8: Provide goals as below – 

mvn clean install spring-boot:run (Cmd prompt)

Or

Step 9:  Now go to URL http://localhost:8082/. Index page will open up as below –

This image has an empty alt attribute; its file name is index-1-300x155.jpg

Once you click on the link, this request will be intercepted by spring security and you will be asked to enter username and password.

This image has an empty alt attribute; its file name is login-1-300x190.jpg

Home Page –

This image has an empty alt attribute; its file name is homepage-300x130.jpg
Bitnami