• SpringBoot--中间件技术-4:整合Shiro,Shiro基于会话SessionManager实现分布式认证,附案例含源代码!


    SpringBoot整合安全中间件Shiro

    技术栈:SpringBoot+Shiro

    代码实现

    1. pom文件加坐标

      Springboot版本选择2.7.14 ;java版本1.8 ; shiro做了版本锁定 1.3.2

      <properties>
        <java.version>1.8java.version>
        
        <shiro.version>1.3.2shiro.version>
      properties>
      <dependencies>
        <dependency>
          <groupId>org.springframework.bootgroupId>
          <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>
      
        <dependency>
          <groupId>org.springframework.bootgroupId>
          <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
          <groupId>org.springframework.bootgroupId>
          <artifactId>spring-boot-starter-data-jpaartifactId>
        dependency>
        <dependency>
          <groupId>org.springframework.bootgroupId>
          <artifactId>spring-boot-starter-loggingartifactId>
        dependency>
        <dependency>
          <groupId>org.springframework.bootgroupId>
          <artifactId>spring-boot-starter-testartifactId>
          <scope>testscope>
        dependency>
        
        <dependency>
          <groupId>org.projectlombokgroupId>
          <artifactId>lombokartifactId>
          <version>1.16.16version>
        dependency>
        
        <dependency>
          <groupId>mysqlgroupId>
          <artifactId>mysql-connector-javaartifactId>
          <version>8.0.21version>
        dependency>
        
        <dependency>
          <groupId>com.baomidougroupId>
          <artifactId>mybatis-plus-boot-starterartifactId>
          <version>3.4.3version>
        dependency>
      
        
        <dependency>
          <groupId>org.apache.shirogroupId>
          <artifactId>shiro-coreartifactId>
          <version>${shiro.version}version>
        dependency>
        <dependency>
          <groupId>org.apache.shirogroupId>
          <artifactId>shiro-springartifactId>
          <version>${shiro.version}version>
        dependency>
        <dependency>
          <groupId>org.apache.shirogroupId>
          <artifactId>shiro-webartifactId>
          <version>${shiro.version}version>
        dependency>
        <dependency>
          <groupId>org.apache.shirogroupId>
          <artifactId>shiro-ehcacheartifactId>
          <version>${shiro.version}version>
        dependency>
        
      dependencies>
      
      • 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
    2. 主配置文件

      #配置数据源
      spring:
        datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/spring?serverTimezone=GMT
          username: root
          password: 123456
      
      #配置自动驼峰映射
      mybatis:
        configuration:
          map-underscore-to-camel-case: true
        type-aliases-package: com.dong.pojo
      #MP配置自动驼峰映射
      mybatis-plus:
        configuration:
          map-underscore-to-camel-case: true
          log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #mybatis所执行的sql输出控制台
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
    3. POJO实体类

      Permission

      @NoArgsConstructor
      @AllArgsConstructor
      @Data
      @Component
      @TableName(value = "pe_permission")
      public class Permission {
          @TableField(value = "id")
          private String id;
          @TableField(value = "name")
          private String name;
          @TableField(value = "code")
          private String code;
          @TableField(value = "description")
          private String description;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

      Role

      @NoArgsConstructor
      @AllArgsConstructor
      @Data
      @TableName(value = "pe_role")
      @Component
      public class Role {
          @TableField(value = "id")
          private String id;
          @TableField(value = "name")
          private String name;
          @TableField(value = "code")
          private String code;
          @TableField(value = "description")
          private String description;
      
          // 外部属性
          @TableField(exist = false)
          private List<Permission> permissions;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19

      Users

      @NoArgsConstructor
      @AllArgsConstructor
      @Data
      @TableName(value = "pe_user")
      @Component
      public class Users {
          @TableId(value = "id")
          private String id;
          @TableField(value = "username")
          private String username;
          @TableField(value = "password")
          private String password;
          @TableField(value = "salt")
          private String salt;
      
          // 外部属性
          @TableField(exist = false)
          private List<Role> rolesList;
          public Users(String id, String username, String password) {
              this.id = id;
              this.username = username;
              this.password = password;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
    4. dao层

      UsersMapper

      @Mapper
      public interface UserMapper extends BaseMapper<Users> {
          @Insert("insert into pe_user(id,username,password,salt) values(#{id},#{username},#{password},#{salt})")
          public int save(Users users);
      
          // 级联查询
          @Results(id = "users",value = {
                  @Result(column = "id",property = "rolesList",many = @Many(select = "com.dong.springboot_mp_shiro.com.dong.mapper.RoleMapper.findById"))
          })
      
          @Select("select * from pe_user where username=#{v}")
          public Users findUserDetail(String name);
      
          // 简单查询
          @Select("select * from pe_user where username=#{v}")
          public Users findBaseUser(String name);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

      RoleMapper

      @Mapper
      public interface RoleMapper extends BaseMapper<Role> {
      
          @Results(id = "role",value = {
                  @Result(column = "id",property = "permissions",many=@Many(select = "com.dong.springboot_mp_shiro.com.dong.mapper.PermissionMapper.findByPermissionId"))
          })
      
          @Select("select * from pe_role where id in (select role_id from pe_user_role where user_id =#{v} )")
          public Role findById(String id);
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      PermissionMapper

      import com.baomidou.mybatisplus.core.mapper.BaseMapper;
      import com.dong.springboot_mp_shiro.com.dong.pojo.Permission;
      import org.apache.ibatis.annotations.Mapper;
      import org.apache.ibatis.annotations.Select;
      @Mapper
      public interface PermissionMapper extends BaseMapper<Permission> {
      
          @Select("select * from pe_permission where id in (select permission_id from pe_role_permission where role_id =#{v})")
          public Permission findByPermissionId(String permissionId);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    5. service层

      接口:

      IUserService

      public interface IUserService {
          public int save(Users users);
      
          public Users baseFindUser(String name);
      
          public Users findUserDetail(String Name);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      IRoleService

      public interface IRoleService {
      }
      
      • 1
      • 2

      IPermissionService

      public interface IPermissionService {
      }
      
      • 1
      • 2

      实现类:

      UserServiceImp

      @Service
      public class UserServiceImp implements IUserService {
      
        @Autowired(required = false)
        private UserMapper uMapper;
      
        @Override
        public int save(Users users) {
          System.out.println("service:"+ users);
      
          // 获取salt字符串
          String salt = DigestsUtil.generateSalt();
          // 密码加密
          String password = DigestsUtil.generatePassword(users.getPassword(), salt);
      
          users.setPassword(password);
          users.setSalt(salt);
      
          int res = uMapper.save(users);
          return res;
        }
      
        @Override
        public Users baseFindUser(String name) {
          Users baseUser = uMapper.findBaseUser(name);
          return baseUser;
        }
      
        @Override
        public Users findUserDetail(String name) {
          Users userDetail = uMapper.findUserDetail(name);
          return userDetail;
        }
      }
      
      • 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
    6. controller层

      @RestController
      public class UserController {
          @Autowired(required = false)
          private UserServiceImp service;
      
          // 首页
          @RequiresPermissions("user-home")
          @RequestMapping("/user/home")
          public  String home(){
              return "访问个人主页成功";
          }
      
          // 用户注册
          @RequiresPermissions("user-add")
          @RequestMapping("/user/{id}")
          public String save(@PathVariable String id){
              /*int res = service.save(users);
              if(res>0){
                  return "添加成功";
              }else{
                  return "添加失败";
              }*/
              return "新增成功";
          }
      
          @RequiresPermissions("user-delete")
          @RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)
          public String delete(@PathVariable String id){
              return "删除成功";
          }
      
          @RequiresPermissions("user-update")
          @RequestMapping(value = "/user/{id}",method = RequestMethod.PUT)
          public String update(@PathVariable String id){
              return "修改成功";
          }
      
          @RequiresPermissions("user-find")
          @RequestMapping(value = "/user",method = RequestMethod.GET)
          public String find(){
              return "查询成功";
          }
      
          // 登录认证
          @RequestMapping("/login")
          public String login(Users users){
              try {
                  // 构造登录令牌
                  UsernamePasswordToken token = new UsernamePasswordToken(users.getUsername(), users.getPassword());
                  // 获取subject
                  Subject subject = SecurityUtils.getSubject();
                  // 调用subject认证
                  subject.login(token);
                  return "登录成功";
              } catch (AuthenticationException e) {
                  return  "用户名或密码错误";
              }
          }
      
          // 未登录跳转
          @RequestMapping("/autherror")
          public String autherror(){
              return "未认证,请登录";
          }
      }
      
      • 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

      ==@RequiresPermissions(" "):==标注访问该资源需要的权限

      • 执行subject.long登录方法,执行Reaml的AuthenticationException方法

      • 鉴权授权,执行Reaml的AuthorizationInfo方法

    7. MyRealm

      public class MyRealm extends AuthorizingRealm {
      
          @Autowired(required = false)
          private UserServiceImp serviceImp;
      
           // 授权鉴权
          @Override
          protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
              // 获取已经认证的用户数据
              Users users = (Users) principalCollection.getPrimaryPrincipal();
      
              // 查询用户的详细信息
              Users userDetail = serviceImp.findUserDetail(users.getUsername());
      
              HashSet<String> perms = new HashSet<>(); // 权限set集合
              HashSet<String> roles = new HashSet<>(); // 角色set集合
      
              for(Role role: userDetail.getRolesList() ){
                  roles.add(role.getCode());
                  for(Permission permission: role.getPermissions() ){
                      perms.add(permission.getCode());
                  }
              }
              SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
              info.setStringPermissions(perms);
              info.setRoles(roles);
              return info;
          }
      
          // 认证
          @Override
          protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
             // 获取用户登陆输入的密码(token)
              UsernamePasswordToken upToken =  (UsernamePasswordToken)authenticationToken;
              // 用户输入的账号
              String username = upToken.getUsername();
              Users users = serviceImp.baseFindUser(username);
              if(users != null){
                  SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(users, users.getPassword(), ByteSource.Util.bytes(users.getSalt()), "MyRealm");
                  return info;
              }
              // 账号查不到,返回null(抛出异常)
              return null;
          }
      
          @PostConstruct   // 属性初始化
          public void  initCredentialsMatcher(){
              // 指定密码算法
              HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);
              // 指定迭代次数
              hashedCredentialsMatcher.setHashIterations(DigestsUtil.COUNTS);
              // 生成密码比较器
              setCredentialsMatcher(hashedCredentialsMatcher);
          }
      }
      
      • 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

      @PostConstruct注解,属性初始化

      加密工具类

      public class DigestsUtil {
          // 编码方式
          public static final String SHA1="SHA-1";
          // 加密次数
          public static final Integer COUNTS=369;
      
          //  获取salt字符串
          public static String generateSalt(){
              SecureRandomNumberGenerator secureRandomNumberGenerator = new SecureRandomNumberGenerator();
              return secureRandomNumberGenerator.nextBytes().toHex();
          }
      
          // 生成密文密码
          public static String generatePassword(String input,String salt){
              return new SimpleHash(SHA1,input,salt,COUNTS).toString();
          }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
    8. Shiro配置类:ShiroConfiguration

      @Configuration
      public class ShiroConfiguration {
          /**
           * 1.创建shiro自带cookie对象
           */
          @Bean
          public SimpleCookie sessionIdCookie(){
              SimpleCookie simpleCookie = new SimpleCookie();
              simpleCookie.setName("ShiroSession");
              return simpleCookie;
          }
      
          //2.创建realm
          @Bean
          public MyRealm getRealm() {
              return new MyRealm();    //new 自定义的Reaml
          }
      
          /**
           * 3.创建会话管理器
           */
          @Bean
          public DefaultWebSessionManager sessionManager(){
              DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
              sessionManager.setSessionValidationSchedulerEnabled(false);
              sessionManager.setSessionIdCookieEnabled(true);
              sessionManager.setSessionIdCookie(sessionIdCookie());
              sessionManager.setGlobalSessionTimeout(3600000);
              return sessionManager;
          }
      
          //4.创建安全管理器
          @Bean
          public SecurityManager defaultWebSecurityManager() {
              DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
              securityManager.setRealm(getRealm());
              securityManager.setSessionManager(sessionManager());
              return securityManager;
          }
      
          /**
           * 5.保证实现了Shiro内部lifecycle函数的bean执行
           */
          @Bean(name = "lifecycleBeanPostProcessor")
          public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
              return new LifecycleBeanPostProcessor();
          }
      
          /**
           * 6.开启对shiro注解的支持
           *   AOP式方法级权限检查
           */
          @Bean
          @DependsOn("lifecycleBeanPostProcessor")
          public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
              DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
              defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
              return defaultAdvisorAutoProxyCreator;
          }
      
          /**
           * 7.配合DefaultAdvisorAutoProxyCreator事项注解权限校验
           */
          @Bean
          public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {
              AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
              authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager());
              return authorizationAttributeSourceAdvisor;
          }
      
          /*
          * 8.配置shiro的过滤器工厂再web程序中,shiro进行权限控制全部是通过一组过滤器集合进行控制
          * */
          @Bean
          public ShiroFilterFactoryBean shiroFilter(){
              //  1.创建过滤工厂
              ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
              // 2.设置安全管理器
              filterFactoryBean.setSecurityManager(defaultWebSecurityManager());
              // 3.通用配置(跳转登录页面,为授权跳转的页面)
              filterFactoryBean.setLoginUrl("/autherror");
              //4.设置过滤器集合
              //key = 拦截的url地址
              //value = 过滤器类型
              LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
              filterMap.put("/login","anon");//当前请求地址可以匿名访问
              filterMap.put("/user/**","authc");// 当前请求地址必须认证之后才可以访问
      			// 在过滤器工程内设置系统过滤器
            filterFactoryBean.setFilterChainDefinitionMap(filterMap);
              return filterFactoryBean;
          }
      }
      
      • 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
    9. 统一异常处理器

      @ControllerAdvice
      public class UserControllerAdv {
      
          @ExceptionHandler(value = AuthorizationException.class)
          @ResponseBody
          public String tongyi(HttpServletRequest request , HttpServletResponse response, AuthorizationException e){
              return "未授权---统一异常处理器";
          }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

    Shiro实现分布式会话SessionManager

    代码结构:代码结构和SpringBoot整合Shiro中的案例相同

    问题:如图

    在这里插入图片描述

    解决思路:将当前的session会话存到缓存Redis中

    在这里插入图片描述

    实现步骤:

    1. 创建RedisSessionDao extends AbstractSessionDAO
    2. 配置ShiroConfig

    代码实现:

    1. RedisSessionDao

      public class RedisSessionDao extends AbstractSessionDAO {
      
          @Autowired
          private RedisTemplate redisTemplate;
        
          //创建会话
          @Override
          protected Serializable doCreate(Session session) {
              Serializable sessionId = generateSessionId(session);
              assignSessionId(session, sessionId);
              redisTemplate.opsForValue().set(sessionId,session);
              return sessionId;
          }
      
          @Override
          protected Session doReadSession(Serializable sessionId) {
              return (Session) redisTemplate.opsForValue().get(sessionId);
          }
      
          @Override
          public void delete(Session session) {
              redisTemplate.delete(session.getId());
          }
      
          @Override
          public Collection<Session> getActiveSessions() {
              return Collections.emptySet();
          }
      
          @Override
          public void update(Session session) {
              redisTemplate.opsForValue().set(session.getId(),session);
          }
      
      }
      
      • 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
    2. 需要操作Redis,整合Redis

      1. 导入redis坐标

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>
        
        • 1
        • 2
        • 3
        • 4
      2. yaml主配置文件配置redis

        server:
          port: 8080
        #配置数据源
        spring:
          datasource:
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://localhost:3306/spring?serverTimezone=GMT
            username: root
            password: 123456
          redis:
            port: 6379
        
        #配置自动驼峰映射
        mybatis:
          configuration:
            map-underscore-to-camel-case: true
          type-aliases-package: com.dong.pojo
        #MP配置自动驼峰映射
        mybatis-plus:
          configuration:
            map-underscore-to-camel-case: true
            log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #mybatis所执行的sql输出控制台
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
      3. ShiroConfig

        向容器中注入一个SessionDao,把SessionDao绑定给会话管理器

        @Configuration
        public class ShiroConfiguration {
            /**
             * 1.创建shiro自带cookie对象
             */
            @Bean
            public SimpleCookie sessionIdCookie(){
                SimpleCookie simpleCookie = new SimpleCookie();
                simpleCookie.setName("ShiroSession");
                return simpleCookie;
            }
        
            //2.创建realm
            @Bean
            public MyRealm getRealm() {
                return new MyRealm();
            }
        
            // 向容器中注入一个SessionDao
            @Bean
            public SessionDAO redisSessionDao(){
                RedisSessionDao sessionDAO =   new RedisSessionDao();
                return sessionDAO;
            }
        
            /**
             * 3.创建会话管理器
             */
            @Bean
            public DefaultWebSessionManager sessionManager(){
                DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
              	//把SessionDao绑定给会话管理器
                sessionManager.setSessionDAO(redisSessionDao()); 
              	
                sessionManager.setSessionValidationSchedulerEnabled(false);
                sessionManager.setSessionIdCookieEnabled(true);
                sessionManager.setSessionIdCookie(sessionIdCookie());
                sessionManager.setGlobalSessionTimeout(3600000);
                return sessionManager;
            }
        
            //4.创建安全管理器
            @Bean
            public SecurityManager defaultWebSecurityManager() {
                DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
                securityManager.setRealm(getRealm());
                securityManager.setSessionManager(sessionManager());
                return securityManager;
            }
        
            /**
             * 5.保证实现了Shiro内部lifecycle函数的bean执行
             */
            @Bean(name = "lifecycleBeanPostProcessor")
            public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
                return new LifecycleBeanPostProcessor();
            }
        
            /**
             * 6.开启对shiro注解的支持
             *   AOP式方法级权限检查
             */
            @Bean
            @DependsOn("lifecycleBeanPostProcessor")
            public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
                DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
                defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
                return defaultAdvisorAutoProxyCreator;
            }
        
            /**
             * 7.配合DefaultAdvisorAutoProxyCreator事项注解权限校验
             */
            @Bean
            public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {
                AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
                authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager());
                return authorizationAttributeSourceAdvisor;
            }
        
            /*
            * 8.配置shiro的过滤器工厂再web程序中,shiro进行权限控制全部是通过一组过滤器集合进行控制
            * */
            @Bean
            public ShiroFilterFactoryBean shiroFilter(){
                //  1.创建过滤工厂
                ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
                // 2.设置安全管理器
                filterFactoryBean.setSecurityManager(defaultWebSecurityManager());
                // 3.通用配置(跳转登录页面,为授权跳转的页面)
                filterFactoryBean.setLoginUrl("/autherror");
                //4.设置过滤器集合
                //key = 拦截的url地址
                //value = 过滤器类型
                LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
                filterMap.put("/login","anon");//当前请求地址可以匿名访问
                filterMap.put("/user/**","authc");
                filterFactoryBean.setFilterChainDefinitionMap(filterMap);
                return filterFactoryBean;
            }
        }
        
        • 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
        • 94
        • 95
        • 96
        • 97
        • 98
        • 99
        • 100
        • 101

  • 相关阅读:
    300万数据导入导出优化方案,从80s优化到8s(实测)
    第2.2章 StarRocks表设计——排序键和数据模型
    Pygame中Sprite的使用方法6-5
    【1】初识Java
    OS2.1.4:进程通信
    二叉树问题——验证二叉搜索树
    linux硬盘挂载
    Xcode报错“compact unwind compressed function offset doesn‘t fit in 24 bits
    Docker-consul容器服务更新与发现
    Linux - Django + Nginx + uwsgi 部署项目 - 安装 uWSGI 服务器 -(4)
  • 原文地址:https://blog.csdn.net/HakerDONG/article/details/134432513