You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Shiro+Spring WebMvc:如何在控制器中最优获取当前登录用户?

在Spring WebMvc中用Apache Shiro获取已登录用户信息的最佳方式

1. 直接调用Shiro的SecurityUtils工具类

这是最直接的实现方式,在控制器方法里直接获取Subject对象,进而拿到用户信息:

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @GetMapping("/current-user")
    public Object getCurrentUser() {
        Subject currentUser = SecurityUtils.getSubject();
        // 获取登录用户名(若登录时以用户名作为Principal)
        String username = (String) currentUser.getPrincipal();
        
        // 若用户信息是自定义实体类,直接强转即可
        // CustomUser user = (CustomUser) currentUser.getPrincipal();
        
        return username;
    }
}
  • 优点:无需额外配置,上手快,适合简单场景。
  • 注意:未登录时currentUser.getPrincipal()会返回null,需自行判断登录状态。

2. 用@Autowired注入Subject(推荐)

通过Spring依赖注入获取Subject,比直接调用SecurityUtils更利于单元测试:

import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    private final Subject subject;

    @Autowired
    public UserController(Subject subject) {
        this.subject = subject;
    }

    @GetMapping("/current-user")
    public Object getCurrentUser() {
        if (subject.isAuthenticated()) {
            return subject.getPrincipal();
        }
        return "未登录";
    }
}
  • 优点:符合Spring依赖注入的设计理念,单元测试时可轻松Mock Subject对象。

3. 自定义参数解析器,直接在方法参数中获取用户信息

如果想让代码更简洁,可自定义参数解析器,让控制器方法直接接收用户实体:

步骤1:自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}

步骤2:实现HandlerMethodArgumentResolver

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(CurrentUser.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        Subject subject = SecurityUtils.getSubject();
        return subject.getPrincipal();
    }
}

步骤3:注册参数解析器到Spring MVC

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new CurrentUserArgumentResolver());
    }
}

步骤4:在控制器中使用

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

@RestController
public class UserController {

    @GetMapping("/current-user")
    public Object getCurrentUser(@CurrentUser CustomUser user) {
        // 直接拿到自定义用户实体,无需手动获取Subject
        return user.getUsername();
    }
}
  • 优点:代码最简洁,控制器方法专注业务逻辑,无需重复编写获取用户的代码。
  • 注意:要确保getPrincipal()返回的是自定义用户实体类,否则需在解析器中做类型转换。

4. 结合Shiro的@RequiresAuthentication注解

如果方法仅允许已登录用户访问,可先添加@RequiresAuthentication注解,再获取用户信息,确保进入方法时用户已登录:

import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    private final Subject subject;

    @Autowired
    public UserController(Subject subject) {
        this.subject = subject;
    }

    @GetMapping("/user/profile")
    @RequiresAuthentication
    public Object getUserProfile() {
        // 此时subject.isAuthenticated()一定为true,无需额外判断
        CustomUser user = (CustomUser) subject.getPrincipal();
        return user;
    }
}
  • 优点:自动拦截未登录请求,无需手动处理未登录场景,代码更安全。

内容的提问来源于stack exchange,提问作者Helge1977

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:37:32