Java研学-Shiro安全框架(四)

六 SpringBoot集成Shiro认证

1 分析

  Shiro提供认证授权功能,所以SpringBoot中不需再编写自定义注解,权限拦截,登录拦截,登录登出。Shiro 环境中有三个封装对象Subject ,SecurityManager和Realms,SpringBoot 集成 Shiro 时需要配置相对应的Bean(Subject 不用)
shiro认证

2 导入依赖

<properties><java.version>8</java.version><shiro.version>1.7.1</shiro.version><thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version>
</properties>
<!--Shiro核心框架 -->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>${shiro.version}</version>
</dependency>
<!-- Shiro使用Spring框架 -->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro.version}</version>
</dependency>
<!-- Shiro使用EhCache缓存框架 -->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>${shiro.version}</version>
</dependency>
<!-- thymeleaf模板引擎和shiro框架的整合 -->
<dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>${thymeleaf.extras.shiro.version}</version>
</dependency>

3 创建数据源

// 有类才能生成Bean
public class EmployeeRealm extends AuthorizingRealm {@Autowiredprivate IEmployeeService employeeService;@Autowiredprivate IPermissionService permissionService;@Autowiredprivate IRoleService roleService;//授权方法@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {Employee currentEmployee= (Employee) principalCollection.getPrimaryPrincipal();SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();if(currentEmployee.isAdmin()){List<Role> roles=roleService.listAll();for(Role role:roles){info.addRole(role.getSn());}info.addStringPermission("*:*");}else{List<Role> roleList=roleService.queryByEmployeeId(currentEmployee.getId());for(Role role:roleList){info.addRole(role.getSn());}//查询该用户的权限集合List<String> permissionList=permissionService.queryByEmployeeId(currentEmployee.getId());info.addStringPermissions(permissionList);}return info;}//认证方法@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {// 根据token获取用户名String username = (String) authenticationToken.getPrincipal();// 根据用户名查询用户Employee currentEmployee=employeeService.getByUsername(username);// 根据查询结果返回对应数据if(currentEmployee==null){return null;}return new SimpleAuthenticationInfo(currentEmployee,currentEmployee.getPassword(), ByteSource.Util.bytes(currentEmployee.getSalt()),getName());}
}

4 创建Shiro配置类

// 配置类注解
@Configuration
public class ShiroConfig {// 1.Realm 数据源从数据库中查询数据(先有Realm才能配置Bean,配置这个Bean需要先有这个类)// Bean一定是对象,对象不一定是Bean,对象需要基于类创建@Beanpublic EmployeeRealm employeeRealm(){EmployeeRealm realm = new EmployeeRealm();return realm;}// 2.SecurityManager 安全管理器(基于web环境下的)// 此处可用set调本类方法或传参的方式联系Realm    // 传参是在spring容器中查找这个Bean先类型再名字,去掉@Bean注解会报错(参数名与方法名尽量一致)// 调用方法首先不会运行该方法,会看方法的返回值类型,在容器中查找该类型,找到多个再按照名字去找,找到了就直接用// 不会运行该方法,若在容器中没找到该方法,就运行该方法并把返回值放到容器中,然后再拿过来用(无@Bean注解也行)@Beanpublic DefaultWebSecurityManager defaultWebSecurityManager(EmployeeRealm employeeRealm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(employeeRealm);return securityManager;}// 请求拦截器 shiro过滤器 由于创建麻烦此处使用工厂类创建过滤器对象// 若想知道一个工厂类返回什么类型的Bean 可查询其getObject()方法@Beanpublic ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();// 配置登录页面shiroFilterFactoryBean.setLoginUrl("/static/login.html");// 配置安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);// 配置拦截规则(过滤链) 底层为双链表组成(有序,就是我们放入的顺序,过滤器根据顺序执行)LinkedHashMap<String,String> filterChainDefinitionMap=new LinkedHashMap<>();// 对静态资源设置匿名访问(浏览器图标 html css js)放行filterChainDefinitionMap.put("/favicon.ico**","anon");filterChainDefinitionMap.put("/static/**","anon");// 不需拦截的访问(公共资源)放行filterChainDefinitionMap.put("/login","anon");// 退出并且shiro清除session信息(上下文对象也就是用户信息) 执行退出方法// 无需在再编写退出方法,直接调用logout即可踢回登陆页面filterChainDefinitionMap.put("/logout","logout");// 进行拦截filterChainDefinitionMap.put("/**","authc");// 将拦截规则设置给拦截器链(shiro生成了很多拦截器,看我们选用哪个)shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);// 此时无登录信息 访问任何页面都应该被踢回登录页面return shiroFilterFactoryBean;}
}

5 LoginController – 登录方法

  登录认证实际上是shiro在做,但数据需要在realm中提供

@Controller
public class LoginController {@RequestMapping("/login")@ResponseBodypublic JsonResult login(String username, String password){// 他会自动从Spring容器中拿到SecurityManager设置给SecurityUtils// 然后再将SecurityManager设置给subjectSubject subject = SecurityUtils.getSubject();// 将用户名密码封装到tokenUsernamePasswordToken token = new UsernamePasswordToken(username,password);// 此处返回异常不精确到某一项,防止有人试错(先试帐号再试密码)try {// 登录失败就抛异常subject.login(token);subject.getSession().setAttribute("user_in_session",subject.getPrincipal());} catch (UnknownAccountException e) {return new JsonResult(false,"账号密码有误");} catch (IncorrectCredentialsException e) {return new JsonResult(false,"帐号密码有误");} catch (Exception e) {return new JsonResult(false,"系统异常,稍后再试");}return new JsonResult(true,"登录成功");}
}

6 数据源查询方法(service) – getByUsername

// IEmployeeService
Employee getByUsername(String username);
// EmployeeServiceImpl
public Employee getByUsername(String username) {return employeeMapper.getByUsername(username);
}

7 数据源查询方法(mapper) – getByUsername

// mapper
Employee getByUsername(String username);
// xml
<select id="getByUsername" resultMap="BaseResultMap">select e.id, e.username, e.name, e.password, e.email, e.age, e.admin,d.id d_id,d.name d_name,d.sn d_sn,e.saltfrom employee e left join department d on e.dept_id = d.idwhere username=#{username}
</select>

8 shiro 内置过滤器

  shiro 启动时会默认将以下这些类(过滤器)加载到程序中,然后使用Map将这些数据的关系以key value的方式存储起来。

过滤器的名称(key)Java 类(value)
anonorg.apache.shiro.web. lter.authc.AnonymousFilter
authcorg.apache.shiro.web. lter.authc.FormAuthenticationFilter
authcBasicorg.apache.shiro.web. lter.authc.BasicHttpAuthenticationFilter
rolesorg.apache.shiro.web. lter.authz.RolesAuthorizationFilter
permsorg.apache.shiro.web. lter.authz.PermissionsAuthorizationFilter
userorg.apache.shiro.web. lter.authc.UserFilter
logoutorg.apache.shiro.web. lter.authc.LogoutFilter
portorg.apache.shiro.web. lter.authz.PortFilter
restorg.apache.shiro.web. lter.authz.HttpMethodPermissionFilter
sslorg.apache.shiro.web. lter.authz.SslFilter

anon: 匿名拦截器,即不需要登录即可访问(谁都可以访问,不需要拦截);一般用于静态资源过滤;示例“/static/**=anon”

authc: 表示需要认证(登录)才能使用,该路径所有请求都需登录后才能访问;示例“/**=authc”

authcBasic:Basic HTTP身份验证拦截器

roles: 角色授权拦截器,验证用户是否拥有资源角色;示例“/admin/**=roles[admin]”

perms: 权限授权拦截器,验证用户是否拥有资源权限;示例“/user/create=perms[“user:create”]”

user: 用户拦截器,用户已经身份验证/记住我登录的都可;示例“/index=user”

logout: 退出拦截器,登出后自动清理session中的用户信息。主要属性:redirectUrl:退出成功后重定向的地址(/);示例“/logout=logout”

port: 端口拦截器,主要属性:port(80):可以通过的端口;示例“/test= port[80]”,如果用户访问该页面是非80,将自动将请求端口改为80并重定向到该80端口,其他路径/参数等都一样

rest: rest风格拦截器;

ssl: SSL拦截器,只有请求协议是https才能通过;否则自动跳转会https端口(443);其他和port拦截器一样;

9 400错误问题解决

  当传入的参数 SpringMVC 无法转换时,就会出现400问题(第一次访问时出现),session是在浏览器第一次访问服务器时,由服务器创建并生成一个sessionID,通过response响应给浏览器。

  浏览器访问服务器时,服务器中有一个session池,当找到session后,将返回对应的JsessionID。

  但第一次访问时会首先经过shiro过滤器,其中有一个会话管理器(SessionManager),他发现当前是第一次访问,因此会进行一次URL重写,服务器会生成session并把sessionID返回给安全管理器,会话管理器通过重定向回到浏览器,再次发起申请访问服务器,此时第一次访问服务器实际上是没有访问到服务器,因此服务器无法接收携带的参数(JsessionID)报400错误。(去掉url中的JsessionID即可访问)

  第二次访问时,session已经存在,通过id寻找session,可以正常访问。或者告诉会话管理器,不需要做url重写,可在shiroconfig中生成会话管理器,将 setSessionIdUrlRewritingEnabled 设置为false即可(默认为true)。

@Configuration
public class ShiroConfig {// 略// 会话管理器@Beanpublic DefaultWebSecurityManager sessionManager(){DefaultWebSessionManager sessionManager=new DefaultWebSessionManager();// url重写开关sessionManager.setSessionIdUrlRewritingEnabled(false);return sessionManager;}
}

  此处需注意,编写好 sessionManager 会话管理器后,需要将其设置给 SecurityManager 安全管理器(通过参数)

@Configuration
public class ShiroConfig {// 略@Bean//安全管理器public DefaultWebSecurityManager defaultWebSecurityManager(EmployeeRealm employeeRealm, DefaultWebSessionManager sessionManager){// 创建安全管理器DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();// 设置realmsecurityManager.setRealm(employeeRealm);// 设置会话管理器securityManager.setSessionManager(sessionManager);return securityManager;}//会话管理器@Beanpublic DefaultWebSecurityManager sessionManager(){DefaultWebSessionManager sessionManager=new DefaultWebSessionManager();sessionManager.setSessionIdUrlRewritingEnabled(false);return sessionManager;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/44838.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java核心技术【二十一】Java的I/O流处理:文件的读写操作

Java的I/O流处理&#xff1a;文件读写操作 【创作】 不易&#xff0c;【点赞】 是情义&#xff0c;【关注】 是动力&#xff0c;【收藏】 是回忆。 示例代码地址&#xff1a;https://gitee.com/code-in-java/csdn-blog.git 在Java编程中&#xff0c;输入/输出&#xff08;I/O&a…

PyTorch实现BERT预训练模型转化指南

huggingface官方的介绍&#xff1a; https://huggingface.co/transformers/converting_tensorflow_models.html 直接用命令行 把箭头处路径改为自己放原有tf版本预训练模型的路径 回车后会有一大堆提示&#xff0c;然后发现路径下多了一个bin文件&#xff0c;加上原本的config…

顺序结构 ( 六 ) —— 顺序结构实例 【互三互三】

&#x1f680;欢迎互三&#x1f449;&#xff1a;程序猿方梓燚 &#x1f48e;&#x1f48e;&#x1f680;所属专栏&#xff1a;C教程&#x1f48e; &#x1f680;关注博主&#xff0c;后期持续更新系列文章 &#x1f680;如果有错误感谢请大家批评指出&#xff0c;及时修改 &am…

iNavFlight飞控固件学习-1《开发环境搭建》

目录 文章目录 目录摘要1.官网2.形成Linux开发环境工具2.1 简介2.2 相关工具2.2.1 Ubuntu / Debian系统配置命令2.2.2 Fedora系统配置命令2.2.3 Fedora系统配置命令 2.3 克隆存储库2.4 构建工具2.5 使用cmake2.6 构建固件2.7 清除2.8 cmake 缓存维护2.9 编译通过ninja2.10 更新…

红酒与未来科技:传统与创新的碰撞

在岁月的长河中&#xff0c;红酒以其深邃的色泽、丰富的口感和不同的文化魅力&#xff0c;成为人类文明中的一颗璀璨明珠。而未来科技&#xff0c;则以其迅猛的发展速度和无限的可能性&#xff0c;领着人类走向一个崭新的时代。当红酒与未来科技相遇&#xff0c;一场传统与创新…

ADI新型充电器解决方案可实现电池堆电压和充电效率

就目前而言&#xff0c;这可能是生活中zui常见的问题了。世纪之交&#xff0c;电池&#xff08;尤其是基于锂离子的电池&#xff09;成本的降低和性能的提高&#xff0c;推动了电池供电的储能和便携式设备的稳步增长。此外&#xff0c;超级电容器由于具有独特的性质&#xff0c…

骨传导耳机最热门好用款推荐,选购骨传导耳机前不能忽略的六大细节

如今的社会在耳机种类方面可以说是越来越多&#xff0c;于是很多人在挑选的时候往往选择不到适合自己的一款耳机&#xff0c;尤其是在近些年来席卷耳机市场的骨传导耳机&#xff0c;开放耳道的设计在很多时候佩戴无异于是更加的适合&#xff0c;正好小编这边对于比较热门的几款…

社交App iOS审核中的4.3问题:深入分析与解决策略

社交App审核中的4.3问题&#xff1a;深入分析与解决策略 在iOS应用开发和审核过程中&#xff0c;开发者经常会遇到苹果审核4.3问题。这一问题往往涉及应用的设计和内容重复性&#xff0c;导致应用被拒绝上架。为了帮助开发者更好地理解和解决这一问题&#xff0c;本文将对4.3问…

动漫3d模型设计需要注意什么?---模大狮模型网

设计动漫3D模型时&#xff0c;有几个方面需要注意&#xff1a; 保持角色风格一致性&#xff1a; 动漫通常有独特的风格和美学&#xff0c;设计时要确保模型与所代表的角色或作品的整体风格相符。注意保持线条和比例的一致性&#xff0c;使模型能够忠实地呈现原作的特点。 注重…

springboot餐饮管理系统-计算机毕业设计源码43667

摘 要 在信息化、数字化的时代背景下&#xff0c;餐饮行业面临着前所未有的挑战与机遇。为了提高运营效率、优化顾客体验&#xff0c;餐饮企业亟需一套高效、稳定且灵活的管理系统来支撑其日常运营。基于Spring Boot的餐饮管理系统应运而生&#xff0c;成为餐饮行业数字化转型的…

Python基础教学之一:入门篇——迈入编程世界的第一步

Python基础教学之一&#xff1a;入门篇——迈入编程世界的第一步 一、Python简介&#xff1a;历史与现状 Python&#xff0c;一种解释型、高级和通用的编程语言&#xff0c;由Guido van Rossum在1989年圣诞节期间创造&#xff0c;并于1991年首次发布。设计哲学强调代码的可读性…

论文降痕降重全攻略:从技巧到工具,助你轻松应对学术挑战

AIGC降重工具&#xff1a;快速降低论文查重率 高查重率是许多毕业生的困扰。通常&#xff0c;高查重率源于过度引用未经修改的参考资料和格式错误。传统的降重方法&#xff0c;如修改文本和增添原创内容&#xff0c;虽必要但耗时且成效不一。 鉴于此&#xff0c;应用AI工具进…

【企业级监控】源码部署Zabbix与监控主机

Zabbix企业级分布式监控 文章目录 Zabbix企业级分布式监控资源列表基础环境一、LNMP环境搭建&#xff08;在zbx主机上&#xff09;1.1、配置Yum仓库1.1.1、下载阿里云的仓库文件1.2.2、安装PHP7的仓库1.2.3、生成Mariadb10.11的仓库文件1.2.4、快速重建Yum缓存 1.2、安装PHP7.4…

请求取消(多种)

XMLHttpRequest XMLHttpRequest 可以使用 abort() 方法来实现请求取消。 const xhr new XMLHttpRequest();xhr.open(GET, http://localhost:3000/api/txt);xhr.timeout 2;xhr.ontimeout function () {xhr.abort();console.error(请求超时&#xff0c;已中断);};xhr.onload …

shell脚本之for循环

一、循环中的常见语句 1.1 echo 打印 -n &#xff1a;表示不换行输出-e &#xff1a;输出转义字符 \b &#xff1a;相当于退格键(backspace)\n &#xff1a;换行&#xff0c;相当于回车\f &#xff1a;换行&#xff0c;换行后的新行的开头连着上一行的行尾\t &#xff1a;插入…

Oracle 23ai 中的重要新特性 VECTOR 数据类型

Oracle 23ai 中的 VECTOR 数据类型是 Oracle 数据库在 AI 领域的一个重要新特性&#xff0c;它允许用户以向量的形式存储数据&#xff0c;并在这些向量的基础上进行高效的搜索和分析。以下是对 Oracle 23ai VECTOR 数据类型的详细解析&#xff1a; 参考官方文档地址 https://d…

【Ubuntu-18.04.6 LTS (Bionic Beaver)】串口无法root登录解决方案

root用户无法再窗口登录 用户界面登录提示 soory that didnot work 解决方案 GDM 配置 /etc/gdm3/custom.conf 中增加或删除注释 [security] AllowRoottrue重启服务 service gdm restart确认 PAM 配置 GDM 使用 PAM 进行认证&#xff0c;可能 PAM 配置中限制了 root 登录…

GitHub网页打开慢的解决办法

有时候看资料絮叨github网页打不开&#xff0c;经百度后&#xff0c;发下下面的方法有效。 1&#xff09;获取github官网ip 我们首先要获取github官网的ip地址&#xff0c;方法就是打开cmd&#xff0c;然后ping 找到github的地址&#xff1a;20.205.243.166 2&#xff09;配…

体验升级!贵州“森林之城”携苏州金龙新V系谱写高端旅运新篇章

自今年出台文旅“四免一多一减”方案以来&#xff0c;贵州省围绕旅游资源&#xff0c;着力打造亮点&#xff0c;不断提升产品供给水平&#xff0c;旅游市场持续火爆。近日&#xff0c;贵州森林之城旅运公司从苏州金龙批量采购50座海格新V系豪华大巴&#xff0c;为贵州高端旅游市…

域名系统DNS的工作原理和服务搭建

文章目录 域名解析和DNSDNS概念 DNS服务工作原理递归查询迭代查询递归和迭代的区别DNS缓存 DNS服务器的安装whoisDNS软件bind DNS主服务器实现1.在主配置文件中定义区域2.定义区域解析库文件各种资源类型解析库记录定义项 3.配置识别区域库文件4.重启named服务启用DNS客户端缓存…