Comprehensive Spring Security Guide: Authentication, Authorization, Custom Configurations, and CSRF Protection

This article provides an in‑depth tutorial on Spring Security, covering its core concepts, authentication flow, project setup, dependency imports, custom UserDetailsService, password encoding, login handling, role‑based access control, CSRF protection, and integration with Thymeleaf, complete with practical code examples.

Top Architect
Top Architect
Top Architect
Comprehensive Spring Security Guide: Authentication, Authorization, Custom Configurations, and CSRF Protection

Spring Security Overview

Spring Security is a highly customizable security framework that leverages Spring IoC/DI and AOP to provide declarative security access control, reducing the amount of repetitive code needed for system security.

Core functions: authentication and authorization.

Authentication Process

Project Setup

Import Dependency

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

Accessing the Default Login Page

After adding the starter, Spring Security becomes active and intercepts all requests. Unauthenticated users are redirected to the built‑in login page.

In a browser, navigate to http://localhost:8080/ to see the login page.

Default credentials: username user, password printed in the console at application startup.

Custom Username and Password

Edit application.yml to define static users:

# Static user, typically used in internal networks
spring:
  security:
    user:
      name: test   # static username
      password: test   # static password

UserDetailsService Details

When no custom configuration is provided, Spring Security generates a default user. In real projects, credentials are fetched from a database, requiring a custom implementation of UserDetailsService:

@Component
public class UserSecurity implements UserDetailsService {
    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        User user = userService.login(userName);
        if (user == null) {
            throw new UsernameNotFoundException("用户名错误");
        }
        return new org.springframework.security.core.userdetails.User(
                userName, user.getPassword(), AuthorityUtils.createAuthorityList());
    }
}

PasswordEncoder Details

The PasswordEncoder interface handles password hashing and verification. Spring Security provides several implementations; a custom MD5 encoder example:

/**
 * Credential matcher for authentication.
 * encode – hash plain text password.
 * matches – verify plain text against hashed password.
 */
public class MyMD5PasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence charSequence) {
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            return toHexString(digest.digest(charSequence.toString().getBytes()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return "";
        }
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        return s.equals(encode(charSequence));
    }

    private String toHexString(byte[] tmp) {
        StringBuilder builder = new StringBuilder();
        for (byte b : tmp) {
            String s = Integer.toHexString(b & 0xFF);
            if (s.length() == 1) builder.append("0");
            builder.append(s);
        }
        return builder.toString();
    }
}

Register the encoder as a bean:

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(); // Spring's built‑in encoder
}

Login Configuration

Method 1 – Forward

http.formLogin()
    .usernameParameter("name")
    .passwordParameter("pswd")
    .loginPage("/toLogin")
    .loginProcessingUrl("/login")
    .failureForwardUrl("/failure")
    .successForwardUrl("/toMain");

Method 2 – Redirect

http.formLogin()
    .usernameParameter("name")
    .passwordParameter("pswd")
    .loginPage("/toLogin")
    .loginProcessingUrl("/login")
    .defaultSuccessUrl("/toMain", true)
    .failureUrl("/failure");

Custom Handlers

Failure handler example:

public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    private String url;
    private boolean isRedirect;
    public MyAuthenticationFailureHandler(String url, boolean isRedirect) {
        this.url = url;
        this.isRedirect = isRedirect;
    }
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        if (isRedirect) {
            response.sendRedirect(url);
        } else {
            request.getRequestDispatcher(url).forward(request, response);
        }
    }
}

Success handler example:

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private String url;
    private boolean isRedirect;
    public MyAuthenticationSuccessHandler(String url, boolean isRedirect) {
        this.url = url;
        this.isRedirect = isRedirect;
    }
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        if (isRedirect) {
            response.sendRedirect(url);
        } else {
            request.getRequestDispatcher(url).forward(request, response);
        }
    }
}

Authorization Rules

Example of role‑based access control:

http.authorizeRequests()
    .antMatchers("/toLogin", "/register", "/login", "/favicon.ico").permitAll()
    .antMatchers("/**/*.js").permitAll()
    .regexMatchers(".*[.]css").permitAll()
    .anyRequest().authenticated();

Custom 403 handler:

@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
        response.setStatus(HttpServletResponse.SC_OK);
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("<html><body><div style='width:800px;text-align:center;margin:auto;font-size:24px'>权限不足,请联系管理员</div></body></html>");
        response.getWriter().flush();
    }
}

Remember‑Me Feature

http.rememberMe()
    .rememberMeParameter("remember-me")
    .tokenValiditySeconds(14*24*60*60)
    .rememberMeCookieName("remember-me")
    .tokenRepository(persistentTokenRepository)
    .userDetailsService(userSecurity);

Spring Security Annotations

@Secured – restricts method access to specific roles (requires @EnableGlobalMethodSecurity(securedEnabled = true)).

@Secured({"ROLE_管理员", "ROLE_访客"})
@RequestMapping("/toMain")
public String toMain() { return "main"; }

@PreAuthorize – evaluates SpEL expressions before method execution (requires @EnableGlobalMethodSecurity(prePostEnabled = true)).

@PreAuthorize("hasAnyRole('ROLE_管理员','ROLE_访客')")
@RequestMapping("/toMain")
public String toMain() { return "main"; }

@PostAuthorize – evaluates after method execution.

Thymeleaf Integration

Add the following Maven dependencies:

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

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>

CSRF Protection

CSRF (Cross‑Site Request Forgery) is an attack where a malicious site tricks a user's browser into sending unwanted requests to a trusted site. Spring Security generates a CSRF token stored in the session or cookie and validates it on each state‑changing request.

To disable CSRF (not recommended for production), call http.csrf().disable();.

Conclusion

This guide walks through the essential aspects of Spring Security, from basic setup and authentication flow to advanced customizations such as password encoders, login handlers, role‑based access control, remember‑me, method‑level security annotations, Thymeleaf integration, and CSRF protection, providing ready‑to‑use code snippets for each feature.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaAuthenticationCSRFAuthorizationspring-securityPasswordEncoderUserDetailsService
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.