shiro基础认识

中间件shiro的了解与认识

Posted by John Doe on 2020-09-05
Words 1.1k and Reading Time 4 Minutes
Viewed Times

shiro 简介

shiro是apache的一个开源框架,而且呢是一个权限管理的框架,用于实现用户认证、用户授权。spring 中也有一个权限框架 spring security (原名Acegi),它和 spring 依赖过于紧密,没有 shiro 使用简单。shiro 不依赖于 spring,shiro 不仅可以实现 web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。使用shiro实现系统的权限 管理,有效提高开发效率,从而降低开发成本。

shiro 基本功能点

shiro结构图
subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。security Manager:安全管理器,主体进行认证和授权都是通过securityManager进行。authenticator:认证器,主体进行认证最终通过authenticator进行的。 authorizer:授权器,主体进行授权最终通过authorizer进行的。
sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。SessionDao: 通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。
cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。 Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储。 realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。

认证流程

shiro认证流程图

  1. 构建SecurityManager环境
  2. 主体提交认证
  3. SecurityManager 处理
  4. 流转到 Authenticator 执行认证通过 Realm 获取相关的用户信息(获取验证数据进行验证)

授权流程

shiro授权流程图

  1. 创建构建SecurityManager环境
  2. 主体提交授权认证
  3. SecurityManager 处理
  4. 流转到 Authorizor 授权器执行授权认证
  5. 通过 Realm 从数据库或配置文件获取角色权限数据返回给授权器,进行授权。

shiro使用流程

注:适用于基于redis缓存的token验证,redis存储用户角色与权限,获取用户信息(包含角色、权限、登录过期时间、主键id等等)

自定义配置安全域

  1. extends AuthorizingRealm
  2. 验证用户名/密码/验证 token 是否有效
  3. 从数据库获取用户的角色
  4. 根据角色获取用户权限

shiro核心配置——config

  1. 读reids缓存
  2. 自定义域
  3. 构建 SecurityManager环境
  4. 配置shiro过滤器,配置拦截哪些请求
  5. 开启shiro aop注解支持
    实例代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    @Configuration
    public class ShiroConfig {
    /**
    *自定义密码 校验
    *@return com.yingxue.lesson.shiro.CustomHashedCredentialsMatcher
    */
    @Bean
    public CustomHashedCredentialsMatcher customHashedCredentialsMatcher(){
    return new CustomHashedCredentialsMatcher();
    }
    /**
    *自定义域
    *@return com.yingxue.lesson.shiro.CustomRealm
    *@throws
    */

    @Bean
    public CustomRealm customRealm(){
    CustomRealm customRealm=new CustomRealm();
    customRealm.setCredentialsMatcher(customHashedCredentialsMatcher());
    return customRealm;
    }



    /**
    *安全管理
    *@return org.apache.shiro.mgt.SecurityManager
    *@throws
    */

    @Bean
    public SecurityManager securityManager(){
    //构建 SecurityManager环境
    DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
    //自定义 Realm
    securityManager.setRealm(customRealm());
    return securityManager;
    }

    /**
    *shiro过滤器,配置拦截哪些请求
    *@param securityManager
    *@return org.apache.shiro.spring.web.ShiroFilterFactoryBean
    *@throws
    */

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager);
    //自定义拦截器限制并发人数,参考博客
    LinkedHashMap<String, Filter> filtersMap = new LinkedHashMap<>();
    //用来校验token
    filtersMap.put("token", new CustomAccessControlFilter()); shiroFilterFactoryBean.setFilters(filtersMap);
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/api/user/login", "anon");
    //放开swagger-ui地址
    filterChainDefinitionMap.put("/swagger/**", "anon");
    filterChainDefinitionMap.put("/v2/api-docs", "anon");
    filterChainDefinitionMap.put("/swagger-ui.html", "anon");
    filterChainDefinitionMap.put("/swagger-resources/**", "anon");
    filterChainDefinitionMap.put("/webjars/**", "anon");
    filterChainDefinitionMap.put("/favicon.ico", "anon");
    filterChainDefinitionMap.put("/captcha.jpg", "anon");
    filterChainDefinitionMap.put("/csrf","anon");
    filterChainDefinitionMap.put("/**","token,authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
    }


    /**
    *开启shiro aop注解支持.
    *使用代理方式;所以需要开启代码支持;
    *@param securityManager
    *@return org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
    *@throws
    */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return authorizationAttributeSourceAdvisor;
    }
    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = newDefaultAdvisorAutoProxyCreator();
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    return defaultAdvisorAutoProxyCreator;
    }


    }

shiro注解控制请求调用与前端权限控制可见性

后端controller层shiro注解使用:
实例代码:
拥有sys:user:list权限的角色才能调用这个请求

1
2
3
4
5
6
7
8
@PostMapping("/users")
@ApiOperation(value = "分页查询用户接口")
@RequiresPermissions("sys:user:list")
public DataResult<PageVO<SysUser>> pageInfo(@RequestBody UserPageReqVO vo){
DataResult result=DataResult.success();
result.setData(userService.pageInfo(vo));
return result;
}

前端控制不同角色按钮元素可见性:
拥有sys:log:delete权限的角色才能看到使用这个按钮
1
2
3
4
5
6
7
<script type="text/html" id="toolbar">
<div class="layui-btn-group">
<button type="button" class="layui-btn" lay-event="batchDelLog" shiro:hasPermission="sys:log:delete">
<i class="layui-icon">&#xe608;</i> 批量删除
</button>
</div>
</script>


This is copyright.

...

...

00:00
00:00