VietMX's Blog
  • C++
  • JAVA
  • JS
  • NODEJS
  • PYTHON
  • TOOLS
  • BLOCKCHAIN
  • AI
  • EBOOK
  • ACM
  • ALGORITHM
  • Q&A

Spring Security Form Login

2021 VietMX JAVA 0

Table of Contents

  • 1. Introduction
  • 2. The Maven Dependencies
  • 3. Spring Security Java Configuration
    • 3.1. Authentication Manager
    • 3.2. Configuration to Authorize Requests
    • 3.3. Configuration for Form Login
  • 4. Add Spring Security to the Web Application
  • 5. The Spring Security XML Configuration
  • 6. The web.xml
  • 7. The Login Form
  • 8. Further Configuring Spring Login
    • 8.1. The Login Page
    • 8.2. The POST URL for Login
    • 8.3. The Landing Page on Success
    • 8.4. The Landing Page on Failure
  • 9. Conclusion

1. Introduction

This tutorial will focus on Login with Spring Security. We’re going to build on top of the previous Spring MVC example, as that’s a necessary part of setting up the web application along with the login mechanism.

2. The Maven Dependencies

When working with Spring Boot, the spring-boot-starter-security starter will automatically include all dependencies, such as spring-security-core, spring-security-web, and spring-security-config among others:

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

If we don’t use Spring Boot, please see the Spring Security with Maven article, which describes how to add all required dependencies. Both standard spring-security-web and spring-security-config will be required.

3. Spring Security Java Configuration

Let’s start by creating a Spring Security configuration class that extends WebSecurityConfigurerAdapter.

By adding @EnableWebSecurity, we get Spring Security and MVC integration support:

@Configuration
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
        // authentication manager (see below)
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        // http builder configurations for authorize requests and form login (see below)
    }
}

In this example, we used in-memory authentication and defined three users.

Next we’ll go through the elements we used to create the form login configuration.

Let’s start by building our Authentication Manager.

3.1. Authentication Manager

The Authentication Provider is backed by a simple, in-memory implementation, InMemoryUserDetailsManager. This is useful for rapid prototyping when a full persistence mechanism is not yet necessary:

protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .withUser("user1").password(passwordEncoder().encode("user1Pass")).roles("USER")
        .and()
        .withUser("user2").password(passwordEncoder().encode("user2Pass")).roles("USER")
        .and()
        .withUser("admin").password(passwordEncoder().encode("adminPass")).roles("ADMIN");
}

Here we’ll configure three users with the username, password, and role hard-coded.

Starting with Spring 5, we also have to define a password encoder. In our example, we’ll use the BCryptPasswordEncoder:

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

Next let’s configure the HttpSecurity.

3.2. Configuration to Authorize Requests

We’ll start by doing the necessary configurations to Authorize Requests.

Here we’re allowing anonymous access on /login so that users can authenticate. We’ll restrict /admin to ADMIN roles and securing everything else:

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
      .csrf().disable()
      .authorizeRequests()
      .antMatchers("/admin/**").hasRole("ADMIN")
      .antMatchers("/anonymous*").anonymous()
      .antMatchers("/login*").permitAll()
      .anyRequest().authenticated()
      .and()
      // ...
}

Note that the order of the antMatchers() elements is significant; the more specific rules need to come first, followed by the more general ones.

3.3. Configuration for Form Login

Next we’ll extend the above configuration for form login and logout:

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
      // ...
      .and()
      .formLogin()
      .loginPage("/login.html")
      .loginProcessingUrl("/perform_login")
      .defaultSuccessUrl("/homepage.html", true)
      .failureUrl("/login.html?error=true")
      .failureHandler(authenticationFailureHandler())
      .and()
      .logout()
      .logoutUrl("/perform_logout")
      .deleteCookies("JSESSIONID")
      .logoutSuccessHandler(logoutSuccessHandler());
}
  • loginPage() – the custom login page
  • loginProcessingUrl() – the URL to submit the username and password to
  • defaultSuccessUrl() – the landing page after a successful login
  • failureUrl() – the landing page after an unsuccessful login
  • logoutUrl() – the custom logout

4. Add Spring Security to the Web Application

To use the above-defined Spring Security configuration, we need to attach it to the web application.

We’ll use the WebApplicationInitializer, so we don’t need to provide any web.xml:

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext sc) {

        AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
        root.register(SecSecurityConfig.class);

        sc.addListener(new ContextLoaderListener(root));

        sc.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"))
          .addMappingForUrlPatterns(null, false, "/*");
    }
}

Note that this initializer isn’t necessary if we’re using a Spring Boot application. For more details on how the security configuration is loaded in Spring Boot, have a look at our article on Spring Boot security auto-configuration.

5. The Spring Security XML Configuration

Let’s also have a look at the corresponding XML configuration.

The overall project is using Java configuration, so we need to import the XML configuration file via a Java @Configuration class:

@Configuration
@ImportResource({ "classpath:webSecurityConfig.xml" })
public class SecSecurityConfig {
   public SecSecurityConfig() {
      super();
   }
}

And the Spring Security XML Configuration, webSecurityConfig.xml:

<http use-expressions="true">
    <intercept-url pattern="/login*" access="isAnonymous()" />
    <intercept-url pattern="/**" access="isAuthenticated()"/>

    <form-login login-page='/login.html' 
      default-target-url="/homepage.html" 
      authentication-failure-url="/login.html?error=true" />
    <logout logout-success-url="/login.html" />
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="user1" password="user1Pass" authorities="ROLE_USER" />
        </user-service>
        <password-encoder ref="encoder" />
    </authentication-provider>
</authentication-manager>

<beans:bean id="encoder" 
  class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
</beans:bean>

6. The web.xml

Before the introduction of Spring 4, we used to configure Spring Security in the web.xml; only an additional filter added to the standard Spring MVC web.xml:

[prismatic_encoded class=%%language-xml%%]Jmx0O2Rpc3BsYXktbmFtZSZndDtTcHJpbmcgU2VjdXJlZCBBcHBsaWNhdGlvbiZsdDsvZGlzcGxheS1uYW1lJmd0Ow0KDQombHQ7IS0tIFNwcmluZyBNVkMgLS0mZ3Q7DQombHQ7IS0tIC4uLiAtLSZndDsNCg0KJmx0OyEtLSBTcHJpbmcgU2VjdXJpdHkgLS0mZ3Q7DQombHQ7ZmlsdGVyJmd0Ow0KICAgICZsdDtmaWx0ZXItbmFtZSZndDtzcHJpbmdTZWN1cml0eUZpbHRlckNoYWluJmx0Oy9maWx0ZXItbmFtZSZndDsNCiAgICAmbHQ7ZmlsdGVyLWNsYXNzJmd0O29yZy5zcHJpbmdmcmFtZXdvcmsud2ViLmZpbHRlci5EZWxlZ2F0aW5nRmlsdGVyUHJveHkmbHQ7L2ZpbHRlci1jbGFzcyZndDsNCiZsdDsvZmlsdGVyJmd0Ow0KJmx0O2ZpbHRlci1tYXBwaW5nJmd0Ow0KICAgICZsdDtmaWx0ZXItbmFtZSZndDtzcHJpbmdTZWN1cml0eUZpbHRlckNoYWluJmx0Oy9maWx0ZXItbmFtZSZndDsNCiAgICAmbHQ7dXJsLXBhdHRlcm4mZ3Q7LyombHQ7L3VybC1wYXR0ZXJuJmd0Ow0KJmx0Oy9maWx0ZXItbWFwcGluZyZndDs=[/prismatic_encoded]

The filter – DelegatingFilterProxy – simply delegates to a Spring-managed bean – the FilterChainProxy – which itself is able to benefit from full Spring bean life-cycle management and such.

7. The Login Form

The login form page is going to be registered with Spring MVC using the straightforward mechanism to map views names to URLs. Furthermore, there is no need for an explicit controller in between:

registry.addViewController("/login.html");

This, of course, corresponds to the login.jsp:

<html>
<head></head>
<body>
   <h1>Login</h1>
   <form name='f' action="login" method='POST'>
      <table>
         <tr>
            <td>User:</td>
            <td><input type='text' name='username' value=''></td>
         </tr>
         <tr>
            <td>Password:</td>
            <td><input type='password' name='password' /></td>
         </tr>
         <tr>
            <td><input name="submit" type="submit" value="submit" /></td>
         </tr>
      </table>
  </form>
</body>
</html>

The Spring Login form has the following relevant artifacts:

  • login – the URL where the form is POSTed to trigger the authentication process
  • username – the username
  • password – the password

8. Further Configuring Spring Login

We briefly discussed a few configurations of the login mechanism when we introduced the Spring Security Configuration above. Now let’s go into some greater detail.

One reason to override most of the defaults in Spring Security is to hide that the application is secured with Spring Security. We also want to minimize the information a potential attacker knows about the application.

Fully configured, the login element looks like this:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
      .loginPage("/login.html")
      .loginProcessingUrl("/perform_login")
      .defaultSuccessUrl("/homepage.html",true)
      .failureUrl("/login.html?error=true")
}

Or the corresponding XML configuration:

<form-login 
  login-page='/login.html' 
  login-processing-url="/perform_login" 
  default-target-url="/homepage.html"
  authentication-failure-url="/login.html?error=true" 
  always-use-default-target="true"/>

8.1. The Login Page

Next we’ll configure a custom login page using the loginPage() method:

http.formLogin()
  .loginPage("/login.html")

Similarly, we can use the XML configuration:

login-page='/login.html'

If we don’t specify this, Spring Security will generate a very basic Login Form at the /login URL.

8.2. The POST URL for Login

The default URL where the Spring Login will POST to trigger the authentication process is /login, which used to be /j_spring_security_check before Spring Security 4.

We can use the loginProcessingUrl method to override this URL:

http.formLogin()
  .loginProcessingUrl("/perform_login")

We can also use the XML configuration:

login-processing-url="/perform_login"

By overriding this default URL, we’re concealing that the application is actually secured with Spring Security. This information should not be available externally.

8.3. The Landing Page on Success

After successfully logging in, we will be redirected to a page that by default is the root of the web application.

We can override this via the defaultSuccessUrl() method:

http.formLogin()
  .defaultSuccessUrl("/homepage.html")

Or with XML configuration:

default-target-url="/homepage.html"

If the always-use-default-target attribute is set to true, then the user is always redirected to this page. If that attribute is set to false, then the user will be redirected to the previous page they wanted to visit before being prompted to authenticate.

8.4. The Landing Page on Failure

Similar to the Login Page, the Login Failure Page is autogenerated by Spring Security at /login?error by default.

To override this, we can use the failureUrl() method:

http.formLogin()
  .failureUrl("/login.html?error=true")

Or with XML:

authentication-failure-url="/login.html?error=true"

9. Conclusion

In this Spring Login Example, we configured a simple authentication process. We also discussed the Spring Security Login Form, the Security Configuration, and some of the more advanced customizations available.

The implementation of this article can be found in the GitHub project – this is an Eclipse-based project, so it should be easy to import and run as it is.

When the project runs locally, the sample HTML can be accessed at:

http://localhost:8080/spring-security-mvc-login/login.html

Related posts:

Java Program to Find Nearest Neighbor for Static Data Set
Comparing Two HashMaps in Java
Java Program to Check whether Graph is Biconnected
Error Handling for REST with Spring
Java Program to Delete a Particular Node in a Tree Without Using Recursion
Java Program to Implement Segment Tree
Hướng dẫn Java Design Pattern – State
Request a Delivery / Read Receipt in Javamail
How to Read a File in Java
Refactoring Design Pattern với tính năng mới trong Java 8
Java Program to Implement ScapeGoat Tree
Debugging Reactive Streams in Java
Java Program to Find All Pairs Shortest Path
Java Program to implement Associate Array
Java Program to Apply DFS to Perform the Topological Sorting of a Directed Acyclic Graph
Guide to Spring Cloud Kubernetes
Java Program to Find the Longest Path in a DAG
Command-Line Arguments in Java
Java Program to Compute the Volume of a Tetrahedron Using Determinants
JUnit 5 @Test Annotation
A Guide to HashSet in Java
Giới thiệu Google Guice – Binding
Guide to the Java TransferQueue
Java Program to Implement Hamiltonian Cycle Algorithm
Guide to Selenium with JUnit / TestNG
Java Program to Use Above Below Primitive to Test Whether Two Lines Intersect
Guide to @ConfigurationProperties in Spring Boot
Performance Difference Between save() and saveAll() in Spring Data
Using JWT with Spring Security OAuth
Java Program to Implement Shoelace Algorithm
Java Program to Perform Preorder Recursive Traversal of a Given Binary Tree
Guide to Guava Multimap
  • Form Login
  • Spring Security

SEARCH

  • The Stern-Brocot tree and Farey sequences

    2021 0
  • 15 Puzzle Game: Existence Of The Solution

    2021 0
  • Josephus Problem

    2021 0
  • Optimal schedule of jobs given their deadlines and durations

    2021 0
  • Scheduling jobs on two machines

    2021 0
  • Scheduling jobs on one machine

    2021 0
  • Sprague-Grundy theorem

    2021 0
  • Games on arbitrary graphs

    2021 0
  • K-th order statistic in O(N)

    2021 0
  • Search the subarray with the maximum/minimum sum

    2021 0
  • Longest increasing subsequence

    2021 0
  • Range Minimum Query

    2021 0
  • Heavy-light decomposition

    2021 0
  • 2 – SAT

    2021 0
  • Paint the edges of the tree

    2021 1
  • Edge connectivity / Vertex connectivity

    2021 0
  • Topological Sorting

    2021 0
  • Kuhn’s Algorithm for Maximum Bipartite Matching

    2021 0

Algorithm Array Collections Convert Converting Custom Data Structure Deep Learning Dictionary File Finding Generate Graph Guide HttpClient Implement InputStream Introduction Jackson Java JavaScript JPA JUnit List Machine Learning MongoDB New Year Node.js OAuth2 Perform Program Python REST API Set Spring Spring Boot Spring Cloud Spring Data Spring MVC Spring Security Stream String Strings Tree WebFlux

  • ACM
  • AI
  • ALGORITHM
  • BLOCKCHAIN
  • C/C++
  • EBOOK
  • JAVA
  • JS
  • NODEJS
  • PYTHON
  • TOOLS
CONTACT INFORMATION
  • Email: maixuanviet.com@gmail.com
  • Skype: maixuanviet.com@outlook.com
  • Linkein: linkedin.com/in/maixuanviet
  • HackerRank: hackerrank.com/vietmx
  • Github: github.com/vietmx
  • Tiktok: tiktok.com/@maixuanviet.com

DMCA.com Protection Status