Spring Boot 整合 Shiro
1. Shiro 简介
- Apache Shiro 是一个强大的简单易用的 Java 安全框架,主要用来更便捷的认证、授权、加密、会话管理、与 Web 集成、缓存等;
- Shiro 使用起来小而简单;
- Shiro 依赖性低,不需要任何框架和容器,Shiro 不仅可以实现 Web 应用的权限管理,还可以实现 C/S 系统,分布式系统权限管理;
- Shiro 属于轻量框架。
2. Shiro 核心功能

1. 主要功能
Shiro 主要有三大功能模块:
- Subject:主体,代表了当前 “用户”;
- SecurityManager:安全管理器,管理所有 Subject,所有与安全有关的操作都会与 SecurityManager 交互,可以配合内部安全组件(类似于 SpringMVC 中的 DispatcherServlet);
- Realms:用于进行权限信息的验证,Shiro 从从 Realm 获取安全数据,可以把 Realm 看成 DataSource,即安全数据源,一般需要自己实现。
2. 细分功能
- Authentication:身份认证/登录,即账号密码验证,验证用户是不是拥有相应的身份;
- Authorization:授权,即角色或者权限验证,验证某个已认证的用户是否拥有某个权限;
- Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;
- Cryptography:加密,保护数据的安全性,如密码加密等;
- Web Support:Web 支持,可以非常容易的集成到 Web 环境;
- Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
- Concurrency:Shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
- Testing:提供测试支持;
- Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
- Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
3. Spring Boot 整合 Shiro 流程
-
导入依赖
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring-boot-web-starter --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.7.0</version> </dependency> -
实体类
使用 Lombok 来简化开发
/** * @author beastars */ @Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; private String perms; } -
根据用户名查询数据库
此处使用 Mybatis-plus 来帮助查询
使用 Mybatis-plus 需要在启动类上添加
@MapperScan("com.lzq.mapper")的注解,来扫描 Mapper 类UserMapper:
/** * @author beastars */ public interface UserMapper extends BaseMapper<User> { }UserService:
/** * @author beastars */ @Service public class UserService { @Autowired private UserMapper userMapper; /** * 使用 Mybatis-plus 提供的 QueryWrapper 来进行条件查询 * 根据用户名查询用户 */ public User queryUserByName(String name) { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name", name); return userMapper.selectOne(wrapper); } } -
自定义一个继承了 AuthorizingRealm 的自定义 Realm 用于查询用户的角色和权限信息并保存到权限管理器
/** * 自定义 Realm * * @author beastars */ public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; // 授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { // 拿到当前登录对象 Subject subject = SecurityUtils.getSubject(); User currentUser = (User) subject.getPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 设置当前用户的权限 info.addStringPermission(currentUser.getPerms()); return info; } // 认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // 获取 token UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken; // 从数据库中查询用户 User user = userService.queryUserByName(userToken.getUsername()); // 用户名认证 if (user == null) { // 如果不存在 return null; // 抛出 UnknownAccountException 异常 } // 获取当前用户 Subject subject = SecurityUtils.getSubject(); // 获取当前用户的 session 信息 Session session = subject.getSession(); // 将信息返回前端,实时显示数据 session.setAttribute("loginUser", user); // 密码认证,shiro来做,加密 // 此处第一个参数 user,可以将用户信息传入,就可以使用 SecurityUtils.getSubject() 来获取当前用户的信息了 return new SimpleAuthenticationInfo(user, user.getPwd(), ""); } } -
创建 ShiroConfig,将自定义 Realm、SecurityManager 和 Filter 工厂等注入到 Spring 容器中
/** * @author beastars */ @Configuration public class ShiroConfig { // 1.创建 Realm 对象,需要自定义类,将自己的验证方式加入容器 @Bean public UserRealm userRealm() { return new UserRealm(); } // 2.DefaultWebSecurityManager,权限管理,配置主要是Realm的管理认证 @Bean(name = "webSecurityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 关联 Realm securityManager.setRealm(userRealm); return securityManager; } // 3.ShiroFilterFactoryBean,Filter工厂,设置对应的过滤条件和跳转条件 @Bean(name = "shiroFilterFactoryBean") public ShiroFilterFactoryBean getShiroFilterFactoryBean( @Qualifier("webSecurityManager") DefaultWebSecurityManager securityManager ) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); // 关联 SecurityManager,设置安全管理器 bean.setSecurityManager(securityManager); // 添加 Shiro 的内置过滤器 /* anon:无需认证就可以访问 authc:必须认证了才能访问 user:必须拥有 记住我 功能才能用 perms:拥有对某个 资源 的权限才能访问 role:拥有某个角色权限才能访问 */ Map<String, String> filterMap = new LinkedHashMap<>(); // filterMap.put("/user/update", "anon"); // filterMap.put("/user/add", "authc"); // 授权,只有有user:add权限的用户才可以对user资源进行add操作 filterMap.put("/user/add", "perms[user:add]"); filterMap.put("/user/update", "perms[user:update]"); // 关联权限 bean.setFilterChainDefinitionMap(filterMap); // 设置登录路径 bean.setLoginUrl("/toLogin"); // 设置无权访问页面,当访问某个资源无权限时,就跳到这个路径 bean.setUnauthorizedUrl("/noAuth"); return bean; } } -
设置访问控制器
/** * @author beastars */ @Controller public class RouteController { @RequestMapping("/user/add") public String add() { return "user/add"; } @RequestMapping("/user/update") public String update() { return "user/update"; } @RequestMapping("/toLogin") public String toLogin() { return "login"; } @RequestMapping("/login") public String login(String username, String password, Model model) { // 获取当前用户 Subject Subject subject = SecurityUtils.getSubject(); // 封装用户的登录数据 UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { // 执行登录方法,如果登录成功没有异常,如果登陆失败抛出异常 subject.login(token); return "index"; } catch (UnknownAccountException e) { model.addAttribute("msg", "用户名不存在"); return "login"; } catch (IncorrectCredentialsException e) { model.addAttribute("msg", "密码错误"); return "login"; } } @RequestMapping("/noAuth") @ResponseBody public String unauthorized() { return "无权限访问"; } }
本文介绍了如何将 Apache Shiro 与 Spring Boot 整合,用于实现应用程序的安全管理。Shiro 是一个轻量级的 Java 安全框架,提供认证、授权、加密和会话管理功能。在 Spring Boot 中整合 Shiro,主要包括理解 Shiro 的核心功能,如 Subject、SecurityManager 和 Realm,然后通过配置 SecurityManager、自定义 Realm 并设置过滤器,实现用户登录验证和权限控制。

1835

被折叠的 条评论
为什么被折叠?



