小滴课堂官网:https://xdclass.net/#/index 官网
简介:讲解为什么要学这门课,Shiro权限框架的课程大纲和学后水平
公司新项目需要用到、要么就是需要接收别人的代码、个人技术栈的成长
Springboot2.x/SpringMVC + Maven + jdk8 + IDEA/Eclipse
学后水平:掌握Shiro在公司中实际的使用,包括明白里面的核心原理
简介:讲解什么是权限控制,初学JavaWeb时处理流程
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws Exception {
HttpServletRequest httpRequest=(HttpServletRequest)request;
HttpServletResponse httpResponse=(HttpServletResponse)response;
HttpSession session=httpRequest.getSession();
if(session.getAttribute("username")!=null){
chain.doFilter(request, response);
} else {
httpResponse.sendRedirect(httpRequest.getContextPath()+"/login.jsp");
}
}
简介:介绍什么是ACL和RBAC
ACL: Access Control List 访问控制列表
RBAC: Role Based Access Control
BAT企业 ACL,一般是对报表系统,阿里的ODPS
总结:不能过于复杂,规则过多,维护性和性能会下降, 更多分类 ABAC、PBAC等
简介:介绍主流的权限框架 Apache Shiro、spring Security
什么是 spring Security:官网基础介绍
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
一句话:Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架
什么是 Apache Shiro:官网基础介绍
https://github.com/apache/shiro
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
一句话:Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能
两个优缺点,应该怎么选择
Apache Shiro比Spring Security , 前者使用更简单
Shiro 功能强大、 简单、灵活, 不跟任何的框架或者容器绑定,可以独立运行
Spring Security 对Spring 体系支持比较好,脱离Spring体系则很难开发
SpringSecutiry 支持Oauth鉴权 https://spring.io/projects/spring-security-oauth,Shiro需要自己实现
…
总结:两个框架没有谁超过谁,大体功能一致,新手一般先推荐Shiro,学习会容易点
简介:讲解Shiro架构图交互和四大核心模块 身份认证,授权,会话管理和加密
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x98dYQaT-1657853977081)(http://shiro.apache.org/assets/images/ShiroFeatures.png)]
简介:讲解用户访问整合Shrio的系统,权限控制的运行流程和Shiro常见名称讲解
直达官网 :http://shiro.apache.org/architecture.html
Subject
SecurityManager
Authenticator
Realm
Authorizer
Cryptography
Cache Manager
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cNSLBy6M-1657853977085)(http://shiro.apache.org/assets/images/ShiroArchitecture.png)]
更多资料导航:http://shiro.apache.org/reference.html
简介:使用SpringBoot2.x整合Shiro权限认证
Maven3.5 + Jdk8 + Springboot 2.X + IDEA (Eclipse也可以)
创建SpringBoot项目
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
org.springframework.boot
spring-boot-starter-test
test
com.alibaba
druid
1.1.6
整合Shiro相关jar包
org.apache.shiro
shiro-spring
1.4.0
简介:讲解Shrio的认证和授权实操上集
认证:用户身份识别,俗称为用户“登录”
简介:讲解Shiro的授权实操和常用Api 梳理下集
//是否有对应的角色
subject.hasRole("root")
//获取subject名
subject.getPrincipal()
//检查是否有对应的角色,无返回值,直接在SecurityManager里面进行判断
subject.checkRole("admin")
//检查是否有对应的角色
subject.hasRole("admin")
//退出登录
subject.logout();
简介:讲解shiro默认自带的realm和常见使用方法
realm作用:Shiro 从 Realm 获取安全数据
默认自带的realm:idae查看realm继承关系,有默认实现和自定义继承的realm
两个概念
开发中,往往是自定义realm , 即集成 AuthorizingRealm
简介:讲解Shiro内置 ini realm实操
# 格式 name=password,role1,role2,..roleN
[users]
# user 'root' with password 'secret' and the 'admin' role,
jack = 456, user
# user 'guest' with the password 'guest' and the 'guest' role
xdcalss = 123, root
# 格式 role=permission1,permission2...permissionN 也可以用通配符
# 下面配置user的权限为所有video:find,video:buy,如果需要配置video全部操作crud 则 user = video:*
[roles]
user = video:find,video:buy
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
简介:讲解Shiro内置 JdbcRealm实操
#注意 文件格式必须为ini,编码为ANSI
#声明Realm,指定realm类型
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
#配置数据源
#dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource=com.alibaba.druid.pool.DruidDataSource
# mysql-connector-java 5 用的驱动url是com.mysql.jdbc.Driver,mysql-connector-java6以后用的是com.mysql.cj.jdbc.Driver
dataSource.driverClassName=com.mysql.cj.jdbc.Driver
#避免安全警告
dataSource.url=jdbc:mysql://120.76.62.13:3606/xdclass_shiro?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
dataSource.username=test
dataSource.password=Xdclasstest
#指定数据源
jdbcRealm.dataSource=$dataSource
#开启查找权限, 默认是false,不会去查找角色对应的权限,坑!!!!!
jdbcRealm.permissionsLookupEnabled=true
#指定SecurityManager的Realms实现,设置realms,可以有多个,用逗号隔开
securityManager.realms=$jdbcRealm
方式二
DefaultSecurityManager securityManager = new DefaultSecurityManager();
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://120.76.62.13:3606/xdclass_shiro?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false");
ds.setUsername("test");
ds.setPassword("Xdclasstest");
简介:讲解自定义Realm实战基础
步骤:
方法:
对象介绍
UsernamePasswordToken : 对应就是 shiro的token中有Principal和Credential
UsernamePasswordToken-》HostAuthenticationToken-》AuthenticationToken
SimpleAuthorizationInfo:代表用户角色权限信息
SimpleAuthenticationInfo :代表该用户的认证信息
简介:Shiro认证和授权流程的源码解读,和断点测试
认证流程解读:subject.login(usernamePasswordToken);
DelegatingSubject->login()
DefaultSecurityManager->login()
AuthenticatingSecurityManager->authenticate()
AbstractAuthenticator->authenticate()
ModularRealmAuthenticator->doAuthenticate()
ModularRealmAuthenticator->doSingleRealmAuthentication()
AuthenticatingRealm->getAuthenticationInfo()
补充:有些同学找不到密码验证方法 AuthenticatingRealm-> assertCredentialsMatch()
授权流程解读:subject.checkRole("admin")
DelegatingSubject->checkRole()
AuthorizingSecurityManager->checkRole()
ModularRealmAuthorizer->checkRole()
AuthorizingRealm->hasRole()
AuthorizingRealm->doGetAuthorizationInfo()
###第1集 Shiro内置的Filter过滤器讲解
简介:讲解shiro内置的过滤器讲解
核心过滤器类:DefaultFilter, 配置哪个路径对应哪个拦截器进行处理
authc:org.apache.shiro.web.filter.authc.FormAuthenticationFilter
user:org.apache.shiro.web.filter.authc.UserFilter
anon:org.apache.shiro.web.filter.authc.AnonymousFilter
roles:org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
perms:org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
authcBasic:org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logout:org.apache.shiro.web.filter.authc.LogoutFilter
shiroFilterFactoryBean.setLoginUrl();
设置的 urlport:org.apache.shiro.web.filter.authz.PortFilter
ssl:org.apache.shiro.web.filter.authz.SslFilter
简介:讲解Filter配置路径
/admin/video /user /pub
路径通配符支持 ?、*、**,注意通配符匹配不 包括目录分隔符“/”
心 可以匹配所有,不加*可以进行前缀匹配,但多个冒号就需要多个 * 来匹配
URL权限采取第一次匹配优先的方式
? : 匹配一个字符,如 /user? , 匹配 /user3,但不匹配/user/;
* : 匹配零个或多个字符串,如 /add* ,匹配 /addtest,但不匹配 /user/1
** : 匹配路径中的零个或多个路径,如 /user/** 将匹 配 /user/xxx 或 /user/xxx/yyy
例子
/user/**=filter1
/user/add=filter2
请求 /user/add 命中的是filter1拦截器
简介: 讲解数据安全核心知识,介绍常见的处理办法,Shiro 里的 CredentialsMatcher使用
为啥要加解密
什么是散列算法
什么是salt(盐) 667788——》aabbcc
Shiro里面 CredentialsMatcher,用来验证密码是否正确,
源码:AuthenticatingRealm -> assertCredentialsMatch()
一般会自定义验证规则
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//散列算法,使用MD5算法;
hashedCredentialsMatcher.setHashAlgorithmName("md5");
//散列的次数,比如散列两次,相当于 md5(md5("xxx"));
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
简介:讲解权限角色控制 @RequiresRoles, @RequiresPermissions等注解的使用和编程式控制
配置文件的方式
使用ShiroConfig
注解方式
编程方式
Subject subject = SecurityUtils.getSubject();
//基于角色判断
if(subject.hasRole(“admin”)) {
//有角色,有权限
} else {
//无角色,无权限
}
//或者权限判断
if(subject.isPermitted("/user/add")){
//有权限
}else{
//无权限
}
简介:讲解缓存的作用和Shiro的缓存模块
什么是shiro缓存
AuthenticatingRealm 及 AuthorizingRealm 分别提供了对AuthenticationInfo 和 AuthorizationInfo 信息的缓存。
简介:讲解Shiro Session模块作用和SessionManager
什么是会话session
什么是会话管理器SessionManager
会话管理器管理所有subject的所有操作,是shiro的核心组件
核心方法:
//开启一个session
Session start(SessionContext context);
//指定Key获取session
Session getSession(SessionKey key)
shiro中的会话管理器有多个实现
SessionDao 会话存储/持久化
SessionDAO
AbstractSessionDAO
CachingSessionDAO
EnterpriseCacheSessionDAO
MemorySessionDAO
核心方法
//创建
Serializable create(Session session);
//获取
Session readSession(Serializable sessionId) throws UnknownSessionException;
//更新
void update(Session session)
//删除,会话过期时会调用
void delete(Session session);
//获取活跃的session
Collection getActiveSessions();
会话存储有多个实现
附属资料:
RememberMe
1、 Cookie 写到客户端并 保存
2、 通过调用subject.login()前,设置 token.setRememberMe(true);
3、 关闭浏览器再重新打开;会发现浏览器还是记住你的
4、 注意点:
- subject.isAuthenticated() 表示用户进行了身份验证登录的,即Subject.login 进行了登录
- subject.isRemembered() 表示用户是通过RememberMe登录的
- subject.isAuthenticated()==true,则 subject.isRemembered()==false, 两个互斥
- 总结:特殊页面或者API调用才需要authc进行验证拦截,该拦截器会判断用户是否是通过 subject.login()登录,安全性更高,其他非核心接口或者页面则通过user拦截器处理即可
简介:介绍Apache Shiro整合SpringBoot2.x综合实战和技术栈
简介:设计案例实战数据库 用户-角色-权限 及关联表
简介:使用springboot+mybatis+shiro搭建项目基础框架
官方下载 https://start.spring.io/
项目依赖
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.2
org.springframework.boot
spring-boot-starter-test
test
com.alibaba
druid
1.1.6
org.apache.shiro
shiro-spring
1.4.0
org.springframework.boot
spring-boot-maven-plugin
spring-snapshots
Spring Snapshots
https://repo.spring.io/snapshot
true
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
spring-snapshots
Spring Snapshots
https://repo.spring.io/snapshot
true
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
简介:开发用户-角色-权限 相关Service和Dao层
数据库配置
#==============================数据库相关配置========================================
spring.datasource.driver-class-name =com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://120.76.62.13:3606/xdclass_shiro?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username =test
spring.datasource.password =Xdclasstest
#使用阿里巴巴druid数据源,默认使用自带的
#spring.datasource.type =com.alibaba.druid.pool.DruidDataSource
#开启控制台打印sql
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# mybatis 下划线转驼峰配置,两者都可以
#mybatis.configuration.mapUnderscoreToCamelCase=true
mybatis.configuration.map-underscore-to-camel-case=true
简介:开发用户-角色-权限 多对多关联查询SQL
第一步 查询用户对应的角色映射关系
select * from user u
left join user_role ur on u.id=ur.user_id
where u.id=3
第二步 查询用户对应的角色信息
select * from user u
left join user_role ur on u.id=ur.user_id
left join role r on ur.role_id = r.id
where u.id=3
第三步 查询角色和权限的关系
select * from user u
left join user_role ur on u.id=ur.user_id
left join role r on ur.role_id = r.id
left join role_permission rp on r.id=rp.role_id
where u.id=1
第四步 查询角色对应的权限信息(某个用户具备的角色和权限集合)
select * from user u
left join user_role ur on u.id=ur.user_id
left join role r on ur.role_id = r.id
left join role_permission rp on r.id=rp.role_id
left join permission p on rp.permission_id=p.id
where u.id=1
简介:自定义CustomRealm开发实战
简介:讲解ShiroFilterFactoryBean配置实战
配置流程和思路
shiroFilterFactoryBean-》
SessionManager
简介:讲解前后端分离情况下自定义SessionManager
**简介: 讲解使用filterChainDefinitionMap控制api访问角色权限 **
localhost:8080/pub/login
localhost:8080/authc/video/play_record
localhost:8080/admin/video/order
localhost:8080/video/update
简介:Shiro logout常见错误思路和加密处理
@Test
public void testMD5(){
//加密算法
String hashName = "md5";
//密码明文
String pwd = "123";
//加密函数,使用shiro自带的
Object result = new SimpleHash(hashName, pwd, null, 2);
System.out.println(result);
}
简介:权限控制综合案例 自定义Shiro Filter过滤器
背景知识:
我们的需求:
订单信息,可以由角色 普通管理员 admin 或者 超级管理员 root 查看
只要用户具备其中一个角色即可
自定义Filter
// mappedValue -》roles[admin,root]
public class CustomRolesOrAuthorizationFilter extends AuthorizationFilter {
@Override
protected 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;
}
//当前subject是rolesArray中的任何一个,则有权限访问
for (int i = 0; i < rolesArray.length; i++) {
if (subject.hasRole(rolesArray[i])) {
return true;
}
}
return false;
}
}
FactoryBean配置
Map filtersMap = new LinkedHashMap<>();
filtersMap.put("roleOrFilter",new CustomRolesOrAuthorizationFilter());
filterChainDefinitionMap.put("/admin/**","roleOrFilter[admin,root]");
shiroFilterFactoryBean.setFilters(filtersMap);
简介:自定义Shiro Filter过滤器验证
配置不同的角色,验证自定义过滤器是否有效
登录(post)
localhost:8080/pub/login
管理员查看后台信息(get)
localhost:8080/admin/video/order
简介:讲解使用Redis整合CacheManager
使用原因?
步骤
org.crazycake
shiro-redis
3.1.0
配置bean
//使用自定义的cacheManager
securityManager.setCacheManager(cacheManager());
/**
* 配置redisManager
*
*/
public RedisManager getRedisManager(){
RedisManager redisManager = new RedisManager();
redisManager.setHost("localhost");
redisManager.setPort(6379);
return redisManager;
}
/**
* 配置具体cache实现类
* @return
*/
public RedisCacheManager cacheManager(){
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(getRedisManager());
//设置过期时间,单位是秒,20s,
redisCacheManager.setExpire(20);
return redisCacheManager;
}
安装redis (如何不会使用redis,则参考网上的博客文章)
原有的问题
class java.lang.String must has getter for field: authCacheKey or id\nWe need a field to identify this Cache Object in Redis. So you need to defined an id field which you can get unique id to identify this principal. For example, if you use UserInfo as Principal class, the id field maybe userId, userName, email, etc. For example, getUserId(), getUserName(), getEmail(), etc.\nDefault value is authCacheKey or id, that means your principal object has a method called \"getAuthCacheKey()\" or \"getId()\""
改造原有的逻辑,修改缓存的唯一key
doGetAuthorizationInfo 方法
原有:
String username = (String)principals.getPrimaryPrincipal();
User user = userService.findAllUserInfoByUsername(username);
改为
User newUser = (User)principals.getPrimaryPrincipal();
User user = userService.findAllUserInfoByUsername(newUser.getUsername());
doGetAuthenticationInfo方法
原有:
return new SimpleAuthenticationInfo(username, user.getPassword(), this.getClass().getName());
改为
return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());
简介:讲解使用Redis整合SessionManager,管理Session会话
为啥session也要持久化?
怎么持久化?
//配置session持久化
customSessionManager.setSessionDAO(redisSessionDAO());
/**
* 自定义session持久化
* @return
*/
public RedisSessionDAO redisSessionDAO(){
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(getRedisManager());
return redisSessionDAO;
}
注意点:
DO对象需要实现序列化接口 Serializable
logout接口和以前一样调用,请求logout后会删除redis里面的对应的key,即删除对应的token
简介:讲解ShiroConfig常用bean 介绍
LifecycleBeanPostProcessor
作用:管理shiro一些bean的生命周期 即bean初始化 与销毁
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
AuthorizationAttributeSourceAdvisor
作用:加入注解的使用,不加入这个AOP注解不生效(shiro的注解 例如 @RequiresGuest)
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
DefaultAdvisorAutoProxyCreator
作用: 用来扫描上下文寻找所有的Advistor(通知器), 将符合条件的Advisor应用到切入点的Bean中,需要在LifecycleBeanPostProcessor创建后才可以创建
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setUsePrefix(true);
return defaultAdvisorAutoProxyCreator;
}
**简介:介绍单体应用到分布式应用下的鉴权方式 **
电商项目:商品服务,支付服务,用户服务
简介:基于原先项目,实现自定义sessionid
Shiro 默认的sessionid生成 类名 SessionIdGenerator
创建一个类,实现 SessionIdGenerator 接口的方法
/**
* 自定义session持久化
* @return
*/
public RedisSessionDAO redisSessionDAO(){
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(getRedisManager());
//设置sessionid生成器
redisSessionDAO.setSessionIdGenerator(new CustomSessionIdGenerator());
return redisSessionDAO;
}
没有100%可靠的算法,暴力破解,穷举
建议:微服务里面,特别是对C端用户的应用,不要做过于复杂的权限校验,特别是影响性能这块