Springboot整合shiro基于url身份认证和授权认证
你还不会shiro吗?
- 前奏
- shiro核心配置文件(rolesFilter可选)。
- 身份认证
- 多表登录源如何操作?
- 授权管理
- 如何解决界面多角色/资源问题
- 访问效果
权限管理在日常开发中很重要,所以硬着头皮也要啃下来。
实现功能:
- 身份认证
- 对不同页面进行url授权
- 多表登录解决
- 同一个页面多role访问
项目完整github地址 欢迎star
springboot一些学习整合完整地址
shiro的四大组件:
- 身份认证(Authentication)-证明用户身份,通常叫做登陆(login)。
- 授权(Authorization)-访问控制
- 加密(Cryptography)-保护或隐藏数据
- 会话管理(session management)每个用户时间敏感状态
三个核心组件:Subject, SecurityManager 和 Realms.
- Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。 - SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
- Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。 - Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。
Shiro内置过滤器,可以实现权限相关的拦截器
常用的过滤器:
anon: 无需认证(登录)可以访问
authc: 必须认证才可以访问
user: 如果使用rememberMe的功能可以直接访问
perm: 该资源必须得到资源权限才可以访问
role: 该资源必须得到角色权限才可以访问
这里面只用到了身份认证和授权,权限认证只用到了一点点,shiro的原理是封装的过滤器,他能够在访问浏览器前能过自动完成一些内容。
shiro配置主要两部分——shiroconfig和自定义的Realm(继承AuthorizingRealm)
。其中,shiroconfig是shiro的主要配置文件,而自定义的Realm主要是重写AuthorizingRealm
的两个方法,分别是身份认证和授权认证调用数据库查询比对。而如果需要role访问则需要重写一个filter。
前奏
项目结构:
环境:
- Springboot2
- mybatis
- shiro
新建表:
对应的bean:
package com.shiro.bean;public class student {private String username;private String password;private String role;private String perm;//省略get set
mybatis简单查询:
package com.shiro.mapper;import com.shiro.bean.student;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface studentMapper {@Select("select * from student where username=#{name}")student findByName(String name);
}
省略html和sql,详细可以到GitHub下载
页面目录,:
shiro核心配置文件(rolesFilter可选)。
UserRealm.java
package com.shiro.config;import com.shiro.bean.student;
import com.shiro.mapper.studentMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;/*** 自定义Realm* @author bigsai**/
public class UserRealm extends AuthorizingRealm{@Autowired(required = false)private studentMapper studentMapper;private final Logger logger= LoggerFactory.getLogger(UserRealm.class);/*** 执行授权逻辑*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {logger.info("执行逻辑授权");//给资源进行授权SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//添加资源的授权字符串//到数据库查询当前登录用户的授权字符串//获取当前登录用户Subject subject = SecurityUtils.getSubject();student user = (student) subject.getPrincipal();student dbUser = studentMapper.findByName(user.getUsername());info.addRole(user.getRole());//添加role 和perms role代表角色 perms代表操作,或者动作等。用于颗粒化权限管理info.addStringPermission(dbUser.getPerm());System.out.println("user:" dbUser.getPerm());return info;}/*** 执行认证逻辑*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {System.out.println("执行认证逻辑");//编写shiro判断逻辑,判断用户名和密码//1.判断用户名UsernamePasswordToken token = (UsernamePasswordToken)arg0;student user = studentMapper.findByName(token.getUsername());if(user==null){//用户名不存在return null;//shiro底层会抛出UnKnowAccountException}//2.判断密码return new SimpleAuthenticationInfo(user,user.getPassword(),"");}}
rolesFilter
package com.shiro.config;import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;// AuthorizationFilter抽象类事项了javax.servlet.Filter接口,它是个过滤器。
public class rolesFilter extends AuthorizationFilter {@Overrideprotected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) throws Exception {Subject subject = getSubject(req, resp);String[] rolesArray = (String[]) mappedValue;if (rolesArray == null || rolesArray.length == 0) { //没有角色限制,有权限访问return true;}for (int i = 0; i < rolesArray.length; i ) {if (subject.hasRole(rolesArray[i])) { //若当前用户是rolesArray中的任何一个,则有权限访问return true;}}return false;}
}
shiroConfig:shiro的主要配置
package com.shiro.config;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 javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;/*** Shiro的配置类** @author bigsai*/
@Configuration
public class ShiroConfig {/*** 创建ShiroFilterFactoryBean*/@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();//设置安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);Map filtersMap = new LinkedHashMap<>();filtersMap.put("rolesFilter",new rolesFilter());shiroFilterFactoryBean.setFilters(filtersMap);//使用自定义fitter//添加Shiro内置过滤器/*** Shiro内置过滤器,可以实现权限相关的拦截器* 常用的过滤器:* anon: 无需认证(登录)可以访问* authc: 必须认证才可以访问* user: 如果使用rememberMe的功能可以直接访问* perm: 该资源必须得到资源权限才可以访问* role: 该资源必须得到角色权限才可以访问*/Map filterMap = new LinkedHashMap();filterMap.put("/login", "anon");//要将登陆的接口放出来,不然没权限访问登陆的接口filterMap.put("/getcontroller", "anon");
////授权过滤器//注意:当前授权拦截后,shiro会自动跳转到未授权页面filterMap.put("/add", "perms[add]");filterMap.put("/update", "perms[update]");//filterMap.put("/test1.html","rolesFilter[admin,user]");filterMap.put("/*", "authc");//authc即为认证登陆后即可访问//修改调整的登录页面shiroFilterFactoryBean.setLoginUrl("/index");//设置未授权提示页面shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);return shiroFilterFactoryBean;}/*** 创建DefaultWebSecurityManager*/@Bean(name = "securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//关联realmsecurityManager.setRealm(userRealm);return securityManager;}/*** 创建Realm*/@Bean(name = "userRealm")public UserRealm getRealm() {return new UserRealm();}}
身份认证
身份认证,就是登录校检。这是第一层过滤,并且当用户没有登录的时候,回退到没登陆的界面。在controller中,login的核心为:
@RequestMapping("/login")public String login(String name, String password, Model model, HttpServletRequest request) {model.addAttribute("nama", "给个star");/*** 使用Shiro编写认证操作*///1.获取SubjectSubject subject = SecurityUtils.getSubject();//2.封装用户数据UsernamePasswordToken token = new UsernamePasswordToken(name, password);//3.执行登录方法try {subject.login(token);//登录成功//跳转return "redirect:/index2";} catch (UnknownAccountException e) {//e.printStackTrace();//登录失败:用户名不存在model.addAttribute("msg", "用户名不存在");return "login";} catch (IncorrectCredentialsException e) {//e.printStackTrace();//登录失败:密码错误model.addAttribute("msg", "密码错误");return "login";}}
releam中
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {System.out.println("执行认证逻辑");//编写shiro判断逻辑,判断用户名和密码//1.判断用户名UsernamePasswordToken token = (UsernamePasswordToken)arg0;student user = studentMapper.findByName(token.getUsername());if(user==null){//用户名不存在return null;//shiro底层会抛出UnKnowAccountException}//2.判断密码return new SimpleAuthenticationInfo(user,user.getPassword(),"");}
而这只是表象的处理过程,而在releam(继承AuthorizingRealm
)中需要充血doGetAuthenticationInfo()
方法.
大致流程为:登录
——>拿账号密码检验
———>用着token的账号通过你的sql查询对象
——>比对数据是否一致
——>通过还是抛各种异常
而在shiroConfig中,基于url过滤时authc
即可访问
多表登录源如何操作?
可能会遇到如下情况:教师端,学生端来自两张表,两个登录接口,我该如何使用shiro身份认证。对于这种问题,你可以配置多个releam,但是我觉得如果简单你可以在不同的登录接口下传递一个参数过来,这个参数就用session传递。因为,shiro的session和网页httprequest获得的session是同一个session
。
所以当你在login传递一个属性到releam中,可用 if else判断然后不同登录接口执行不同的查询方法即可。
授权管理
接上流程
是否登录
——>是/否
——(是)—>查询role/perm添加到subject
——>过滤器校验该url需要权限
——>可以访问/权限不足
shiro主要url可以根据角色(role)和资源(perm)的管理。对于role,可以是管理员,教师等,而perm,可能是一个动作,一个操作,等等。并且可能一个角色拥有多个role和perm。
同理,授权就是查询数据库的role或者perm字段添加到角色中。当然具体api不做介绍。
主要方法为上述:
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {logger.info("执行逻辑授权");//给资源进行授权SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//添加资源的授权字符串//到数据库查询当前登录用户的授权字符串//获取当前登录用户Subject subject = SecurityUtils.getSubject();student user = (student) subject.getPrincipal();student dbUser = studentMapper.findByName(user.getUsername());info.addRole(user.getRole());//添加role 和perms role代表角色 perms代表操作,或者动作等。用于颗粒化权限管理info.addStringPermission(dbUser.getPerm());System.out.println("user:" dbUser.getPerm());return info;}
而url中也是
filterMap.put("/add", "perms[add]");filterMap.put("/update", "roles[admin]");
如何解决界面多角色/资源问题
常常遇到这种情况:一个接口/页面,有两个或者以上角色可以访问。然后再后台的过滤器配置总。shiro默认的配置是and而不是or。这就需要我们自己定义filter继承AuthorizationFilter
从写对应方法。
以多角色访问为例子。从写上述就是文件rolesFilter。在使用的时候也要首先声明filter才能使用。
访问效果
在页面授权的
运行测试:访问其他接口都被返回到这个界面
登陆成功后,界面可以访问
有个小注意点:如果mybatis2.0版本回和spring-start-web有冲突。我用1.3.2版本没问题。
参考:百度百科
项目github地址
springboot一些学习整合完整地址
如果对后端、爬虫等感性趣欢迎关注我的个人公众号交流:bigsai
Springboot整合shiro基于url身份认证和授权认证相关推荐
- mysql url认证_Springboot+shiro基于url身份认证和授权认证
你还不会shiro吗?前奏 shiro核心配置文件(rolesFilter可选). 身份认证 多表登录源如何操作? 授权管理 如何解决界面多角色/资源问题 访问效果 权限管理在日常开发中很重要,所以硬 ...
- 补习系列(6)- springboot 整合 shiro 一指禅
欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...
- SpringBoot 整合Shiro 一指禅
目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...
- 补习系列-SpringBoot 整合Shiro 一指禅
目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...
- 补习系列- springboot 整合 shiro 一指禅
目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...
- 补习系列(6)-SpringBoot 整合Shiro 一指禅
目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...
- SpringBoot整合Shiro实现登录认证和授权CHCache
文章目录 一. springboot实现普通登录 1 添加依赖 2 编写配置文件 3 新建实体类和mapper 4 编写业务层代码 5 编写控制器 6 编写启动类 7 编写登录页面和主页面 二. sp ...
- SpringBoot整合Shiro搭建登录注册认证授权权限项目模板
主要内容: 1 SpringBoot整合Shiro安全框架; 2 Shiro主要学习内容总结;(执行流程.主要对象接口.注意事项等) 3 Redis实现对权限信息缓存; ! 温馨提示: 想要快速搭Sh ...
- springboot整合shiro + jwt + redis实现权限认证(上手即用)
目录 前言 项目结构 依赖导入 建数据库表 建表语句 使用插件生成增删改查 添加MyRealm 添加ShiroConfig 添加JwtFilter JWT相关得类 JwtToken JwtAudien ...
最新文章
- 【C】 36_函数与指针分析
- C#2.0及C#3.0语言规范
- 动态切换站点样式(换皮肤)
- 算法---------括号生成
- python编码类型互转总结
- Right Here Waiting
- Linux(debian7)操作基础(十二)之文件加密使用指南
- linux中打开gif图片命令,在Linux终端中安装使用Gifski创建GIF动图
- Android版数据结构与算法(五):LinkedHashMap核心源码彻底分析
- uva 540 (Team Queue UVA - 540)
- win7关闭开机启动项_电脑开机非常慢?原来是有软件偷偷自启动,教你一招彻底关闭它们...
- WAP在线浏览器大全
- webpack打包报错系列(二)Failed to load C:\Users\XXX\webpack.config.js:17 mode: ‘development‘
- MongoDB双机热备份
- UnicodeEncodeError: 'gbk' codec can't encode character '\xa0'
- 谷歌招聘 变态15题你会做几道?
- Kali工具库之cadaver
- 2D游戏中的地图创造
- 计算机9月21日二级试题,2016年9月计算机二级Access考前试题及答案
- 记录一次比较糟心的数据库目录挂载
热门文章
- Kubernetes各组件的功能
- HTML5中各种标签总结(多媒体标签)
- Shell之系统函数和自定义函数
- [gic]-中断虚拟化-Host和Guest的中断处理流程举例(gicv3举例)
- VTS工具测试指定的testcase函数(以VtsHalKeymasterV4_0TargetTest为例)
- 获取系统进程信息和进程依赖的dll信息--CreateToolhelp32Snapshot
- 广西中专机器人应用与维护_我校2018级工业机器人应用与维护专业跟岗实习
- python判断计算机是否有网络连接
- 自定义一个SharedPreferences工具类
- 13、HTML <meta>标签