Showing posts with label Spring Framework. Show all posts

In this post, we will use Spring security to handle form based authentication. You can also read my previous posts on Basic Authentication and Digest Authentication.

Technologies/ Frameworks used

Spring Boot, Spring Security, Thymeleaf, AngularJS, Bootstrap

Adding depedencies in pom.xml

In the example, we will use Spring Boot, Spring Security, Undertow and thymeleaf and will add their starters as shown below.

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
      <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</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-thymeleaf</artifactId>
  </dependency>
  <dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity4</artifactId>
    <version>2.1.2.RELEASE</version>
  </dependency>
</dependencies>

Spring Security Configurations

We will extend WebSecurityConfigurerAdapter class which is a convenient base class to create WebSecurityConfigurer.

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .authorizeRequests()
            .antMatchers("/static/**", "/", "/index", "/bower_components/**").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
        .logout()
            .permitAll();
  }
 
  @Bean
  public UserDetailsService userDetailsService() {
    InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
    manager.createUser(User.withUsername("gaurav").password("s3cr3t").roles("USER").build());
    return manager;
  }
 
  @Bean
  SpringSecurityDialect securityDialect() {
    return new SpringSecurityDialect();
  }
}

@EnableWebSecurity annotation enables the Spring Security. We have overridden the configure method and configured the security. In the above code, we have disabled the csrf request support (By default it is enabled). We are authorizing all the requests to /index, /,/static folder and sub-folders, bower_components folder and its sub-folder accessible without authentication but all other should be authenticated. We are referring /login as our login page for authentication.

In the above code snippet, we are also registering the UserDetailsService. When we enable web-security in Spring, it expects a bean of type UserDetailsService which is used to get UserDetails. For example purpose, I am using InMemoryUserDetailsManager provided by the Spring.

MVC configuration

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/viewUsers").setViewName("viewUsers");
    registry.addViewController("/index").setViewName("index");
    registry.addViewController("/").setViewName("index");
    registry.addViewController("/login").setViewName("login");
  }
}

In the above configurations, we are registering ViewController and setting their names. This is all configuration that we need to do to enable Spring Security. You can find the full working project including the html files on Github.

Spring Boot provides two interfaces CommandLineRunner and ApplicationRunner to run specific piece of code when application is fully started. These interfaces get called just before run() on SpringApplication completes.

CommandLineRunner

This interface provides access to application arguments as string array. Let's see the example code for more clarity.

@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
  private static final Logger logger = LoggerFactory.getLogger(CommandLineAppStartupRunner.class);

  @Override
  public void run(String... args) throws Exception {
    logger.info("Application started with command-line arguments: {} . \n To kill this application, press Ctrl + C.", Arrays.toString(args));
  }
}

ApplicationRunner

ApplicationRunner wraps the raw application arguments and exposes interface ApplicationArguments which have many convinent methods to get arguments like getOptionNames() return all the arguments names, getOptionValues() return the agrument value and raw source arguments with method getSourceArgs(). Let's see an example code this.

@Component
public class AppStartupRunner implements ApplicationRunner {
  private static final Logger logger = LoggerFactory.getLogger(AppStartupRunner.class);

  @Override
  public void run(ApplicationArguments args) throws Exception {
    logger.info("Your application started with option names : {}", args.getOptionNames());
  }
}

When to use it

When you want to execute some piece of code exactly before the application startup completes, you can use it. In one of our project, we used these to source data from other microservice via service discovery which was registered in consul.

Ordering

You can register as many application/commandline runner as you want. You just need to register them as Bean in the application context and Spring Application will automatically picks them up. You can order them as well either by extending interface org.springframework.core.Ordered or by @Order annotation.

This is all about application/commandline runner. You can also see org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner in spring-batch which implements CommandLineRunner to register and start batch jobs at application startup. I hope you find this informative and helpful. You can grab the full example code on Github.

In this post, we will create a simple Spring Boot application which will run on embedded Apache Tomcat.

What is Spring Boot?

Spring Boot helps in creating stand-alone, production-grade application easily with minimum fuss. It is the opinionated view of Spring framework and other third party libraries which believes in convenient configuration based setup.

Let's start building Spring Boot Application.

Adding dependencies in pom.xml

We will first add spring-boot-starter-parent as parent of our maven based project.

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.1.RELEASE</version>
</parent>

The benefit of adding spring-boot-starter-parent is that version managing of dependency is easy. You can omit the required version on the dependency. It will pick the one configured the parent pom or from starters pom. Also, it conveniently setup the build related configurations as well.

Adding spring-boot-starter-web dependency

This will configure/ add all the required dependencies for spring-web module.

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

Writing App class

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

@SpringBootApplication indicates that class is configuration class and also trigger the auto-configure through @EnableAutoConfiguration and component scanning through @ComponentScan annotation in it.

@EnableAutoConfiguration

It enables the auto-configuration of Spring Application Context. It attempts to configuration your application as per the classpath dependencies that you have added.

In the main() of App class, we have delegated the call to run() method of SpringApplication. SpringApplication will bootstrap and auto-configure our application and in our case will start the embedded tomcat server. In run method, we have passed App.class as argument which tells Spring that this is our primary spring component (helps in bootstrapping).

Writing HelloGbController

@RestController
public class HelloGbController {
  @GetMapping
  public String helloGb() {
    return "Gaurav Bytes says, \"Hello There!!!\"";
  }
}

I have used two annotations @RestController and @GetMapping. You can read more on new annotation introduced by Spring here.

@RestController signifies that this class is web @Controller and spring will consider it to handle incoming web requests.

Running the application

You can use maven command mvn spring-boot:run to run it as Spring Boot application and when you hit the localhost:8080 on your web browser, you will see the below web page.

Creating a jar for spring boot application

You need to add spring-boot-maven-plugin plugin to your build configuration in pom.xml and then you can create a jar with maven command mvn repackage and simply run it as jar with command java -jar spring-boot-quickstart-0.0.1-SNAPSHOT.jar.

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

This is how you can build a simple spring boot application. I hope you find this post helpful. You can download the example code from Github.