Springboot2(23)轻松整合shiro(带验证码)

2023-11-16

源码地址

springboot2教程系列

Shiro配置

1.Spring集成Shiro一般通过xml配置,SpringBoot集成Shiro一般通过java代码配合@Configuration和@Bean配置。

2.Shiro的核心通过过滤器Filter实现。Shiro中的Filter是通过URL规则来进行过滤和权限校验,所以我们需要定义一系列关于URL的规则和访问权限。

3.SpringBoot集成Shiro,我们需要写的主要是两个类,ShiroConfiguration类,还有继承了AuthorizingRealm的Realm类。

  • ShiroConfiguration类,用来配置Shiro,注入各种Bean。包括过滤器(shiroFilter)、安全事务管理器(SecurityManager)、密码凭证(CredentialsMatcher)、aop注解支持(authorizationAttributeSourceAdvisor)等等
  • Realm类,包括登陆认证(doGetAuthenticationInfo)、授权认证(doGetAuthorizationInfo)

引入依赖

   <properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
		<shiro.version>1.4.0</shiro.version>
		<commons.lang.version>2.6</commons.lang.version>
		<kaptcha.version>0.0.9</kaptcha.version>
	</properties>


	<dependencies>

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>${shiro.version}</version>
		</dependency>

		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>${commons.lang.version}</version>
		</dependency>

		<dependency>
			<groupId>com.github.axet</groupId>
			<artifactId>kaptcha</artifactId>
			<version>${kaptcha.version}</version>
		</dependency>
		
    </dependencies>

编写ShiroConfiguration类

/**
 * Shiro的配置文件
 */
@Configuration
public class ShiroConfig {

    /**
     * Session会话管理器,session交给shiro管理
     */
    @Bean
    public DefaultWebSessionManager sessionManager(@Value("${myframe.sessionTimeout:3600}") long globalSessionTimeout){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        //是否开启会话验证器,默认是开启的
        sessionManager.setSessionValidationSchedulerEnabled(true);
        //禁止URL地标后面添加JSESSIONID
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        //设置全局会话超时时间
        sessionManager.setGlobalSessionTimeout(globalSessionTimeout * 1000);
        sessionManager.setSessionValidationInterval(globalSessionTimeout * 1000);
        return sessionManager;
    }


    /**
     * 安全管理器
     * @param userRealm
     * @param sessionManager
     * @return
     */
    @Bean("securityManager")
    public SecurityManager securityManager(UserRealm userRealm, SessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        securityManager.setRememberMeManager(null);
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }


    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        shiroFilter.setLoginUrl("/login.html");
        shiroFilter.setUnauthorizedUrl("/");

        Map<String, String> filterMap = new LinkedHashMap<>();

        filterMap.put("/public/**", "anon");
        filterMap.put("/login.html", "anon");
        filterMap.put("/sys/login", "anon");
        filterMap.put("/captcha.jpg", "anon");
        filterMap.put("/**", "authc");
        shiroFilter.setFilterChainDefinitionMap(filterMap);

        return shiroFilter;
    }

    /**
     * Shiro生命周期处理器,保证实现了Shiro内部lifecycle函数的bean执行
     * @return
     */
    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     *  启用shrio授权注解拦截方式,AOP式方法级权限检查
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }

    /**
     * 加入注解的使用,不加入这个注解不生效 使用shiro框架提供的切面类,用于创建代理对象
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

过滤器Filter实现

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean shiroFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new DelegatingFilterProxy("shiroFilter"));
        //该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
        registration.addInitParameter("targetFilterLifecycle", "true");
        registration.setOrder(Integer.MAX_VALUE - 1);
        registration.setEnabled(true);
        registration.addUrlPatterns("/*");
        return registration;
    }

}

Realm类实现

/**
 * 认证
 */
@Component
public class UserRealm extends AuthorizingRealm {
    @Resource
    private SysUserDao sysUserDao;
    
    /**
     * 授权(验证权限时调用)
     */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SysUserEntity user = (SysUserEntity)principals.getPrimaryPrincipal();
		Long userId = user.getUserId();
        //用户权限列表
		Set<String> permsSet = new HashSet<>();
		String perms = sysUserDao.queryAllPerms(userId);
		permsSet.addAll(Arrays.asList(perms.trim().split(",")));
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setStringPermissions(permsSet);
		return info;
	}

	/**
	 * 认证(登录时调用)
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken)authcToken;
		//查询用户信息
		SysUserEntity user = sysUserDao.selectOne(token.getUsername());
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
		return info;
	}

}

登录实现类

**
 * 登录相关
 */
@Controller
public class SysLoginController {
	@Autowired
	private Producer producer;

	/**
	 * 生成验证码
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping("captcha.jpg")
	public void captcha(HttpServletResponse response)throws IOException {
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");

        //生成文字验证码
        String text = producer.createText();
        //生成图片验证码
        BufferedImage image = producer.createImage(text);
        //保存到shiro session
        ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text);
        
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
	}
	
	/**
	 * 登录
	 */
	@ResponseBody
	@RequestMapping(value = "/sys/login", method = RequestMethod.POST)
	public R login(String username, String password, String captcha) throws IllegalAccessException {
		String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY);
		if(!captcha.equalsIgnoreCase(kaptcha)){
			return R.error("验证码不正确");
		}
		try{
			Subject subject = ShiroUtils.getSubject();
			UsernamePasswordToken token = new UsernamePasswordToken(username, password);
			subject.login(token);
		}catch (UnknownAccountException e) {
			return R.error(e.getMessage());
		}catch (LockedAccountException e) {
			return R.error("账号已被锁定,请联系管理员");
		} catch (IncorrectCredentialsException e) {
			return R.error("账号或密码不正确");
		}catch (AuthenticationException e) {
			return R.error("账户验证失败");
		}
		return R.ok();
	}
	
	/**
	 * 退出
	 */
	@RequestMapping(value = "logout", method = RequestMethod.GET)
	public String logout() {
		ShiroUtils.logout();
		return "redirect:login.html";
	}
	
}

权限测试类

@RestController
public class PermController {

    @RequestMapping("/sysRead")
    @RequiresPermissions("sys:read")
    public String sysRead(){
        return "you can sysRead";
    }

    @RequiresPermissions("sys:write")
    @RequestMapping("/sysWrite")
    public String sysWrite(){
        return "you can sysWrite";
    }

    @RequiresPermissions("sys:delete")
    @RequestMapping("/sysDelete")
    public String sysDel(){
        return "you can sysDelete";
    }
}

每次访问带有@RequiresPermissions()方法时,都会进入UserRealm类的AuthorizationInfo()授权方法

另外subject.hasRole(“admin”) 或 subject.isPermitted(“admin”) 也会调用AuthorizationInfo()授权方法

登录测试(用户密码tom/123456)
在这里插入图片描述

权限测试
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Springboot2(23)轻松整合shiro(带验证码) 的相关文章

  • Shiro学习笔记。

    授权需要继承 AuthorizingRealm 类 并实现其 doGetAuthorizationInfo 方法 AuthorizingRealm 类继承自 AuthenticatingRealm 但没有实现 AuthenticatingR
  • Springboot2(27)集成netty实现反向代理(内网穿透)

    源码地址 springboot2教程系列 其它netty文件有博客 Springboot2 24 集成netty实现http服务 类似SpingMvc的contoller层实现 Springboot2 25 集成netty实现文件传输 Sp
  • SpringBoot+Shiro实现免密登录

    1 自定义登录认证规则 import org apache shiro authc UsernamePasswordToken public class EasyUsernameToken extends UsernamePasswordT
  • 非常简单的无闪刷新验证码原理

    非常简单的无闪刷新验证码原理 只有这一段事件触发语句全搞定 nclick this src GifCode asp newDate getTime GifCode asp验证码的图片 事件 nclick this src GifCode a
  • Shiro之@RequiresPermissions注解原理详解

    前言 shiro为我们提供了几个权限注解 如下图 这几个注解原理都类似 这里我们讲解 RequiresPermissions的原理 铺垫 第一 首先要清楚 RequiresPermissions的基本用法 就是在Controller的方法里
  • Shiro权限框架-限制密码重试次数(8)

    1 实现原理 保证原子性 单系统 AtomicLong计数 集群系统 RedissionClient提供的RAtomicLong计数 1 获取系统中是否已有登录次数缓存 缓存对象结构预期为 用户名 登录次数 2 如果之前没有登录缓存 则创建
  • Shiro学习小记--身份验证得到principals

    项目使用shiro进行权限管理 Shiro国内目前资料极少 学习时完全就是根据张开涛的 跟我学Shiro 自己去摸索的 慢慢的开始入门 Shiro中有一个概念是principals 解释如下 principals 身份 即主体的标识属性 可
  • shrio验证cookie有效性

    shrio验证cookie有效性 概述 shrio中提供cookie管理的功能 当用户选择了rememberMe 则下次不需要再登录 而是直接通过本地记录的cookie进行验证 然后就可以访问权限为user的页面 问题 shiro提供清除用
  • springboot使用shiro的@Requiresroles注解不起作用(解决方法)

    看shiro的视频发现 Requiresroles不生效 解决方法 spring容器中 Bean public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator DefaultAd
  • Jeesite开发平台限制用户多点登录

    Jeesite开发平台限制用户多点登录 授权查询回调函数 进行鉴权但缓存中无用户的授权信息时调用 Override protected AuthorizationInfo doGetAuthorizationInfo PrincipalCo
  • 源码分析shiro认证授权流程

    1 shiro介绍 Apache Shiro是一个强大易用的Java安全框架 提供了认证 授权 加密和会话管理等功能 认证 用户身份识别 常被称为用户 登录 授权 访问控制 密码加密 保护或隐藏数据防止被偷窥 会话管理 每用户相关的时间敏感
  • shiro框架---关于用户登录退出接口的介绍

    接上一篇文章shiro框架 shiro配置用户名和密码的注意 项目已分享到GitHub上 如果需要的可以看下 springboot shiro项目Git下载地址 在我前几篇文章里有shiro配置的文件下载包 下载后里边有四个配置文件Shir
  • 在微服务项目中,Spring Security 比 Shiro 强在哪?

    Spring Security 和Shiro的区别
  • 无法自动装配字段:无法连接到 com.sun.proxy.$Proxy22

    Caused by org springframework beans factory BeanCreationException Could not autowire field protected com cms service Fol
  • Spring MongoDB 和 Apache Shiro

    我正在尝试将 Apache Shiro 与 Spring 和 MongoDB 结合使用 我正在使用自动连接的 Spring 数据存储库 我为 Shiro 创建了自己的自定义领域 它使用 Spring 数据存储库与 Mongo 进行通信 pu
  • Java – 高效、数据库感知的实例级授权?

    在 JPA 应用程序中 我有一个场景 其中该应用程序是 列出给定用户有权提款的所有帐户 我有帐户实体和一个多对多表 其中列出了每个用户对每个帐户拥有的授权 为了实现上述场景 应用程序当前只是内部联接两个表 这非常快 现在 我计划添加一个显式
  • 使用 Shiro 登录后重定向到最后访问的页面

    使用 apache shiro 登录并重定向到最后访问的页面的更好方法是什么 我只有这个 SecurityUtils getSubject login new UsernamePasswordToken username password
  • 使用 ini 文件进行 Spring MVC 和 Shiro 配置

    我正在尝试使用 Spring MVC 和 Apache Shiro 建立一个环境 我正在关注 shiro apache org 中提到的文章 我在 web xml 中使用 Spring 的 DelegatingFilterProxy 作为
  • Shiro 与 SpringSecurity [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我目前正在评估基于Java的安全框架 我是Spring 3 0用户 因此SpringSecurity似乎是正确的选择 但Spring安全性似乎过
  • 配置 shiro.ini 以进行 JDBC 连接

    作为我新的一年学习新技术计划的一部分 我开始尝试使用 Apache Shiro 安全框架 我设法让基本示例正常工作 该示例将用户名 密码和角色存储在 shiro ini 文件中 但是当我修改 shiro ini 文件以使用 JDBC 时 它

随机推荐

  • 上帝之眼Nmap(黑客工具)简介及命令大全

    目录 前言 一 Nmap简介 1 1 Nmap优点 1 2 Nmap四项基本功能 二 Nmap常用命令 2 1 主机发现 2 2 扫描技术 2 3 端口规格和扫描顺序 2 4 服务 版本探测 2 5 脚本扫描 2 6 操作系统检测 2 7
  • 95、Image Restoration with Mean-Reverting Stochastic Differential Equations

    简介 主页 https github com Algolzw image restoration sde 扩散模型终于在去噪 超分辨率等应用了 这是一种基于随机微分方程的通用图像恢复方法 关键结构包括均值还原SDE 该SDE将高质量图像转换
  • 机会转瞬即逝刷脸看准目标把握未来

    所有的企业家 不仅仅要考虑全球化让我受益 而是要让全球化变得更加普惠 让更多的人 更多的企业受益 鼓励并且帮助更多企业参与全球竞争 全球贸易 贸易战是为昨天而战或者为昨天的利益而战 我们今天要思考的 不是怎么去维护或者保护昨天 而是应该赢得
  • Java-获取时间戳、util.Date、sql.Date类的使用

    Java 获取时间戳 util Date sql Date类的使用 1 获取时间戳 获取系统当前时间 System类中的currentTimeMillis package com lmw time import org junit Test
  • 不定量表达法

    文章目录 1 some 一些 any 一些 most 大多数 every 每一个 all 所有的 2 both 两者都 either 两者之一 neither 两者都不 3 many 许多 much 许多 a lot of lots of
  • eclipse之 Type Hierachy:Viewing the type hierarchy

    1 Type Hierachy 继承关系层次图快捷键F4 2 show the type hierachy 子面板会根据选中的类显示对应的内容 show the supertype hierachy ctrl T 显示子类到父类的层次关系
  • Qt知识笔记(一)

    Qt知识笔记 一 Qt概述 Qt特点 Qt模块 Qt窗口类 坐标体系 相对坐标 垃圾回收机制 Qt概述 Qt是一个跨平台的 C 应用程序开发框架 具有短平快的优秀特质 投资少 周期短 见效快 效益高 几乎支持所有的平台 可用于桌面程序开发以
  • LVS负载均衡群集——LVS-NAT模式搭建和LVS-DR模式搭建

    目录 lvs工作模式 1 NAT模式 VS NAT 2 直接路由模式 VS DR 3 IP隧道模式 VS TUN LVS调度算法 LVS群集类型 1 负载均衡群集 LB 2 高可用群集 HA 3 高性能运输群集 HPC LVS NAT模式搭
  • element-ui + sortable.js 实现可拖拽表格

    element ui sortable js 实现可拖拽表格 先看效果 安装Sortablejs npm install sortablejs save demo
  • VC++ 源码实现通达信公式管理器2

    前面我们介绍了如何加载显示公式列表 本篇章介绍如何格式化显示公式内容 常用的CEdit或CRichEdit是不支持这种格式显示的 这里需要借助第三方控件SciLexer 没错 Notepad 就是使用的这个控件 它支持不同的文本内容支持不同
  • 基于多动作深度强化学习的柔性车间调度研究(Python代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 文献来源 4 Python代码实现 1 概述 灵活作业车间调度问题 FJSP 在现代制造
  • 三维建模软件Cinema 4D 2024 mac(c4d2024)中文版特点

    Cinema 4D 2024 mac是一款专业的三维建模 动画和渲染软件 c4d2024 可以用于电影制作 广告设计 工业设计等领域 Cinema 4D 2024具有强大的建模工具 可以创建各种复杂的几何体 包括多边形网格 NURBS曲线和
  • arctan函数加上90°;arctan(a/b)与arctan(b/a)的关系

  • 隐藏设备管理器控件

    include
  • cocos学习笔记---Node 支持的事件类型

    Node 支持的事件类型主要有 export enum EventType 触摸事件 TOUCH START 0 当手指触点落在目标节点区域内时 TOUCH MOVE 0 当手指在屏幕上目标节点区域内移动时 TOUCH END 0 当手指在
  • 建立统计回归模型的基本步骤_基本回归模型

    建立统计回归模型的基本步骤 Linear Regression and Regression Trees 线性回归和回归树 by Satoru Hayasaka and Rosaria Silipo KNIME 由 悟早坂 和 罗萨丽娅Si
  • 如何在Latex中插入MATLAB代码

    最近在编写一篇文章时需要用到在latex中插入MATLAB代码 如果直接在文本中添加会使文章变得不美观 那么此时我们非常有必要了解一下如何在latex中插入优美的MATLAB代码 1 复制mcode std文件在latex目录里 通常情况下
  • MAC上安装LLVM+Clang

    MAC上安装LLVM Clang 折腾了一天的结果 感觉不把它写下来都对不住自己了 哭唧唧 参考资料 http clang llvm org get started html http blog csdn net shuaiby artic
  • vue中将base64流数据转成pdf文件可打印

    vue中将base64流数据转成pdf文件可打印 vue中将base64流数据转成pdf文件可打印 一 base编码转为pdf方法 二 打印方法 vue中将base64流数据转成pdf文件可打印 这次后端返参不是oss那边传回来的 而是传给
  • Springboot2(23)轻松整合shiro(带验证码)

    源码地址 springboot2教程系列 Shiro配置 1 Spring集成Shiro一般通过xml配置 SpringBoot集成Shiro一般通过java代码配合 Configuration和 Bean配置 2 Shiro的核心通过过滤