Backend Development 8 min read

Implementing Login Authentication with Custom Annotations and Interceptors in Spring Boot

This guide demonstrates how to enforce login authentication in a Spring Boot application by defining a @LoginUser annotation, creating a corresponding interceptor, registering it in the MVC configuration, and testing the functionality with sample controller endpoints, illustrating session handling and thread‑local user storage.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Implementing Login Authentication with Custom Annotations and Interceptors in Spring Boot

This article explains how to protect Spring Boot controller methods that require a logged‑in user by using a custom @LoginUser annotation together with a request interceptor.

1. Define the annotation

package com.futao.springmvcdemo.annotation;

import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginUser {
    /**
     * Required user role (default is Normal)
     */
    Role role() default Role.Normal;
}

2. Implement the interceptor

package com.futao.springmvcdemo.annotation.impl;

import com.futao.springmvcdemo.model.enums.Role;
import com.futao.springmvcdemo.model.system.ErrorMessage;
import com.futao.springmvcdemo.model.system.RestResult;
import com.futao.springmvcdemo.utils.ThreadLocalUtils;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.*;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.*;

@Component
public class LoginUserInterceptor extends HandlerInterceptorAdapter {
    private static final Logger logger = LoggerFactory.getLogger(LoginUserInterceptor.class);

    @Resource
    private ThreadLocalUtils
threadLocalUtils;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler;
            LoginUser methodAnno = hm.getMethodAnnotation(LoginUser.class);
            LoginUser classAnno = hm.getBeanType().getAnnotation(LoginUser.class);
            if (ObjectUtils.anyNotNull(methodAnno, classAnno)) {
                HttpSession session = request.getSession(false);
                if (ObjectUtils.allNotNull(session)) {
                    String loginUser = (String) session.getAttribute(SystemConfig.LOGIN_USER_SESSION_KEY);
                    if (ObjectUtils.allNotNull(loginUser)) {
                        System.out.println("当前登陆用户为:" + loginUser);
                        threadLocalUtils.set(loginUser);
                        return true;
                    } else {
                        System.out.println("用户不存在");
                    }
                } else {
                    RestResult restResult = new RestResult(false, "-1", ErrorMessage.NOT_LOGIN, ErrorMessage.NOT_LOGIN.substring(6));
                    response.getWriter().append(JSON.toJSONString(restResult));
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // release thread‑local resource
        threadLocalUtils.remove();
    }
}

3. Register the interceptor in MVC configuration

package com.futao.springmvcdemo.annotation;

import com.futao.springmvcdemo.annotation.impl.*;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.web.servlet.config.annotation.*;
import javax.annotation.Resource;

@SpringBootConfiguration
public class WebMvcConfiguration implements WebMvcConfigurer {
    @Resource
    private SignInterceptor signInterceptor;
    @Resource
    private LoginUserInterceptor loginUserInterceptor;
    @Resource
    private RequestLogInterceptor requestLogInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(requestLogInterceptor).addPathPatterns("/**");
        registry.addInterceptor(loginUserInterceptor).addPathPatterns("/**");
        registry.addInterceptor(signInterceptor).addPathPatterns("/**");
    }
}

4. Sample controller

package com.futao.springmvcdemo.controller;

import com.futao.springmvcdemo.annotation.LoginUser;
import com.futao.springmvcdemo.service.UserService;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;

@RequestMapping(path = "User", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@RestController
public class UserController {
    @Resource
    private UserService userService;

    @LoginUser
    @GetMapping(path = "my")
    public JSONObject my() {
        JSONObject json = new JSONObject();
        json.put("当前的登陆的用户是:", userService.currentUser());
        return json;
    }

    @PostMapping(path = "login")
    public JSONObject login(@RequestParam("mobile") String mobile, HttpServletRequest request) {
        HttpSession session = request.getSession();
        session.setAttribute(SystemConfig.LOGIN_USER_SESSION_KEY, String.valueOf(UUID.randomUUID()));
        session.setMaxInactiveInterval(SystemConfig.SESSION_INVALIDATE_SECOND);
        return new JSONObject();
    }
}

The login endpoint creates an HttpSession , stores a random UUID as the user identifier, and writes the session ID to the browser as a JSESSIONID cookie. Subsequent requests automatically include this cookie; the interceptor extracts the session ID, looks up the stored user key in a server‑side map, and, if valid, places the user information into a ThreadLocal for easy access throughout the request processing.

Beyond authentication, the same annotation‑driven interceptor pattern can be extended to implement features such as third‑party request signing, system logging, or role‑based access control without modifying each controller method.

JavaSpring BootCustom Annotationsession managementLogin Interceptor
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

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