Shiro 授权是指 Shiro 框架(Apache Shiro)中用于控制用户对系统资源(如网页、方法、文件等)访问权限的功能。它决定了已认证(通过身份验证)的用户是否被允许执行特定的操作或者访问特定的资源。简单来说,就是在用户身份被确认之后,进一步确定该用户能做什么。
核心概念:
- 权限(Permission)
- 权限是 Shiro 授权的核心元素。它代表了对系统资源的访问许可。例如,在一个文件管理系统中,“读取文件”“写入文件”“删除文件” 等都是不同的权限。权限可以用字符串来表示,如 “user:read” 表示用户模块的读取权限,这种字符串格式方便进行权限的定义、管理和验证。
- 角色(Role)
- 角色是一组权限的集合。比如,在一个公司管理系统中,“管理员” 角色可能包含 “员工信息管理”“部门信息管理”“薪资信息查看” 等一系列权限;而 “普通员工” 角色可能只有 “个人信息查看”“考勤打卡” 等权限。角色可以被看作是权限的一个分组,便于对用户进行权限分配。
Shiro 授权的实现过程:
- 首先,需要在 Shiro 配置中定义角色和权限。这可以通过编程方式(如在 Java 代码中使用 Shiro 的 API)或者通过配置文件(如 INI 文件、XML 文件等,具体取决于项目的设置)来完成。
- 当用户请求访问一个资源时,Shiro 会拦截这个请求。然后,它会根据用户的身份(通常是通过之前的身份验证过程获取的用户信息)来检查该用户是否具有访问这个资源所需的角色或者权限。
- 如果用户具有相应的授权,Shiro 会允许请求通过,资源将被正常访问;如果用户没有授权,Shiro 会阻止请求,并返回一个未授权的提示(如在 Web 应用中返回 403 Forbidden 错误页面)
1,配置shiro.ini
#对用户信息进行配置 [users] #用户账号密码 #配置规则:用户账号=密码,角色1,角色2 admin=123456,管理员 czkt=111111,客户经理 #对权限信息进行配置,基于角色配置 [roles] #角色和权限 #配置规则:角色名称=权限1,权限2,权限字符串可使用通配符配置 管理员=user:*,role:* #客户经理只能对用户进行列表和详细的查看操作 客户经理=user:list,user:view
2,授权测试
package com.bdqn.shiro; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.subject.Subject; import org.junit.Test; public class ShiroTest { @Test public void testShiro(){ //1创建Realm(安全数据源) //通过shiro.ini配置文件创建Realm IniRealm realm=new IniRealm("classpath:shiro.ini"); //2创建SecurityManager DefaultSecurityManager securityManager=new DefaultSecurityManager(); //注入创建的Realm(安全数据源) securityManager.setRealm(realm); SecurityUtils.setSecurityManager(securityManager); //3,操作Subject,进行认证 Subject subject=SecurityUtils.getSubject(); //封装一个令牌 UsernamePasswordToken token=new UsernamePasswordToken("admin","123456"); try { subject.login(token); } catch (AuthenticationException e) { System.out.println("认证异常"); e.printStackTrace(); } System.out.println("是否认证通过:"+subject.isAuthenticated()); //认证通过后,进行权限验证 System.out.println("是否为管理员角色"+subject.hasRole("管理员"));//判断是否为某个角色 System.out.println("是否能操作用户查看功能"+subject.isPermitted("user:view"));//判断是否拥有某个权限 //也可以使用check方法判断是否拥有某权限,但是失败的情况下会抛出UnauthorizedException异常 subject.checkPermission("user:view"); } }
SpringBoot+Shiro授权:
-
- 引入依赖
- 在 SpringBoot 项目中使用 Shiro,首先需要在项目的
pom.xml
文件中添加 Shiro 的依赖。通常会添加shiro - spring - boot - starter
依赖,这个依赖会自动帮我们配置 Shiro 的基本环境。例如:
- 在 SpringBoot 项目中使用 Shiro,首先需要在项目的
- 引入依赖
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro - spring - boot - starter</artifactId><version>1.7.1</version> </dependency>
- 配置 Shiro
- 可以通过创建一个
ShiroConfig
类来配置 Shiro。在这个类中,可以定义 Shiro 的安全管理器(SecurityManager)、过滤器链(FilterChain)等重要组件。例如,定义一个简单的安全管理器:
- 可以通过创建一个
@Configurationpublic class ShiroConfig {@Beanpublic SecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 可以在这里设置Realm等其他组件return securityManager;}}
- 授权实现步骤
- 定义 Realm(领域对象)
- Realm 是 Shiro 中用于进行认证和授权的数据源。在 SpringBoot + Shiro 中,需要创建一个自定义的 Realm 类,继承自
AuthorizingRealm
。这个类主要实现两个方法:doGetAuthenticationInfo
用于认证,doGetAuthorizationInfo
用于授权。例如:
- Realm 是 Shiro 中用于进行认证和授权的数据源。在 SpringBoot + Shiro 中,需要创建一个自定义的 Realm 类,继承自
- 定义 Realm(领域对象)
public class MyRealm extends AuthorizingRealm {@Autowiredprivate UserService userService;@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String username = (String) principals.getPrimaryPrincipal();User user = userService.findByUsername(username);SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();// 添加用户角色authorizationInfo.addRole(user.getRole());// 添加用户权限authorizationInfo.addStringPermission(user.getPermission());return authorizationInfo;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// 认证逻辑,这里省略详细代码return null;}}
- 配置 Realm 到 SecurityManager
- 在
ShiroConfig
类中,将自定义的 Realm 配置到安全管理器中。例如:
- 在
@Configurationpublic class ShiroConfig {@Beanpublic SecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(myRealm());return securityManager;}@Beanpublic MyRealm myRealm() {return new MyRealm();}}
- 在 Controller 或 Service 中进行授权检查
- 在 SpringBoot 的 Controller 或者 Service 层中,可以使用 Shiro 的 API 来进行授权检查。例如,在 Controller 方法中检查用户是否具有某个角色或者权限:
@RestControllerpublic class MyController {@GetMapping("/admin")@RequiresRoles("admin")public String adminPage() {return "This is the admin page.";}@GetMapping("/user/read")@RequiresPermissions("user:read")public String userReadPage() {return "This is the user read page.";}}
- 授权策略调整
- 基于注解的授权策略
- 除了上面使用的
@RequiresRoles
和@RequiresPermissions
注解外,还可以通过配置 Shiro 来调整这些注解的行为。例如,可以在ShiroConfig
类中配置全局的授权异常处理,当用户没有授权访问某个资源时,返回自定义的错误信息:
- 除了上面使用的
- 基于注解的授权策略
@Configurationpublic class ShiroConfig {@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(securityManager);return advisor;}}
- 自定义授权过滤器
- 可以创建自定义的授权过滤器来满足特定的业务需求。例如,创建一个过滤器来检查用户是否同时具有多个权限才能访问某个资源。首先创建一个自定义过滤器类,继承自
PathMatchingFilter
,然后在ShiroConfig
类中将其配置到过滤器链中。
- 可以创建自定义的授权过滤器来满足特定的业务需求。例如,创建一个过滤器来检查用户是否同时具有多个权限才能访问某个资源。首先创建一个自定义过滤器类,继承自
- 与数据库集成进行授权管理
- 通常情况下,用户的角色和权限信息是存储在数据库中的。在 SpringBoot + Shiro 中,可以通过在自定义的 Realm 类中注入数据访问层(如 JPA Repository 或者 MyBatis Mapper)来从数据库中获取用户的角色和权限信息。例如,在
MyRealm
类中注入UserRepository
来获取用户信息、角色信息和权限信息,以实现动态的授权管理,根据数据库中的数据实时更新用户的授权状态
- 通常情况下,用户的角色和权限信息是存储在数据库中的。在 SpringBoot + Shiro 中,可以通过在自定义的 Realm 类中注入数据访问层(如 JPA Repository 或者 MyBatis Mapper)来从数据库中获取用户的角色和权限信息。例如,在