千家信息网

SpringBoot怎么整合Shiro实现权限控制

发表于:2025-12-03 作者:千家信息网编辑
千家信息网最后更新 2025年12月03日,这篇文章主要介绍"SpringBoot怎么整合Shiro实现权限控制",在日常操作中,相信很多人在SpringBoot怎么整合Shiro实现权限控制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的
千家信息网最后更新 2025年12月03日SpringBoot怎么整合Shiro实现权限控制

这篇文章主要介绍"SpringBoot怎么整合Shiro实现权限控制",在日常操作中,相信很多人在SpringBoot怎么整合Shiro实现权限控制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"SpringBoot怎么整合Shiro实现权限控制"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1、SpringBoot整合Shiro

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。

1.1、shiro简介

shiro有个核心组件,分别为Subject、SecurityManager和Realms

  • Subject:相当于当前操作的"用户",这个用户不一定是一个具体的人,是一个抽象的概念,表明的是和当前程序进行交互的任何东西,例如爬虫、脚本、等等。所有的Subject都绑定到SecurityManager上,与 Subject 的所有交互都会委托给 SecurityManager;可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者。

  • SecurityManager:这个是shiro框架的核心,所有与安全相关的操作都会与它进行交互,它管理者所有的Subject。

  • Realms:充当了Shiro与应用安全数据间的"桥梁",当对用户执行认证(登录)和授权(访问控制)验证时,SecurityManager 需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作。

1.2、代码的具体实现

1.2.1、Maven的配置

              org.apache.shiro            shiro-spring-boot-starter            1.7.1                                      com.github.theborakompanioni            thymeleaf-extras-shiro            2.0.0                       org.apache.shiro            shiro-ehcache            1.7.1        

shiro默认是与jsp进行使用的,而这里是shiro整合thymeleaf所有要导入shiro整合thymeleaf的jar包

1.2.2、整合需要实现的类

  • 一般来说整合只需要完成两个类的实现即可

  • 一个是 ShiroConfig 一个是 CustomerRealm

  • 如果需要添加shiro缓存并且不是自带的缓存而是redis缓存还需要进行另外两个类的编写

  • 一个是 RedisCache 一个是 RedisCacheManager

1.2.3、项目结构

1.2.4、ShiroConfig的实现

未加shiro的缓存

package com.yuwen.config;import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;import com.yuwen.shiro.cache.RedisCacheManager;import com.yuwen.shiro.realm.CustomerRealm;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.realm.Realm;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.HashMap;import java.util.Map;@Configurationpublic class ShiroConfig {    //让页面shiro标签生效    @Bean    public ShiroDialect shiroDialect(){        return new ShiroDialect();    }    //1、创建shiroFilter   负责拦截所有请求    @Bean    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();        //给filter设置安全管理        factoryBean.setSecurityManager(defaultWebSecurityManager);        //配置系统的受限资源        //配置系统公共资源 全部都能访问的设置anon        Map map = new HashMap<>();        map.put("/main","authc");//请求这个资源需要认证和授权 authc表示需要认证后才能访问        map.put("/admin","roles[admin]"); //表示admin角色才能访问 roles[]表示需要什么角色才能访问        map.put("/manage","perms[user:*:*]"); //表示需要user:*:*权限才能访问 perms[]表示需要什么权限才能访问        //访问需要认证的页面如果未登录会跳转到/login路由进行登陆        factoryBean.setLoginUrl("/login");        //访问未授权页面会自动跳转到/unAuth路由        factoryBean.setUnauthorizedUrl("/unAuth");        factoryBean.setFilterChainDefinitionMap(map);        return factoryBean;    }    //2、创建安全管理器    @Bean    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("getRealm") Realm realm){        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();        //给安全管理器设置        securityManager.setRealm(realm);        return securityManager;    }    //3、创建自定义的realm    @Bean    public Realm getRealm(){        CustomerRealm customerRealm = new CustomerRealm();        //修改凭证校验匹配器        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();        //设置加密算法为md5        credentialsMatcher.setHashAlgorithmName("MD5");        //设置散列次数        credentialsMatcher.setHashIterations(1024);        customerRealm.setCredentialsMatcher(credentialsMatcher);        return customerRealm;    }}

因为一般在数据库中设置明文密码不安全,所有我这里对密码进行了md5加密,我的加密方式为:密码 = 密码+盐+散列次数 而后进行MD5加密 所以这里创建自定义的realm时需要进行设置匹配器这样登录时密码才能匹配成功

1.2.5、CustomerRealm的实现

package com.yuwen.shiro.realm;import com.yuwen.pojo.User;import com.yuwen.pojo.vo.ViewPerms;import com.yuwen.pojo.vo.ViewRole;import com.yuwen.service.UserService;import com.yuwen.shiro.salt.MyByteSource;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;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.apache.shiro.util.CollectionUtils;import org.springframework.util.ObjectUtils;import javax.annotation.Resource;import java.util.List;//自定义realmpublic class CustomerRealm extends AuthorizingRealm {    @Resource    private UserService userService; //授权    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        //获取身份信息        String primaryPrincipal = (String)principalCollection.getPrimaryPrincipal();        //根据主身份信息获取角色 和 权限信息        List roles = userService.findRolesByUsername(primaryPrincipal);        if (!CollectionUtils.isEmpty(roles)){            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();            roles.forEach(viewRole -> {                simpleAuthorizationInfo.addRole(viewRole.getName());                //权限信息                List perms = userService.findPermsByRoleId(viewRole.getName());                if (!CollectionUtils.isEmpty(perms)){                    perms.forEach(viewPerms -> {                        simpleAuthorizationInfo.addStringPermission(viewPerms.getPName());                    });                }            });            return simpleAuthorizationInfo;        }        return null;    }     //认证    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {        //获取登入的身份信息        String principal = (String) authenticationToken.getPrincipal();        User user = userService.findByUsername(principal);        if (!ObjectUtils.isEmpty(user)){            //ByteSource.Util.bytes(user.getSalt()) 通过这个工具将盐传入            //如果身份认证验证成功,返回一个AuthenticationInfo实现;            return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),new MyByteSource(user.getSalt()),this.getName());        }        return null;    }}

在登录时会自动调用这个身份验证 在验证时如果出错,会报异常,我在controller层接收了异常并处理

controller层中登录时的异常处理

@PostMapping("/login")    public String login(String username,String password){        //获取主体对象        Subject subject = SecurityUtils.getSubject();        try {         //自动调用CustomerRealm 类中的身份验证方法            subject.login(new UsernamePasswordToken(username,password));            return "index";        }catch (UnknownAccountException e){ //接收异常并处理            e.printStackTrace();            model.addAttribute("msg","用户名有误,请重新登录");        }catch (IncorrectCredentialsException e){//接收异常并处理            e.printStackTrace();            model.addAttribute("msg","密码有误,请重新登录");        }        return "login";    }

1.2.6、shiro缓存配置

定义了shiro缓存,用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效率

默认缓存的配置

在 ShiroConfig中 的 getRealm() 方法中开启缓存管理

 @Bean    public Realm getRealm(){        CustomerRealm customerRealm = new CustomerRealm();        //开启缓存管理        customerRealm.setCacheManager(new EhCacheManager());        //开启全局缓存        customerRealm.setCachingEnabled(true);        //开启认证缓存        customerRealm.setAuthenticationCachingEnabled(true);        customerRealm.setAuthenticationCacheName("authenticationCache");        //开启权限缓存        customerRealm.setAuthorizationCachingEnabled(true);        customerRealm.setAuthorizationCacheName("authorizationCache");        return customerRealm;    }

与reids整合的缓存这里就不说明了,放在源码里自己查看,源码在下方

1.2.7、主页index.html的设置

在这里用标签来判断某些区域需要认证或什么角色或者什么权限才能访问

        首页    

index

退出用户:

显示认证通过内容

没有认证时 显示

admin角色 显示

具有用户模块的"user:*:*"权限 显示

1.3、简单测试

1.3.1、admin角色所有权限测试

1.3.2、无角色有权限测试

1.3.3、无角色无权限测试


到此,关于"SpringBoot怎么整合Shiro实现权限控制"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

权限 缓存 用户 整合 角色 认证 身份 登录 安全 密码 管理 验证 信息 控制 配置 加密 处理 学习 测试 安全管理 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 文明校园网络安全手抄报图片 qq传送微云文件出现服务器繁忙 网络安全博弈论教材 修改数据库一个字段值 软件开发项目关键指标 网络安全最终不过是在对危险 怀柔区管理软件开发一体化 方舟生存进化老是连接服务器超时 大型小游戏服务器 行政法里有网络安全法吗 Java对数据库增量查询 宁波游戏软件开发创新服务 服务器购买后没启动 手机导航app软件开发 sql数据库主键怎么自动生成 您无法再安全服务器 车牌识别系统数据库索引清理 科技互联网观察家 学校网络安全工作体系建设 数据库完全恢复的步骤 软件开发的建立模板 硬件转码 服务器 中行x86服务器采购 博客系统的ER图和数据库 网络安全法 要求日志留存 王牌战争服务器描述错误 阿里云ecs服务器试用体验 计算机网络技术实习手册怎么填 学校网络安全工作体系建设 手机应用软件开发是啥
0