Shrio笔记

一、权限管理

不同身份的用户进入到系统所能完成的操作是不同的,我们对不同用户进行的可执行的操作管理称之为权限管理

1.1 实现方法

基于主页的实现方法(权限通过主页来限制)

适用于权限管理比较单一,用户少,权限固定

在这里插入图片描述
基于用户权限的实现方法

可以实现权限的动态分配,但是不够灵活

在这里插入图片描述
RBAC 基于角色的访问控制(Role-Based Access Control)

在这里插入图片描述

二、Shiro工作原理

2.1Shiro核心功能

Authentication 认证 ,Authorization 授权,Session Management 会话管理功能,Cryptography 密码管理

  • Authentication 认证,验证用户是否有相应的身份—登录认证

  • Authorization 授权,即权限验证,对已经通过认证的用户检查是否具有某个权限或角色,从而控制是否能够进行某种操作

  • Session Management 会话管理功能,用户认证成功之后创建会话,在没有退出之前,当前用户的所有信息都会保存在这个会话中

  • Cryptography 密码管理,对敏感信息进行加密处理,shiro就提供这种密钥。

  • 支持特性:

    Web Support —shiro提供过滤器。

    ​ Caching 缓存支持,shiro可以缓存用户信息以及用户角色权限信息;提高执行效率。

    ​ Concurrency shiro支持多线程应用。

    ​ Testing 提供测试支持。

2.2 核心组件

三大核心组件: Subject , Security Manager, Realms

  • Subject, 表示待认证和授权用户。
  • Security Manager,它是shiro框架的核心,shiro就是通过Security Manager来进行内部实例的管理,并通过它提供安全管理的各种服务。
  • Security ,相当于shiro进行认证和授权的数据源,充当了shiro与安全数据的“桥梁”。

shiro的工作示意图 :
在这里插入图片描述

三、springboot整合shiro

3.1创建项目

包含:mysql, springweb, thymeleaf, druid和mybatis

依赖:

	   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
<!--        druid starter-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>
<!--        mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
<!--        junit测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
3.2 yml配置:
spring:
  datasource:
    druid:
      url: jdbc:mysql://localhost:3306/shirotest?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: chen123456
      initial-size: 1
      min-idle: 1
      max-active: 20
server:
  port: 8081
mybatis:
  mapper-locations: classpath:/mapper/*.xml
  type-aliases-package: com.vector.beens

整合shiro:

<!--        shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.0</version>
        </dependency>
3.3 配置shiro的ini拦截器
package com.vector.config;

import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {

  @Bean
  public IniRealm getIniRealm(){
    IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
    return iniRealm;
  }
  @Bean
  public DefaultWebSecurityManager getDefaultWebSecurityManager(IniRealm iniRealm){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    // securityManager要完成需要realm
    securityManager.setRealm(iniRealm);
    return securityManager;
  }
  // 过滤器
  @Bean
  public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager){
    ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
    //shiro认证和授权是需要securityManager的
    filter.setSecurityManager(securityManager);
    //拦截规则
    /**
     * anon 匿名用户可访问
     * authc 认证用户可访问
     * user 使用RemeberMe的用户可访问
     * perms 对应权限可访问
     * role 对应角色可访问
     */
    Map<String,String> filterMap = new HashMap<>();
    //根目录不拦截
    filterMap.put("/","anon");
    //。。。
    filterMap.put("/login.html","anon");
    filterMap.put("/regist.html","anon");
    filterMap.put("/user/login","anon");
    filterMap.put("/user/regist","anon");
    filterMap.put("/static/**","anon");
    //认证用户可访问
    filterMap.put("/**","authc");
    filter.setFilterChainDefinitionMap(filterMap);
      // 设置默认登陆页面
    filter.setLoginUrl("/login.html");
    // 设置未授权访问页面跳转路径
    filter.setUnauthorizedUrl("/login.html");
    return filter;
  }
}
3.4 基于数据库jdbc的shiro配置
package com.vector.config;
@Configuration
public class ShiroConfig {

  @Bean
  public JdbcRealm getJdbcRealm(DataSource dataSource){
    JdbcRealm jdbcRealm = new JdbcRealm();
    //会自动从数据库中查询用户及权限数据(数据库表结构要符合JdbcRealm的规范)
    jdbcRealm.setDataSource(dataSource);
    //默认开启认证功能,需要手动开启授权功能
    jdbcRealm.setPermissionsLookupEnabled(true);
    return jdbcRealm;
  }
  @Bean
  public DefaultWebSecurityManager getDefaultWebSecurityManager(JdbcRealm jdbcRealm){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    // securityManager要完成需要realm
    securityManager.setRealm(jdbcRealm);
    return securityManager;
  }
  // 过滤器
  @Bean
  public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager){
    ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
    //shiro认证和授权是需要securityManager的
    filter.setSecurityManager(securityManager);
    //拦截规则
    Map<String,String> filterMap = new HashMap<>();
    //根目录不拦截
    filterMap.put("/","anon");
    filterMap.put("/login.html","anon");
    filterMap.put("/regist.html","anon");
    filterMap.put("/user/login","anon");
    filterMap.put("/user/regist","anon");
    filterMap.put("/static/**","anon");
    //认证用户可访问
    filterMap.put("/**","authc");
    filter.setFilterChainDefinitionMap(filterMap);
    // 设置默认登陆页面
    filter.setLoginUrl("/login.html");
    // 设置未授权访问页面跳转路径
    filter.setUnauthorizedUrl("/login.html");
    return filter;
  }
}
3.4 serviceiml中代码
// 登录认证代码
@Service
public class UserServiceImpl implements UserService {
  @Override
  public void chickLogin(String username, String password) {
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    subject.login(token);
  }
}

四、shiro标签的使用

  1. jsp中的引用

    <%@ taglib prefix="shiro" url="http://shiro.apache.org/tags" %>
    
  2. Thymeleaf模板中引用

    • 导入对shiro的依赖

      <dependency>
           <groupId>com.github.theborakompanioni</groupId>
           <artifactId>thymeleaf-extras-shiro</artifactId>
           <version>2.0.0</version>
      </dependency>
      

      在ShiroConfig中配置shiro的

      @Bean
        public ShiroDialect getShiroDialect(){
          return new ShiroDialect();
        }
      // ...
      

      引入shiro命名空间

    <html xmlns:th="http://www.thymeleaf.org" 
          xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
        ...
    </html>
    
常用标签的使用
<shiro:guest>该标签中的内容是在未登录状态下显示</shiro:guest>	

<shiro:user>已登陆用户可访问</shiro:user>

用户[<shiro:principal/>]欢迎登录		//获取用户

// 判断角色
当前用户是<shiro:hasRole  name="admin">超级管理员</shiro:hasRole>
        <shiro:hasRole  name="cmanager">仓库管理员</shiro:hasRole>
        <shiro:hasRole  name="xmanage">销售管理员</shiro:hasRole>

// 判断用到的权限
仓管
<ul>
    <shiro:hasPermission name="sys:c:save">
        <li><a href="#">保存</a></li>
    </shiro:hasPermission>
    <shiro:hasPermission name="sys:c:delete">
        <li><a href="#">删除</a></li>
    </shiro:hasPermission>
</ul>

五、Dao层实现

1.根据用户名查询用户信息
2.shiro进行授权管理需要当前用户的角色和权限
    。根据用户名查询当前用户的角色列表(联合查询)
    。根据用户查询当前用户的权限列表(联合查询)

六、自定义realm的配置

6.1 MyRealm类
public class MyRealm extends AuthorizingRealm {
  @Resource
  private UserDao userDao;
  @Resource
  private RoleDao roleDao;
  @Resource
  private PermissionDao permissionDao;

  public String getName(){
    return "myRealm";
  }
  /**
   * 获取授权数据
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    //获取用户的用户名
    String username = (String) principalCollection.iterator().next();
    //查询角色列表
    Set<String> roleNames = roleDao.queryRoleNameByUserName(username);
    //查询当前用户的权限列表
    Set<String> ps = permissionDao.queryPermissionByUserName(username);
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    info.setRoles(roleNames);
    info.setStringPermissions(ps);
    return info;
  }

  /**
   * 获取认证数据
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    // 从token中获取用户名
    UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    String username = token.getUsername();
    // 根据用户名从数据库中查询安全数据
    User user = userDao.queryUserByUserName(username);
    if (user==null){
      return null;
    }
    AuthenticationInfo info = new SimpleAuthenticationInfo(
            username,   //当前用户名
            user.getUserPwd(),  // 从数据库中查出的密码
            getName()
    );
    return info;
  }
}
6.2 config中
@Configuration
public class ShiroConfig {
  @Bean
  public ShiroDialect getShiroDialect(){
    return new ShiroDialect();
  }

  @Bean
  public MyRealm getMyRealm(){
    MyRealm myRealm = new MyRealm();
    return myRealm;
  }
  @Bean
  public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    // securityManager要完成需要realm
    securityManager.setRealm(myRealm);
    return securityManager;
  }
  // 过滤器
  @Bean
  public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager){
    ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
    //shiro认证和授权是需要securityManager的
    filter.setSecurityManager(securityManager);
    //拦截规则
    Map<String,String> filterMap = new HashMap<>();
    //根目录不拦截
    filterMap.put("/","anon");
    filterMap.put("/login.html","anon");
    filterMap.put("/regist.html","anon");
    filterMap.put("/user/login","anon");
    filterMap.put("/user/regist","anon");
    filterMap.put("/static/**","anon");
    //认证用户可访问
    filterMap.put("/**","authc");
    filter.setFilterChainDefinitionMap(filterMap);
    // 设置默认登陆页面
    filter.setLoginUrl("/login.html");
    // 设置未授权访问页面跳转路径
    filter.setUnauthorizedUrl("/login.html");
    return filter;
  }
}

七、shiro的mad5加密

// shiro.config中添加内容
@Bean
  public HashedCredentialsMatcher getHashedCredentialsMatcher(){
    //指定加密规则
    HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
    //加密方式
    matcher.setHashAlgorithmName("md5");
    //hash加密次数
    matcher.setHashIterations(1);
    return matcher;
  }

  @Bean
  public MyRealm getMyRealm(HashedCredentialsMatcher matcher){
    MyRealm myRealm = new MyRealm();
    myRealm.setCredentialsMatcher(matcher);
    return myRealm;
  }
...
  // 如果数据库中的密码加了盐则需要 (MyRealm.java中)
    /**
   * 获取认证数据
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    // 从token中获取用户名
    UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    String username = token.getUsername();
    // 根据用户名从数据库中查询安全数据
    User user = userDao.queryUserByUserName(username);
    if (user==null){
      return null;
    }
    AuthenticationInfo info = new SimpleAuthenticationInfo(
            username,   //当前用户名
            user.getUserPwd(),  // 从数据库中查出的密码
            ByteSource.Util.bytes(user.getPwdSalt()),
            getName()
    );
    return info;
  }

八、授权处理

8.1 配置注解支持

在config中配置

// 注解拦截
  @Bean
  public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
    DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    autoProxyCreator.setProxyTargetClass(true);
    return autoProxyCreator;
  }
  //注解权限
  @Bean
  public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){
    AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
    advisor.setSecurityManager(securityManager);
    return advisor;
  }


//调用注解,例如:
@RequiresPermissions("sys:c:save")
8.2 全局异常处理
@ControllerAdvice
public class GlobalExceptionHander {
  @ExceptionHandler
  public String doException(Exception e){
    if (e instanceof AuthorizationException){
      return "";
    }
    return "";
  }
}

九、缓存的使用

减少数据库的访问压力

  • 导入依赖
<!--        boot缓存-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
<!--        第三方缓存-->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
<!--        shiro支持缓存-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.7.0</version>
        </dependency>
  • ehcache.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<ehcache updateCheck="false" dynamicConfig="false">
    <diskStore path="D:\TEMP" />
    <cache name="users" timeToliveSecond="300" maxEntriesLocalHeap="1000"/>
    <defaultCache name="defaultCache"
                  maxElementsInMemory="10000"
                  eternal="false"
                  timeToIdleSeconds="120"
                  timeToLiveSeconds="120"
<!--                  是否存入磁盘-->
                  overflowToDisk="false"
                  maxElementsOnDisk="100000"
                  diskPersistent="false"
                  diskExpiryThreadIntervalSeconds="120"
<!--                    缓存淘汰策略LRU(最近最久未使用) LFU(最少使用)-->
                  memoryStoreEvictionPolicy="LRU" />
</ehcache>
  • ShiroConfig.java配置缓存
//缓存配置
  @Bean
  public EhCacheManager getEhCacheManager(){
    EhCacheManager ehCacheManager = new EhCacheManager();
    ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
    return ehCacheManager;
  }
  
  @Bean
  public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm,EhCacheManager ehCacheManager){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    // securityManager要完成需要realm
    securityManager.setRealm(myRealm);
    securityManager.setCacheManager(ehCacheManager);
    return securityManager;
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值