当前位置:首页 > 文章列表 > 文章 > java教程 > SpringBoot怎么整合Shiro实现权限控制

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

来源:亿速云 2024-04-02 20:12:37 0浏览 收藏

从现在开始,努力学习吧!本文《SpringBoot怎么整合Shiro实现权限控制》主要讲解了等等相关知识点,我会在golang学习网中持续更新相关的系列文章,欢迎大家关注并积极留言建议。下面就先一起来看一下本篇正文内容吧,希望能帮到你!

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、项目结构

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

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;
@Configuration
public 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;

//自定义realm
public 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

退出
    main | manage | admin
用户:

    显示认证通过内容
    没有认证时 显示
    admin角色 显示
    具有用户模块的"user:*:*"权限 显示

1.3、简单测试

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

1.3.1、admin角色所有权限测试

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

1.3.2、无角色有权限测试

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

1.3.3、无角色无权限测试

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

今天带大家了解了的相关知识,希望对你有所帮助;关于文章的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

版本声明
本文转载于:亿速云 如有侵犯,请联系study_golang@163.com删除
win7无法打开nvidia控制面板怎么办?win7打不开nvidia控制面板解决方法win7无法打开nvidia控制面板怎么办?win7打不开nvidia控制面板解决方法
上一篇
win7无法打开nvidia控制面板怎么办?win7打不开nvidia控制面板解决方法
linux arp有什么作用
下一篇
linux arp有什么作用
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • PPTFake答辩PPT生成器:一键生成高效专业的答辩PPT
    PPTFake答辩PPT生成器
    PPTFake答辩PPT生成器,专为答辩准备设计,极致高效生成PPT与自述稿。智能解析内容,提供多样模板,数据可视化,贴心配套服务,灵活自主编辑,降低制作门槛,适用于各类答辩场景。
    14次使用
  • SEO标题Lovart AI:全球首个设计领域AI智能体,实现全链路设计自动化
    Lovart
    SEO摘要探索Lovart AI,这款专注于设计领域的AI智能体,通过多模态模型集成和智能任务拆解,实现全链路设计自动化。无论是品牌全案设计、广告与视频制作,还是文创内容创作,Lovart AI都能满足您的需求,提升设计效率,降低成本。
    14次使用
  • 美图AI抠图:行业领先的智能图像处理技术,3秒出图,精准无误
    美图AI抠图
    美图AI抠图,依托CVPR 2024竞赛亚军技术,提供顶尖的图像处理解决方案。适用于证件照、商品、毛发等多场景,支持批量处理,3秒出图,零PS基础也能轻松操作,满足个人与商业需求。
    28次使用
  • SEO标题PetGPT:智能桌面宠物程序,结合AI对话的个性化陪伴工具
    PetGPT
    SEO摘要PetGPT 是一款基于 Python 和 PyQt 开发的智能桌面宠物程序,集成了 OpenAI 的 GPT 模型,提供上下文感知对话和主动聊天功能。用户可高度自定义宠物的外观和行为,支持插件热更新和二次开发。适用于需要陪伴和效率辅助的办公族、学生及 AI 技术爱好者。
    28次使用
  • 可图AI图片生成:快手可灵AI2.0引领图像创作新时代
    可图AI图片生成
    探索快手旗下可灵AI2.0发布的可图AI2.0图像生成大模型,体验从文本生成图像、图像编辑到风格转绘的全链路创作。了解其技术突破、功能创新及在广告、影视、非遗等领域的应用,领先于Midjourney、DALL-E等竞品。
    53次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码