Backend Development 12 min read

Implementing Multi-Device Token Storage and Validation with Spring Boot, Redis, and Vue

This article explains how to design and implement a token generation, storage, and verification system for both PC and mobile clients in a distributed microservice architecture, using Spring Boot, Redis, custom annotations, AOP aspects, and Vue front‑end integration.

Architect's Guide
Architect's Guide
Architect's Guide
Implementing Multi-Device Token Storage and Validation with Spring Boot, Redis, and Vue

Introduction: In a distributed microservice scenario, token validation and single sign‑on are needed for both PC and mobile clients.

Token storage entity: a LoginToken class with fields PcLoginToken , MobileLoginToken , LoginIP is stored in Redis.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginToken {
    private String PcLoginToken;
    private String MobileLoginToken;
    private String LoginIP;
}

Login service: generates token, stores it in Redis with a 7‑day expiry, and returns it to the client.

@Service
public class loginServiceImpl implements LoginService {
    @Autowired UserService userService;
    @Autowired RedisUtils redisUtils;
    @Override
    public R Login(LoginEntity entity) {
        // ... (core login logic, token generation, Redis storage)
    }
}

Enum BizCodeEnum defines response codes; custom exception classes handle login errors such as bad parameters, unknown login type, and token mismatch.

public class BadLoginParamsException extends Exception {
    public BadLoginParamsException() {}
    public BadLoginParamsException(String message) { super(message); }
}

Client‑side storage: a Vue component stores the token in localStorage with an expiration helper to automatically remove expired entries.

Storage.prototype.setExpire = (key, value, expire) => {
    let obj = { data: value, time: Date.now(), expire: expire };
    localStorage.setItem(key, JSON.stringify(obj));
};
Storage.prototype.getExpire = key => {
    let val = localStorage.getItem(key);
    if (!val) return null;
    val = JSON.parse(val);
    if (Date.now() - val.time > val.expire) { localStorage.removeItem(key); return null; }
    return val.data;
};

Token verification flow: the front‑end sends loginToken , userid , and loginType in request headers; the back‑end validates them via a custom @NeedLogin annotation and an AOP aspect.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedLogin { String value() default ""; }
public class VerificationAspect {
    @Autowired RedisUtils redisUtils;
    @Pointcut("@annotation(com.huterox.common.holeAnnotation.NeedLogin)")
    public void verification() {}
    @Around("verification()")
    public Object verification(ProceedingJoinPoint pjp) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String loginType = request.getHeader("loginType");
        String userid = request.getHeader("userid");
        String tokenUser = request.getHeader("loginToken");
        String tokenKey = RedisTransKey.getTokenKey(userid + ":" + loginType);
        if (tokenUser == null || userid == null || loginType == null) throw new BadLoginParamsException();
        if (!redisUtils.hasKey(tokenKey)) throw new NotLoginException();
        Object o = redisUtils.get(tokenKey);
        LoginToken loginToken = JSON.parseObject(o.toString(), LoginToken.class);
        if (loginType.equals(LoginType.PcType) && !loginToken.getPcLoginToken().equals(tokenUser))
            throw new BadLoginTokenException();
        if (loginType.equals(LoginType.MobileType) && !loginToken.getMobileLoginToken().equals(tokenUser))
            throw new BadLoginTokenException();
        return pjp.proceed();
    }
}

The controller methods annotated with @NeedLogin trigger the aspect, ensuring that only requests with a valid token stored in Redis can access protected PC or mobile endpoints, completing a secure token‑based authentication mechanism.

RedisVueAuthenticationSpringBootTokenAspect
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

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.