总结
SpringBoot与Shiro的整合为Java Web应用提供了强大的权限管理功能。Shiro是一个轻量级的安全框架,提供了认证、授权、加密和会话管理等功能。与Spring Security相比,Shiro更加简洁和易于使用。
在SpringBoot项目中,Shiro的集成主要涉及到配置安全管理器(SecurityManager)、自定义Realm、配置Filter以及编写相关的Controller和Service层代码。Realm是Shiro的核心组件之一,用于进行权限信息的验证,我们需要实现自己的Realm类来完成用户认证和授权的逻辑。
在权限管理方面,Shiro通过Subject对象来代表当前用户,并通过SecurityManager来管理所有的Subject。用户认证和授权的过程分别在Realm的doGetAuthenticationInfo和doGetAuthorizationInfo方法中实现。
代码实例
以下是一个简单的SpringBoot + Shiro权限管理的代码实例:
引入依赖
在pom.xml
文件中添加Shiro相关的依赖:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.7.0</version>
</dependency>
配置Shiro
创建一个Shiro配置类,用于配置SecurityManager和自定义Realm:
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map; @Configuration
public class ShiroConfig { @Bean public SecurityManager securityManager(MyRealm myRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myRealm); return securityManager; } @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setUnauthorizedUrl("/403"); Map<String, Filter> filters = new HashMap<>(); // 可以添加自定义的过滤器 shiroFilterFactoryBean.setFilters(filters); Map<String, String> filterChainDefinitionMap = new HashMap<>(); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/**", "authc"); ShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); chainDefinition.setChainDefinitionMap(filterChainDefinitionMap); shiroFilterFactoryBean.setFilterChainDefinitionMap(chainDefinition.getChainDefinitionMap()); return shiroFilterFactoryBean; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; }
}
自定义Realm
创建一个自定义的Realm类,用于实现用户认证和授权的逻辑:
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired; public class MyRealm extends AuthorizingRealm { @Autowired private UserService userService; // 假设有一个UserService用于查询用户信息 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String username = (String) principalCollection.getPrimaryPrincipal(); // 查询用户权限和角色 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); // 假设从数据库中查询到的角色和权限 authorizationInfo.addRole("role1"); authorizationInfo.addStringPermission("user:delete"); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; String username = token.getUsername(); // 查询用户信息 User user = userService.findByUsername(username); if (user == null) { throw new UnknownAccountException("用户不存在"); } // 返回验证信息 return new SimpleAuthenticationInfo(username, user.getPassword(), getName()); }
}
编写Controller层
创建一个简单的Controller用于处理登录请求和受保护的资源请求:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.*; @RestController
@RequestMapping("/api")
public class UserController { @PostMapping("/login") public String login(@RequestParam String username, @RequestParam String password) { Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subject.login(token); return "登录成功"; } catch (Exception e) { return "登录失败:" + e.getMessage(); } } @GetMapping("/protected") public String protectedResource() { Subject subject = SecurityUtils.getSubject(); if (subject.isAuthenticated()) { boolean hasRole = subject.hasRole("role1"); boolean hasPermission = subject.isPermitted("user:delete"); return "已认证,拥有role1角色:" + hasRole + ",拥有delete权限:" + hasPermission; } else { return "未认证"; } }
}
配置数据库和实体类
(假设你已经有了一个User实体类和一个UserService用于查询用户信息,这里不再赘述)
运行项目
配置好数据库连接和启动类后,运行SpringBoot项目。你可以通过POST请求访问/api/login
进行登录,然后通过GET请求访问/api/protected
来测试权限管理功能。