当前位置: 首页 > news >正文

shiro的SecurityUtils.getSubject() 使用说明

SecurityUtils.getSubject() 是 Apache Shiro 框架中获取当前用户安全上下文(Subject)的核心方法。这个方法允许你在应用的任何地方访问当前用户的认证状态、权限信息和执行安全操作。

一、SecurityUtils.getSubject() 作用

Subject 代表当前与应用交互的用户:

  • 对于 Web 应用,通常是一个 HTTP 请求的会话
  • 包含用户的身份信息(如用户名、角色)
  • 提供认证(登录 / 登出)和授权(权限检查)方法
  • 可以存储会话数据(类似 HttpSession

二、核心方法与用法

1. 获取当前用户的 Subject

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;// 在任何地方获取当前用户的Subject
Subject currentUser = SecurityUtils.getSubject();

2. 认证操作(登录 / 登出)

// 登录
UsernamePasswordToken token = new UsernamePasswordToken("username", "password");
try {currentUser.login(token); // 验证用户名密码System.out.println("登录成功");
} catch (AuthenticationException e) {System.out.println("登录失败: " + e.getMessage());
}// 登出
currentUser.logout(); // 清除身份信息和会话

3. 授权操作(权限检查)

// 检查是否有角色
boolean hasAdminRole = currentUser.hasRole("admin");// 检查是否有权限
boolean canEdit = currentUser.isPermitted("user:edit");// 强制权限检查(无权限时抛出异常)
currentUser.checkPermission("user:delete");

4. 获取用户身份信息

// 获取主身份(通常是用户名或用户ID)
Object principal = currentUser.getPrincipal(); // 返回在Realm中认证时设置的principal// 判断用户是否已认证(通过登录验证)
boolean isAuthenticated = currentUser.isAuthenticated();// 判断用户是否通过"记住我"功能登录
boolean isRemembered = currentUser.isRemembered();

5. 会话操作

// 获取会话(类似HttpSession,但与Servlet无关)
Session session = currentUser.getSession();
session.setAttribute("key", "value"); // 存储会话数据
Object value = session.getAttribute("key");

三、在 Web 应用中的使用场景

1. Controller 中获取当前用户

@RestController
@RequestMapping("/api")
public class UserController {@GetMapping("/user/info")public ResponseEntity<UserInfo> getUserInfo() {Subject currentUser = SecurityUtils.getSubject();String username = (String) currentUser.getPrincipal(); // 获取用户名// 根据用户名查询用户信息UserInfo userInfo = userService.getUserInfo(username);return ResponseEntity.ok(userInfo);}
}

2. 自定义 Realm 中验证用户

public class MyRealm extends AuthorizingRealm {// 授权方法@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();String username = (String) principals.getPrimaryPrincipal();// 根据用户名查询角色和权限Set<String> roles = userService.getRoles(username);Set<String> permissions = userService.getPermissions(username);info.setRoles(roles);info.setStringPermissions(permissions);return info;}// 认证方法@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {UsernamePasswordToken upToken = (UsernamePasswordToken) token;String username = upToken.getUsername();// 查询用户信息User user = userService.getUserByUsername(username);if (user == null) {throw new UnknownAccountException("用户不存在");}// 返回认证信息(用户名、密码哈希、盐值)return new SimpleAuthenticationInfo(user.getUsername(), // 主身份user.getPassword(), // 密码(已加密)ByteSource.Util.bytes(user.getSalt()), // 盐值getName() // Realm名称);}
}

在密码学和信息安全领域,“盐值”(Salt)有一些常见的同义或近似概念,不同场景下可能会使用不同的名称,主要包括:

  • :最简洁的简称,与 “盐值” 含义完全一致,在技术文档中更常用(例如 “给密码加盐”)。
  • 随机盐:强调盐值的随机性,突出其 “随机生成” 的特性(例如 “每个用户密码需对应一个随机盐”)。
  • 加密盐:在加密场景中使用时的称呼,强调其用于增强加密 / 哈希安全性的作用。
  • 盐字符串:因盐值通常以字符串形式存储或处理,有时会明确其数据类型(例如 “将盐字符串与密码拼接后哈希”)。

四、常见问题与注意事项

1. 在非 Web 环境中使用

  • Shiro 默认通过 ThreadContext 绑定 Subject 到当前线程
  • 在多线程环境中需要手动传递 Subject(使用 Subject.associateWith()

2. NullPointerException 问题

  • 如果在 Shiro 初始化前调用 SecurityUtils.getSubject(),可能返回空
  • 确保 Shiro 过滤器链已正确配置(如 Spring Boot 中的 ShiroFilterFactoryBean

3. 与 Spring Boot 集成

  • 在 Spring Boot 中,通常通过 @Autowired 注入 SecurityManager 而不是直接使用 SecurityUtils
  • 但 SecurityUtils.getSubject() 仍然可用,且更简洁

4. RememberMe 功能

  • 如果用户通过 "记住我" 登录,isRemembered() 返回 true,但 isAuthenticated() 返回 false
  • 在需要强认证的场景(如支付),建议检查 isAuthenticated()
  • 用户在关闭浏览器后仍然保持登录状态,直到会话过期或手动注销。

五、总结

SecurityUtils.getSubject() 是 Shiro 的核心 API,提供了:

  • 用户认证(登录 / 登出)
  • 权限检查(角色 / 权限验证)
  • 会话管理
  • 身份信息获取

合理使用这个方法,可以在应用的任何层次(Controller、Service、工具类)安全地访问当前用户信息,实现细粒度的权限控制。

六、一点说明

1)RememberMe失效,不一定是配制的问题。

2)启用的时候报Bean 'rememberMeManager' of type [org.apache.shiro.web.mgt.CookieRememberMeManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)也不一定是失败的原因。

Bean 'userRealm' of type [xxx.xxxx.config.UserRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
21:20:56.716 [restartedMain] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'rememberMeManager' of type [org.apache.shiro.web.mgt.CookieRememberMeManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
21:20:56.731 [restartedMain] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'securityManager' of type [org.apache.shiro.web.mgt.DefaultWebSecurityManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
21:20:56.750 [restartedMain] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'authorizationAttributeSourceAdvisor' of type [org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

上面的提示并不会影响我们正常的运行。

3)根本原因:map.put("/**", "authc"); 所有的用户一定要通过登录页面进行认证后才可以导致。

将上面的authc改成user,就可以成功通过RememberMe的用户关了浏览器,再次打开以后也可以成功的打开首页。

这样可能会导致一些安全问题,所以还是建议,关了浏览器就要求再次登录系统。


文章转载自:
http://cineast .hdqtgc.cn
http://andron .hdqtgc.cn
http://sandhiller .hdqtgc.cn
http://tristful .hdqtgc.cn
http://leone .hdqtgc.cn
http://lucas .hdqtgc.cn
http://kazoo .hdqtgc.cn
http://telome .hdqtgc.cn
http://nubilous .hdqtgc.cn
http://puny .hdqtgc.cn
http://ecosystem .hdqtgc.cn
http://biologist .hdqtgc.cn
http://glare .hdqtgc.cn
http://buckshot .hdqtgc.cn
http://relieve .hdqtgc.cn
http://thiram .hdqtgc.cn
http://diesel .hdqtgc.cn
http://fetterbush .hdqtgc.cn
http://gnesen .hdqtgc.cn
http://estivation .hdqtgc.cn
http://fucose .hdqtgc.cn
http://glass .hdqtgc.cn
http://gigameter .hdqtgc.cn
http://unworthiness .hdqtgc.cn
http://despoil .hdqtgc.cn
http://sieve .hdqtgc.cn
http://heliolatry .hdqtgc.cn
http://beauteous .hdqtgc.cn
http://rusty .hdqtgc.cn
http://livetrap .hdqtgc.cn
http://www.dtcms.com/a/293704.html

相关文章:

  • 【按下电源键后,电脑里发生了什么?——BIOS:启动世界的“第一把钥匙”】
  • AI产品经理面试宝典第49天:智能客服、教育产品与医疗应用设计题相关解析
  • 深入解析Sqoop数据导入的并行切分机制与主键分区算法
  • AM1.5G AAA稳态太阳光模拟器特点
  • 西安电子科技大学金融学431考研经历分享
  • VSCode 开发 STM32 - clangd 带来的极致补全体验
  • FastAdmin 中生成插件
  • Python笔记之跨文件实例化、跨文件调用、导入库
  • 算法竞赛备赛——【图论】拓扑排序
  • PAT 甲级题目讲解:1002《A+B for Polynomials》
  • 二分查找----2.搜索二维矩阵
  • (13)机器学习小白入门YOLOv:YOLOv8-cls中用TensorBoard实时监控指标
  • 深入浅出理解 Reactor:响应式编程的利器​
  • Github上传文件流程图
  • Docker 应用数据备份、迁移方案
  • Redis原理之分布式锁
  • 武德物业和浑元科技-《软件方法》第2章业务建模之愿景03
  • Oracle物化视图详解
  • 计算机网络第四章(4)——网络层《无分类编址CIDR、路由聚合》
  • ESP32-CAM实战:DIY基于OpenAI的AI视觉识别相机
  • 校园后勤服务平台小程序的设计与实现
  • Android埋点实现方案深度分析
  • 新手向:Idea的使用技巧
  • Android 架构演进:从 MVC 到 MVVM 的设计之道
  • SpringCloud seata全局事务
  • python在windows电脑找回WiFi密码
  • LinkedList的模拟实现+LinkedList和ArrayList的区别
  • 使用 Maven 的 `maven-assembly-plugin` 插件打包zip
  • UE5实现NPC头部朝向玩家功能
  • 旧手机部署轻量级服务器