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

Apache Shiro基本使用指南

文章目录

  • 前言
  • Shiro简介
    • Shiro的核心概念
  • 环境搭建
  • 快速入门示例
    • 1. 创建shiro.ini配置文件
    • 2. 编写测试代码
  • 自定义Realm
    • 创建shiro.ini配置文件
    • 创建自定义Realm类
    • 测试结果
  • 总结

前言

在Java Web开发中,安全框架的选择一直是开发者关注的重点。Spring Security功能强大但配置复杂,而Apache Shiro则以其简单易用、功能完整而受到广大开发者的喜爱。今天我们就来详细了解Shiro的基本使用,看看如何快速上手这个优秀的安全框架。

Shiro简介

Apache Shiro是一个功能强大且易于使用的Java安全框架,它可以帮助我们完成认证、授权、加密、缓存和会话管理等安全相关的功能。

Shiro的核心概念

  • Subject(主体):当前用户,不一定是具体的人,也可能是第三方服务
  • SecurityManager(安全管理器):Shiro的核心,协调各个组件工作
  • Realm(域):数据源,负责获取安全数据(用户、角色、权限)

环境搭建

首先,我们需要在项目中引入Shiro的相关依赖。以Maven项目为例:

<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- Shiro核心依赖 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.3.2</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency>
</dependencies>

快速入门示例

让我们从一个最简单的示例开始,了解Shiro的基本工作流程。

1. 创建shiro.ini配置文件

在resources目录下创建shiro.ini文件:

[users]
# 用户名=密码,角色1,角色2
zhang=123,admin
wang=456,user
li=789,user,manager[roles]
# 角色=权限1,权限2
admin=*
user=user:read,user:create
manager=user:*,order:read

2. 编写测试代码

public class ShiroQuickStart {public static void main(String[] args) {// 1. 获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManagerFactory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");// 2. 得到SecurityManager实例并绑定给SecurityUtilsSecurityManager securityManager = factory.getInstance();SecurityUtils.setSecurityManager(securityManager);// 3. 得到Subject及创建用户名/密码身份验证TokenSubject currentUser = SecurityUtils.getSubject();// 4. 登录if (!currentUser.isAuthenticated()) {UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");token.setRememberMe(true); try {currentUser.login(token);logger.info("用户登录成功");} catch (UnknownAccountException uae) {logger.error("用户不存在: " + token.getPrincipal());} catch (IncorrectCredentialsException ice) {logger.error("密码错误: " + token.getPrincipal());} catch (LockedAccountException lae) {logger.error("账户被锁定: " + token.getPrincipal());} catch (AuthenticationException ae) {logger.error("认证失败");}}// 5. 权限检查if (currentUser.hasRole("admin")) {logger.info("用户拥有admin角色");} else {logger.info("用户没有admin角色");}// 检查具体权限if (currentUser.isPermitted("user:create")) {logger.info("用户有创建用户的权限");} else {logger.info("用户没有创建用户的权限");}// 6. 退出登录currentUser.logout();}
}

自定义Realm

在实际项目中,我们通常需要从数据库获取用户信息,这时就需要自定义Realm。

创建shiro.ini配置文件

[main]
#声明realm
myClass = com.coldscholor.shiro.MyRealm
#注册realm到securityManager中
securityManager.realm = $myClass

创建自定义Realm类

/*** Realm域:Shiro从Realm获取安全数据(如用户、角色、权限),* 就是说SecurityManager要验证用户身份,那么它需要从Realm* 获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm* 得到用户相应的角色/权限进行验证用户是否能进行操作;可以把* Realm看成DataSource,即安全数据源* <p>* 自定义realms对象* 继承AuthorizingRealm* 重写方法* doGetAuthorizationInfo:授权* 获取到用户的授权数据(用户的权限数据)* doGetAuthenticationInfo:认证* 根据用户名密码登录,将用户数据保存(安全数据)*/
public class MyRealm extends AuthorizingRealm {public MyRealm() {// 设置密码匹配器HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);// 设置迭代次数matcher.setHashIterations(DigestsUtil.COUNTS);// 设置加密方式setCredentialsMatcher(matcher);}/*** 授权* @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("授权");// 获取用户名String username = (String) principalCollection.getPrimaryPrincipal();System.out.println("用户名:" + username);// 用户的权限数据List<String> perms = new ArrayList<>();perms.add("save");perms.add("update");perms.add("delete");perms.add("find");// 用户的角色数据List<String> roles = new ArrayList<>();roles.add("admin");roles.add("user");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.addStringPermissions(perms);info.addRoles(roles);return info;}/*** 认证** @param authenticationToken* @return* @throws AuthenticationException*//*@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("认证");UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;String username = token.getUsername();String password = new String(token.getPassword());if ("admin".equals(username) && "123456".equals(password)) {// 参数:用户名,密码,当前realm对象的名称SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());return info;} else {throw new RuntimeException("用户名或密码错误,认证失败");}}*//*** 对密文密码进行解密并认证* salt:是一个随机字符串,用于对密码进行加密* @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("认证");UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;String username = token.getUsername();SecurityService securityService = new SecurityServiceImpl();Map<String,String> map = securityService.findPasswordByLoginName(username);if(map == null){throw new RuntimeException("用户不存在");}String salt = map.get("salt");String password =  map.get("password");//参数1:安全数据   参数2:密码   参数3:混淆字符串  参数4:realm名称SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, ByteSource.Util.bytes(salt), getName());return info;}
}

测试结果

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
认证
登录结果:true

总结

Apache Shiro作为一个轻量级的安全框架,具有简单易用、功能完整的特点。在实际项目中,建议根据具体的业务需求选择合适的配置方式,并结合缓存、异常处理等机制,构建一个安全、高效的权限管理系统。Shiro虽然简单,但功能强大。掌握了这些基本用法,相信你已经能够在项目中熟练使用Shiro来处理安全相关的需求了。

http://www.dtcms.com/a/351600.html

相关文章:

  • 基于SpringBoot的社团管理系统【2026最新】
  • 《C++ Primer 第五版》initializer_list 涉及到的范围 for 循环(range-based for) 的语义差别
  • 车载铁框矫平机:把“钣金诊所”开到工地上
  • 【软考论文】论原型开发方法及其应用
  • Ubuntu 24.04 LTS 桌面版安装问题记录
  • 2025年8月27日,七月初五,生活指南
  • Python包管理与安装机制详解
  • pytorch-利用letnet5框架深度学习手写数字识别
  • 漫谈《数字图像处理》之霍夫变换发展历程与演进脉络
  • 类似ant design和element ui的八大Vue的UI框架详解优雅草卓伊凡
  • (vue)el-progress左侧添加标签/名称
  • C++学习(4)模板与STL
  • 虚幻5引擎:我们是在创造世界,还是重新发现世界?
  • 8.26 review
  • 【大前端】React统计所有网络请求的成功率、失败率以及统一入口处理失败页面
  • Ubuntu22.04安装OBS
  • 嵌入式系统学习Day23(进程)
  • 2025.8.26总结
  • 【系统架构设计(二)】系统工程与信息系统基础中:信息系统基础
  • 数据结构青铜到王者第四话---LinkedList与链表(1)
  • 【SystemUI】新增实体键盘快捷键说明
  • 【SystemUI】锁屏点击通知显示的解锁界面和通知重叠
  • [Sync_ai_vid] 唇形同步推理流程 | Whisper架构
  • 技术分享︱国产化突破:开源MDO工具链在新一代神威超算上的安装与调试
  • DevExpress WinForms中文教程:Data Grid - Excel样式的自定义过滤器对话框
  • 在Excel和WPS表格中输入分数的两种方法
  • 自然处理语言NLP: 基于双分支 LSTM 的酒店评论情感分析模型构建与实现
  • PostgreSQL快速入门
  • 会议室预约小程序主要功能及预约审批流程
  • Java大厂面试全解析:从Spring Boot到微服务架构实战