Skip to content

Lab 18 - Secure View All Orders

We'd like to "lock down" the "view all orders" screen so it can only be seen by an admin.

A. Configure Dependencies

Add the following dependencies to the pom.xml file to pull in the necessary security dependencies.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-test</artifactId>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.thymeleaf.extras</groupId>
  <artifactId>thymeleaf-extras-springsecurity4</artifactId> 
  <version>3.0.2.RELEASE</version>
</dependency>

B. Configure the Security Adapter

Configure the security so that the /coffee-orders page can only be accessed by an ADMIN.

Add the following class, named SecurityConfig to your project:

package com.welltestedlearning.cvm;

import org.springframework.beans.factory.annotation.Autowired;
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.core.userdetails.User;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  // @formatter:off
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
          .antMatchers("/coffee-orders").hasRole("ADMIN")
        .and()
          .formLogin()
            .loginPage("/login")
            .failureUrl("/login-error");
  }
  // @formatter:on

  // @formatter:off
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .inMemoryAuthentication()
          .withUser("admin")
            .password("admin")
          .roles("ADMIN");
  }
  // @formatter:on
}

C. Add Login Page

Create a new template, called login.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title>Admin Login Page</title>
</head>
<body>
<h2>Admin Login Page</h2>

<form th:action="@{/login}" method="post">
  <p th:if="${loginError}">Invalid username and/or password.</p>
  <div>
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" autofocus="autofocus"/>
  </div>
  <div>
    <label for="password">Password:</label>
    <input type="password" id="password" name="password"/>
  </div>
  <input type="submit" value="Log in"/>
</form>
</body>
</html>

D. Create Login Controller

Create a controller class, called WebLoginController that will serve up and process the login template:

@Controller
public class WebLoginController {

  @GetMapping("/login")
  public String login() {
    return "login";
  }

  @GetMapping("/login-error")
  public String loginError(Model model) {
    model.addAttribute("loginError", true);
    return "login";
  }
}

Now try going to the view all orders page (localhost:8080/coffee-orders), and you'll see that you need to log in first.

Also try logging in with incorrect credentials to see what happens.


E. Add Security to Template

The Thymeleaf security tags start with sec and you can restrict parts of a page like this:

<div sec:authorize="isAuthenticated()">
  This content is only shown to authenticated users.
</div>

To use the sec prefix, you'll need to add the namespace like this, at the top of the HTML file:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
>

You can also display information about the logged-in user like this:

<p>Logged user: <span sec:authentication="name">Bob</span></p>
<p>Roles: <span sec:authentication="principal.authorities">user</span></p>

Add these to the page and then view it to see the name and its roles.