Spring Security 5.7.5 Core Authentication and Authorization Setup

Project Dependencies

Include the following essential dependencies in a Spring Boot project:

  • spring-boot-starter-parent (parent POM)
  • spring-boot-starter-web
  • spring-boot-starter-security
  • spring-boot-starter-test (optional, for testing)
  • spring-security-test (opsional, for testing)
<?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
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.3</version>
    </parent>
    <groupId>com.miao</groupId>
    <artifactId>SpringSecurity-First-Start</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <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-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Quick Start

When the application runs, a default user named user is created, and its generated password appears in the console log.

Basic Controller

package com.miao.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloSecurity {

    @RequestMapping("/world")
    public String test1() {
        return "<h1>Hello Spring Security!</h1>";
    }
}

Navigate to http://localhost:8080/hello/world. The default login form at /login intercepts the request. Use /logout to terminate the session.

Authentication Architecture

The authentication flow relies on AbstractAuthenticationProcessingFilter, AbstractUserDetailsAuthenticationProvider, and methods like preAuthenticationChecks and postAuthenticationChecks.

Security Filter Chain Configuration

Spring Security applies authentication to all endpoints by default. To customize which resources require authentication, define a SecurityFilterChain bean. If no such bean exists, the default configuration takes effect.

@Configuration
public class WebSecurityConfigurer {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http.authorizeHttpRequests()
                .mvcMatchers("/index").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .build();
    }
}

User Authentication Sources

Spring Security supplies an in-memory user store by default. To switch to custom authentication (e.g., database-backed), implement UserDetailsService, AuthenticationProvider, or related beans. Doing so disables the default in-memory user.

In-Memory User Configuration

@Bean
public InMemoryUserDetailsManager userDetailsService(PasswordEncoder encoder) {
    UserDetails adminUser = User.withUsername("root")
            .password(encoder.encode("123456"))
            .roles("ADMIN")
            .build();
    return new InMemoryUserDetailsManager(adminUser);
}

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

Placeholders such as {noop}, {bcrypt} indicate the password encoding scheme. BCryptPasswordEncoder is recomended for production.

Database-Backed Authentication

Implement UserDetailsService to load user details from a database.

@Component
public class MyUserDetailsService implements UserDetailsService {

    private final UserInfoDao userInfoDao;

    public MyUserDetailsService(UserInfoDao userInfoDao) {
        this.userInfoDao = userInfoDao;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo entity = userInfoDao.findByUsername(username);
        if (entity == null) {
            return null;
        }
        return User.withUsername(entity.getUsername())
                .password(entity.getPassword())
                .roles(entity.getRole())
                .build();
    }
}

Role-Based Method Security

Enable method-level authorization with @EnableGlobalMethodSecurity(prePostEnabled = true). Use @PreAuthorize on controller methods.

@RestController
public class UserController {

    @RequestMapping("/h1")
    @PreAuthorize("hasAnyRole('normal', 'admin')")
    public String multipleRoles() {
        return "Accessible by normal and admin roles";
    }

    @RequestMapping("/h2")
    @PreAuthorize("hasRole('admin')")
    public String adminOnly() {
        return "Only admin can view this";
    }
}

Accompanying configuration:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig {

    @Bean
    public InMemoryUserDetailsManager userDetailsService(PasswordEncoder encoder) {
        UserDetails normalUser = User.withUsername("normal")
                .password(encoder.encode("123456"))
                .roles("normal")
                .build();
        UserDetails adminUser = User.withUsername("admin")
                .password(encoder.encode("1234567"))
                .roles("admin")
                .build();
        return new InMemoryUserDetailsManager(normalUser, adminUser);
    }

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

Custom Login Page

Replace the default login form with a custom HTML page. Ensure the form submits POST to a configurable processing URL, and disables CSRF if necessary.

Login Form

<form action="/dologin" method="post">
  Username: <input type="text" name="username"><br>
  Password: <input type="password" name="password">
  <input type="submit" value="Login">
</form>

Security Configuration

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http.authorizeHttpRequests()
            .mvcMatchers("/login", "/index").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/dologin")
                .defaultSuccessUrl("/index", true)
            .and()
            .csrf().disable()
            .build();
}

Custom Authentication Success and Failure Handlers

For APIs or single-page applications, replace redirects with JSON responses by implementing AuthenticationSuccessHandler and AuthenticationFailureHandler.

Success Handler

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication) throws IOException {
        Map<String, Object> result = new HashMap<>();
        result.put("msg", "Login succeeded");
        result.put("status", 200);
        result.put("authentication", authentication);
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().println(new ObjectMapper().writeValueAsString(result));
    }
}

Configuration

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http.authorizeHttpRequests()
            .mvcMatchers("/login", "/index").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/login")
                .successHandler(new MyAuthenticationSuccessHandler())
            .and()
            .csrf().disable()
            .build();
}

For failures, redirect with failureForwardUrl or failureUrl, or provide a custom AuthenticationFailureHandler to return JSON error details.

Tags: Spring Security Authentication Authorization java Spring Boot

Posted on Thu, 14 May 2026 22:41:33 +0000 by mepaco