I just announced the newSpring Security 5 modules (primarily focused on OAuth2) in the course:

>> CHECK OUT LEARN SPRING SECURITY

1. Introduction

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

Further reading:

Spring Security – Redirect to the Previous URL After Login

A short example of redirection after login in Spring Security

Read more

Two Login Pages with Spring Security

A quick and practical guide to configuring Spring Security with two separate login pages.

Read more

Spring Security Form Login

A Spring Login Example - How to Set Up a simple Login Form, a Basic Security XML Configuration and some more Advanced Configuration Techniques.

Read more

2. The Maven Dependencies

To add Maven dependencies to the project, please see the Spring Security with Maven article. Both standard spring-security-web and spring-security-config will be required.

3. The web.xml

The Spring Security configuration in the web.xml is simple – only an additional filter added to the standard Spring MVC web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
  http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">

    <display-name>Spring Secured Application</display-name>

    <!-- Spring MVC -->
    <servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet
          </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
          org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>org.baeldung.spring.web.config</param-value>
    </context-param>
    <listener>
        <listener-class>
          org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <!-- Spring Security -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy
          </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

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

4. The Security Java Configuration

Here’s the corresponding Java configuration:

@Configuration
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
          .withUser("user1").password(passwordEncoder().encoder("user1Pass")).roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .authorizeRequests()
          .antMatchers("/login*").anonymous()
          .anyRequest().authenticated()
          .and()
          .formLogin()
          .loginPage("/login.html")
          .defaultSuccessUrl("/homepage.html")
          .failureUrl("/login.html?error=true")
          .and()
          .logout().logoutSuccessUrl("/login.html");
    }
 
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

4.1. authorizeRequests()

We are allowing anonymous access on /login so that users can authenticate. We are also securing everything else.

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

4.2. formLogin()

  • loginPage() – the custom login page
  • defaultSuccessUrl() – the landing page after a successful login
  • failureUrl() – the landing page after an unsuccessful login

4.3. Authentication Manager

The Authentication Provider is backed by a simple, in-memory implementation – InMemoryUserDetailsManager specifically – configured in plain text. This is meant to be used for rapid prototyping when a full persistence mechanism is not yet necessary.

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

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 the XML configuration file needs to be imported via a Java @Configuration class:

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

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 Login Form

The login form page is going to be registered with Spring MVC using the straightforward mechanism to map views names to URLs with 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

7. Further Configuring Spring Login

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

One reason to override most of the defaults in Spring Security is to hide the fact that the application is secured with Spring Security and 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"/>

7.1. The Login Page

The custom login page is configured via the loginPage() method:

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

Or, via XML configuration:

login-page='/login.html'

If this is not specified, a default URL is used – spring_security_login – and Spring Security will generate a very basic Login Form at that URL.

7.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.

This URL can be overridden via the loginProcessingUrl method:

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

Or, via XML configuration:

login-processing-url="/perform_login"

A good reason to override this default URL is to hide the fact that the application is actually secured with Spring Security – that information should not be available externally.

7.3. The Landing Page on Success

After a successful Login process, the user is redirected to a page – which by default is the root of the web application.

This can be overriden via the defaultSuccessUrl() method:

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

Or with XML configuration:

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

In case the always-use-default-target 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 promoted to authenticate.

7.4. The Landing Page on Failure

Same as with the Login Page, the Login Failure Page is autogenerated by Spring Security at /login?error by default.

This can be overridden via the failureUrl() method:

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

Or with XML:

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

8. Conclusion

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

The implementation of this Spring Login tutorial 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:8082/spring-security-mvc-login/login.html

I just announced the new Spring Security 5 modules (primarily focused on OAuth2) in the course:

>> CHECK OUT LEARN SPRING SECURITY

newest oldest most voted
Hitesh Lad
Guest
Hitesh Lad

Thanks for the conciseness of this post. I’ve added spring security to a new project with ease. Also thanks for that separate post RE: the maven dependencies. That was the icing on the cake

mbeddedsoft
Guest
mbeddedsoft

Hello, nice article. Very informative and helpful as usual. Question, I have a Spring 4 MVC web application configured with Spring Security. I’ve got login working using both the standard login form and a REST Service. The problem I have is, users are allowed to ‘view’ certain content anonymously. If they choose to log in, the can do this through the menu login option which is backed by a REST Service. The issue i have is, when users login through the menu option, they are automatically taken to the home page. Even though I already removed the ‘default-target-url’ property from… Read more »

Eugen Paraschiv
Guest

That’s an interesting question. It’s also a very information-rich question – and there’s a whole lot to unpack here – so I won’t hit on everything. First, let’s take a step back. An MVC style application is very different than a REST API – and the authentication process is significantly different as well. For instance, in an MVC style app, you may want the redirect, whereas in an API, you most likely don’t. And all of that is conveniently glossing over questions like – statelessness of the API and does the standard, cookie-based authentication fit into that – questions I… Read more »

mbeddedsoft
Guest
mbeddedsoft

Thank you Eugen!

Eugen Paraschiv
Guest

Sure thing, glad to help. Cheers,
Eugen.

sabrin
Guest
sabrin

Thank you for those interesting series. They help a lot. I have question for you, actually I implements authentication for sso with spring security saml, and now I need to active this authentication if I have special param in my request and if not use simple authentication form. If you have any idea I will be grateful.

Eugen Paraschiv
Guest

Hey Sabrin – you should be able to define multiple authentication providers. These should execute in order, and so you’ll have multiple opportunities to authenticate the user based on whatever is the deciding factor in that process.
Hope that helps. Cheers,
Eugen.

sabrin
Guest
sabrin

Hey, the problem is that for each type of authentication I need to display specific login page.

Eugen Paraschiv
Guest

OK, but based on what. What’s the deciding factor that the application is using when it decides which login page to show?

sabrin
Guest
sabrin

Thank you for replying. We could say that depends on parameter in request header.

Eugen Paraschiv
Guest

The way to go here would be trying to use multiple entry points, via multiple elements. Hope that helps. Cheers,
Eugen.

Sagar Oza
Guest
Sagar Oza

Nice and concise post on security. I have one question though when i enable in spring security config file and upload a csv in my web application it is showing me access denied 403 error. But when i comment or disable csrf element my csv is uploaded. What is the issue ? Thanks in advance

Eugen Paraschiv
Guest

Hey Sagar – so, once you enable CSRF protection, you’ll have to adapt your clients to send the new CSRF token as well. So, you’ll have to modify your client (your form, or whatever you’re using to do the upload) – to make sure it does send that new token.
And, if you’re accessing the API programmatically, you’ll of course have to take care of sending that token yourself (some libraries do have support for that).
Hope that helps. Cheers,
Eugen.

forough m
Guest
forough m

hello, it’s so useful
how can i get all of these codes in a zip file? can i download them?

Eugen Paraschiv
Guest

You can follow the link at the end of the article and clone the repository from github. So, yes.

forough m
Guest
forough m

hi, thank you, but i have a problem in another spring security web app that i spent many days on it and can not find this problem.
my app work with oauth2 and short!
i really need help. if anyone can help me please contact me.
thanks

Eugen Paraschiv
Guest

Not really sure what the actual problem is (from your description here).
Also, the comments aren’t really a good place to discuss this kind of code focused issue. Feel free to email me with the details.
Cheers,
Eugen.