精华内容
下载资源
问答
  • 降低Cache失效率--编译器优化

    千次阅读 热门讨论 2014-01-04 01:14:40
    (Compulsory miss): 第一次访问一个块,该块不在 Cache中, 需从下一级存储中调入 Cache, 这就是强制性失效。这种失效也称为 冷启动失效 ,或 首次访问失效 。(增加块大小,预取) (2). 容量失效 ...

    前言:

    之前看了酷壳 @我的上铺叫路遥 投稿的"七个示例科普CPU Cache",其实没认真看完!

    丫的,我翻阅了一下《计算机系统结构》的书,把cache那章阅读了下!

    发现了新大陆,对自己当时学到的知识的领悟和体会似乎有了新的感受!计算机专业课,其实我都挺认真的学过的,哈哈,只不过...我把我觉得有用的摘录下!

     

    降低Cache失效率的方法

    许多相关Cache的研究都致力于降低Cache的失效率。这里就讨论这个!

    按照产生失效的原因不同,可以把失效分为以下3类(简称为"3C"):

    (1). 强制性失效 (Compulsory miss): 当第一次访问一个块时,该块不在 Cache中, 需从下一级存储中调入 Cache, 这就是强制性失效。这种失效也称为冷启动失效,或首次访问失效。(增加块大小,预取)

    (2). 容量失效 (Capacity miss): 如果程序执行时所需的块不能全部调入 Cache 中, 则当某些块被替换后, 若又重新被访问, 就会发生失效。这种失效称为容量失效。(增加容量) 抖动现象。

    (3). 冲突失效 (Conflict miss): 在组相联或直接映像 Cache 中, 若太多的块映像到同一组(块)中,则会出现改组中某个块被别的块替换、然后又被重新访问的情况。这就是发生了冲突失效。这种失效也称为碰撞失效 (collision) 或干扰失效 (interference)。(提高相联度)

    SPEC92基础测试程序给出了这三种失效在不同容量不同相联度下的失效率情况略。总结的情况如下:

    (1) 相联度越高,冲突失效就越少。

    (2) 强制性失效和容量失效不受相联度的影响。

    (3) 强制性生效不受 Cache 容量的影响,但容量失效却随着容量的增加而减少。

    (4) 表中的数据符合 2:1 的 Cache 经验规则,即大小为N的直接映像 Cache 的失效率约等于大小为 N/2 的 2 路组相联 Cache 的失效率

     

    编译器优化

    前面所介绍的技术(增加块大小、增加Cache容量、提高相联度、伪相联、硬件预取以及预取指令等)都需要改变或者增加硬件。下面介绍的方法,无需对硬件做任何改动就可以降低失效率。或许,这也是能对我们的程序效率有帮助的地方

    我们能很容易地重新组织程序而不影响程序的正确性。例如,把一个程序中的几个过程重新排序,就可能会减少冲突失效,从而降低指令失效率。McFarling研究了如何使用记录信息来判断指令组之间可能发生的冲突,并将指令重新排序以减少失效。他发现,这样可将容量为2KB、块大小为4KB的直接映像指令Cache的失效率降低50%;对于容量为8KB的 Cache,可将失效率降低75%。他还发现当能够是某些指令根本就不进入 Cache 时,可以得到最佳性能。但即使不这么做,优化后的程序在直接映像 Cache 中的失效率也低于未优化程序在同样大小的8路组相联映像 Cache 中的失效率。

    数据对存储位置的限制比指令对存储位置的限制还要少,因此更便于调整顺序。我们对数据进行变换的目的是改善数据的空间局部性和时间局部性。例如,可以把对数据的运算改为对存放在同一 Cache 块中的所有数据进行操作,而不是按照程序员原来随意书写的顺序访问数组元素。

    1. 数组合并 ( merging arrays )

    这种技术通过提高空间局部性来减少失效次数。有些程序同时用相同的索引来访问若干数组中的同一维。这些访问可能会相互干扰,导致冲突失效。我们可以这样来消除这种危险:将这些相互独立的数组合并成为一个复合数组,使得一个 Cache 块中能包含全部所需的元素。

    /* 修改 */

    /* 修改 */

     

    这个例子有一个有趣的特点:如果程序员能正确地使用记录数组,他就能获得与本优化相同的益处。

    2. 内外循环交换 ( loop interchange )

    有些程序中含有嵌套循环,程序没有按照数据在存储器中存储的顺序进行访问。在这种情况下,只要简单地交换循环的嵌套关系,就能使程序按数据在存储器中存储的顺序进行访问。和前一个例子一样,这种技术也是通过提高空间局部性来减少失效次数,重新排列访问顺序使得在一个 Cache 块被替换之前,能最大限度地利用块中的数据。

    /* 修改 */

     

    /* 修改 */

    修改前程序以100个字的跨距访问存储器,而修改后的程序顺序地访问一个 Cache 块中的元素,然后再访问下一块中的元素。这种优化技术在不改变执行的指令条数的前提下,提高了 Cache 的性能。

    简单测试:

    编译: 

    > gcc -Wall a.c -o a

    > gcc -Wall b.c -o b

    结果: //没看CPU的情况,看起来貌似有效。。。

    3. 循环融合 ( loop fusion )

    有些程序含有几部分独立的程序段,它们用相同的循环访问同样的数组,对相同的数据做不同的运算。通过将它们融合为单一的循环,能使读入 Cache 的数据在被替换出去之前,得到反复的使用。和前面的两种技术不同,这种优化的目标是通过改进时间局部性来减少失效次数。

    /* 修改前 */

    /* 修改后 */

    修改前的程序在两个地方访问数组a 和 c,一次是在第一个循环里,另一次是在第二个循环里。两次循环分隔较远,可能会产生重复失效,即在第一个循环中访问某个元素失效之后,虽已将相应块调入 Cache,但在第二个循环中再次访问该元素时,还可能产生失效。而在修改后的程序中,第二条语句直接利用了第一条语句访问 Cache 的结果,无需再到存储器去取。

     

    4. 分块

    这种优化可能是 Cache 优化技术中最著名的一种,它也是通过改进时间局部性来减少时效。下面仍考虑对多个数组的访问,有些数组是按行访问,而有些规则是按列访问。无论数组是按行优先还是按列优先存储,都不能解决问题,因为在每一次循环中既有按行访问也有按列访问。这种正交的访问意味着前面的变换方法,如内外循环交换,对此军无能为力。

    分块算法不是对数组的整行或整列进行访问,而是对子矩阵或块进行操作。其目的仍然是使一个 Cache 块在被替换之前,对它的访问次数达到最多。下面这个矩阵乘法程序有助于我们理解为什么要采用这种优化技术。

     

    还有好多

     

     

    #坚持:有一定的理论素养,却又始终以实践为本!

     

     

     

    展开全文
  • 在上篇文章讲解整合分布式缓存Redis埋下了一个伏笔:如何让我们的缓存注解支持自定义TTL失效时间呢? 这篇文章本可以不用写,因为其实基于Redis的RedisCacheManager它本身天生就是能够针对不同的Cache配置不同的...

    每篇一句

    不为外界技术更替而动摇,不为眼前无收益而动摇。学一门技术,学到的不仅仅是知识,还有决胜于千里之外的格局

    前言

    在上篇文章讲解整合分布式缓存Redis时埋下了一个伏笔:如何让我们的缓存注解支持自定义TTL失效时间呢?

    这篇文章本可以不用写,因为其实基于RedisRedisCacheManager它本身天生就是能够针对不同的Cache配置不同的TTL的。但是我发现有的小伙伴觉得使用得还是不太方便,希望能在使用注解的时候直接控制失效时间,为了帮助解决小伙伴的这个困惑,这就是我书写本文的目的~

    Spring Cache与失效时间TTL

    首先此处我有必要再次强调一点:Spring Cache抽象本省是并不支持Expire失效时间的设定的,我粗暴的把它归为了Spring Cache抽象的一个设计上的bug,可参考文章:【小家Spring】玩转Spring Cache — @Cacheable/@CachePut/@CacheEvict注解的原理深度剖析和使用

    若想在缓存注解上指定失效时间,必须具备如下两个基本条件:

    1. 缓存实现产品支持Expire失效时间(Ehcache、Redis等几乎所有第三方实现都支持)
    2. xxxCacheManager管理的xxxCache必须扩展了Expire的实现

    因为缓存的k-v键值对具有自动失效的特性实在太重要和太实用了,所以虽然org.springframework.cache.Cache它没有实现Expire,但好在第三方产品对Spring缓存标准实现的时候,大都实现了这个重要的失效策略,比如典型例子:RedisCache

    本文以最为常用的Redis缓存为例,介绍两种控制缓存失效时间的方式。

    实现Cache失效时间的两种通用方式

    接下来就以Redis Cache为例,介绍两种常用的、通用的管理缓存失效时间的方式。

    方式一:使用源生的RedisCacheManager进行集中式控制

    由于控制key的失效时间这一块非常的实用和重要,所以其实Spring Data Redis工程早就给与了支持(不管是1.x版本还是2.x版本)。因此话不多说,直接给个例子就非常清晰明了:

    1、准备Cache配置:

    @EnableCaching // 使用了CacheManager,别忘了开启它  否则无效
    @Configuration
    public class CacheConfig extends CachingConfigurerSupport {
    
        @Bean
        public CacheManager cacheManager() {
            RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofDays(1)) // 默认没有特殊指定的
                    .computePrefixWith(cacheName -> "caching:" + cacheName);
    
            // 针对不同cacheName,设置不同的过期时间
            Map<String, RedisCacheConfiguration> initialCacheConfiguration = new HashMap<String, RedisCacheConfiguration>() {{
                put("demoCache", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1))); //1小时
                put("demoCar", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10))); // 10分钟
                // ...
            }};
    
            RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory())
                    .cacheDefaults(defaultCacheConfig) // 默认配置(强烈建议配置上)。  比如动态创建出来的都会走此默认配置
                    .withInitialCacheConfigurations(initialCacheConfiguration) // 不同cache的个性化配置
                    .build();
            return redisCacheManager;
        }
    
        @Bean
        public RedisConnectionFactory redisConnectionFactory() {
            RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
            configuration.setHostName("10.102.132.150");
            configuration.setPort(6379);
            configuration.setDatabase(0);
            LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration);
            return factory;
        }
    
        @Bean
        public RedisTemplate<String, String> stringRedisTemplate() {
            RedisTemplate<String, String> redisTemplate = new StringRedisTemplate();
            redisTemplate.setConnectionFactory(redisConnectionFactory());
            return redisTemplate;
        }
    
    }
    

    使用示例:

    @Service
    public class CacheDemoServiceImpl implements CacheDemoService {
    
    
        @Caching(cacheable = {
                @Cacheable(cacheNames = "demoCache", key = "#id + 0"),
                @Cacheable(cacheNames = "demoCar", key = "#id + 10"),
                @Cacheable(cacheNames = "demoFsx", key = "#id + 100")
        })
        @Override
        public Object getFromDB(Integer id) {
            System.out.println("模拟去db查询~~~" + id);
            return "hello cache...";
        }
    }
    

    运行单元测试

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {RootConfig.class, CacheConfig.class})
    public class TestSpringBean {
    
        @Autowired
        private CacheDemoService cacheDemoService;
        @Autowired
        private CacheManager cacheManager;
    
    
        @Test
        public void test1() {
            cacheDemoService.getFromDB(1);
            cacheDemoService.getFromDB(1);
    
            System.out.println("----------验证缓存是否生效----------");
            Cache cache = cacheManager.getCache("demoCache");
            System.out.println(cache);
            System.out.println(cache.get(1, String.class));
        }
    }
    

    打印结果如下:

    模拟去db查询~~~1
    ----------验证缓存是否生效----------
    org.springframework.data.redis.cache.RedisCache@721eb7df
    hello cache...
    

    缓存生效。去Redis服务端查看对应的key情况:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    眼睛尖的小伙伴可能发现了,只有最后一个key前面有caching前缀,其余两个木有,这是为何呢?
    这是我故意留出来的一个小问题,留给小伙伴们自行思考~

    由此可见,通过RedisCacheManager完成了对不同的Cache进行了失效时间的定制化配置,达到了我们的目的。

    小细节

    针对如上的配置,总结如下两点小细节使时需要注意:

    1. 即使禁用前缀disableKeyPrefix(),也是不会影响对应CacheName的TTL(因为TTL针对的是Cache,而不是key
    2. 每个CacheName都可以对应一个RedisCacheConfiguration(它里面有众多属性都可以个性化),若没配置的(比如动态生成的)都走默认配置

    Spring提供的在RedisCacheManager来统一管理Cache的TTL,这种集中式的管理其实是我赞同的方式,若让他分散在各个缓存注解上,反而非常不利于后期的维护管理~~~因此这种方式我也是推荐的

    方式二:自定义cacheNames方式

    虽然我觉得方案一已经能够满足我们需求了,但是广大小伙伴还是觉得使用起来不太自由,毕竟大多数Cache都希望是通过在注解指定CacheNames让其自动生成就行(其实提前追备好有助于提升初次访问的性能)。但是为了便用性摆第一位的话,那就应广大小伙伴的要求,写出本例供以参考

    其实最终我们期望的使用方式如下:

    @Cacheable(cacheNames = "demoCache#3600", key = "#id + 0"),
    

    通过#分隔,后面部分表示此Cache的TTL(单位:秒)

    为了实现这个效果,其实并不难,只需要对RedisCacheManager稍稍的改造一下即可达到目的:

    public class MyRedisCacheManager extends RedisCacheManager {
    
        public MyRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
            super(cacheWriter, defaultCacheConfiguration);
        }
    
        @Override
        protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
            String[] array = StringUtils.delimitedListToStringArray(name, "#");
            name = array[0];
            if (array.length > 1) { // 解析TTL
                long ttl = Long.parseLong(array[1]);
                cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl)); // 注意单位我此处用的是秒,而非毫秒
            }
            return super.createRedisCache(name, cacheConfig);
        }
    
    }
    

    使用我自定义的MyRedisCacheManager配置CacheConfig如下:

    @EnableCaching // 使用了CacheManager,别忘了开启它  否则无效
    @Configuration
    public class CacheConfig extends CachingConfigurerSupport {
    
        @Bean
        public CacheManager cacheManager() {
            RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofDays(1))
                    .computePrefixWith(cacheName -> "caching:" + cacheName);
    
            MyRedisCacheManager redisCacheManager = new MyRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory()), defaultCacheConfig);
            return redisCacheManager;
        }
    
        @Bean
        public RedisConnectionFactory redisConnectionFactory() {
            RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
            configuration.setHostName("10.102.132.150");
            configuration.setPort(6379);
            configuration.setDatabase(0);
            LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration);
            return factory;
        }
    
        @Bean
        public RedisTemplate<String, String> stringRedisTemplate() {
            RedisTemplate<String, String> redisTemplate = new StringRedisTemplate();
            redisTemplate.setConnectionFactory(redisConnectionFactory());
            return redisTemplate;
        }
    
    }
    

    使用示例如下:

    @Service
    public class CacheDemoServiceImpl implements CacheDemoService {
    
        @Cacheable(cacheNames = {
                "demoCache#3600", "demoCar#600", "demoFsx"
        }, key = "#id")
        @Override
        public Object getFromDB(Integer id) {
            System.out.println("模拟去db查询~~~" + id);
            return "hello cache...";
        }
    }
    

    打印结果:

    模拟去db查询~~~1
    ----------验证缓存是否生效----------
    org.springframework.data.redis.cache.RedisCache@53f4c1e6
    hello cache...
    

    缓存生效。Redis Server里查到缓存结果如图(TTL都分别生效了):
    在这里插入图片描述

    说明:demoFsx没有指定TTL,所以走了默认值ttl=1天

    小细节
    1. 同样的,禁用前缀并不影响它的TTL的生效与否
    2. 若在CacheManager已经配置了Cache对应的TTL配置,那就以CacheManager里配置的为准
    3. 多个方法里配置了同一个CacheNameTTL以第一个执行的生成Cache的方法配置的为准

    总之一个原则:TTL是和Cache绑定的,且是在Cache在首次被初始化的时候就被指定好了

    关于此方案,其实还可以扩展一下,比如可以扩展成可配置的如下:

    @Cacheable(cacheNames = "demoCache#${cache.timeout:1800}",key = "#id")
    

    方案提出来,实现此处我就不写了,因为还是比较容易实现的。

    TTL能精确到key吗?

    据我了解,这是很多小伙伴都想问的一个问题,但其实我一直不明白为何有非常多的小伙伴会有这种呼声呢?

    很多小伙伴是希望把TTL写在key上,形如这样书写:

    @Cacheable(cacheNames = "demoCache",key = "#id_3600")
    

    其实这么想的小伙伴,我觉得根本原因是不太能理解cacheNameRedis的key的关系导致的(本文以Redis为例~)

    我此处不直接解答这个问题,但我对此额外抛出3个问题,相信答案就不攻自破了:

    1. 为何同一个Cache下管理的key你需要不同的TTL???(这种设计本身就不合理吧)
    2. 在不禁用前缀的情况下,cacheName默认都会反映到key上。因此即使你有这种特殊需求,你也可以通过定义特殊的CacheName来实现
    3. 若你真想控制到key这种细粒度,我只能说:实现成本太高了且会打破一定的封装性,后续扩展受限

    综合来说,不管从场景上还是技术上,我都是极力不推荐这种行为的。

    总结

    本文主要介绍了让缓存注解支持TTL失效时间,提供的两种方式都可以用在生产环境中。合理的使用、控制失效时间,能让你的应用更加的高效,缓存利用得更合理。

    另外关于Spring缓存其实还有一个重要知识点:缓存即将过期时主动刷新缓存
    因为缓存失效后,就会有一些请求会打到DB上,这段时间如果是高并发的话DB压力就很大(sync=true可以有一定的缓解作用),DB就很危险,容易造成雪崩。
    因此我们是期望在缓存即将过期的某一时间点,后台主动去更新缓存以确保前端请求的缓存命中率。关于这部分的实现,只有在高并发系统下才有需求,有兴趣和有需要的小伙伴可往这方面考虑一把~


    关注A哥

    Author A哥(YourBatman)
    个人站点 www.yourbatman.cn
    E-mail yourbatman@qq.com
    微 信 fsx641385712
    活跃平台
    公众号 BAT的乌托邦(ID:BAT-utopia)
    知识星球 BAT的乌托邦
    每日文章推荐 每日文章推荐

    BAT的乌托邦

    展开全文
  • 一般memcached的数据都是定时失效的,数据失效时一般会再次去访问取数据接口,然后将其更新至memcached中。这时就会有一个问题,某个数据失效时,恰好同时有大量的客户端访问该数据,这时这些客户端都会发现该...


    memcached一般用于在访问一些性能相对低下的数据接口时(如数据库),为了保证这些数据接口的稳定性,加上memcached以减少访问次数,保证这些数据接口的健壮性。一般memcached的数据都是定时失效的,当数据失效时一般会再次去访问取数据接口,然后将其更新至memcached中。这时就会有一个问题,当某个数据失效时,恰好同时有大量的客户端访问该数据,这时这些客户端都会发现该数据失效,然后都会去调用数据接口去取数据更新,这自然就瞬间地使数据接口失去了memcached的保护,有可能造成系统的故障。

            那么如何解决这个问题呢?

            第一种:数据不失效,定时更新。即数据存放在memcached中永不失效,但是会有一个定时任务,定时的去更新这个数据。

            第二种:既然该问题的症结在于在数据失效时,会有多个客户端去调用数据接口,那么只要想办法在数据失效时只有一个客户端能访问数据接口即可,要做到这点,自然的想法是加锁:如下:

    1. object value = memcached.get(key);  
    2. if(null==value){  
    3.         synchronized{  
    4.                value = memcached.get(key);  
    5.                if(null==value){  
    6.                       value = db.get(key);  
    7.                       memcached.set(key,value);  
    8.                 }  
    9.         }  
    10. }  
    11. return value;  

            这样做的前提是你必须保证这个函数的类是单例的,显然在服务器集群中不可能有这样的场景,那么如果在群集间加锁呢?解铃还需系铃人,既然大家共用一个memcached服务器,那么就使用memcached来实现这个锁机制。即当客户端取不到数据时,先在memcached中设置一个flag表明当前客户端在更新该数据,当其它客户端也来访问时发现失效后就等待直到更新好数据为目。

    1. object value = memcahced.get(key);  
    2. if(null=value){  
    3.     if(memcached.add(key)){  
    4.         value = db.get();  
    5.         memcached.set(key,value);  
    6.     }else{  
    7.         while(true){  
    8.             Thread.sleep(50);  
    9.              value=memcached.get(key);  
    10.              if(null!=value){  
    11.                   break;  
    12.              }  
    13.         }  
    14.     }  
    15. }  
    16. return value;  
             memcached中的add方法是实现该功能的关键,该方法是判断memcached中是否有某个key存在,如果存在则返回false,否则返回true,并添加该key值,如果没有该方法,显然我们只能再一次的通过get 和set去设置该值,显然这样做是线程不安全的,有可能有多个客户端同时取为空,同时去取数据并更新。

              上述的方法存在的缺陷时,一旦数据失效,所有客户端要等待某个客户端更新完毕,这样势必增加服务器压力,可以通过在key失效之间的一段时间就触发更新的方式来解决这个问题。


    展开全文
  • 失效访问控制

    千次阅读 2018-08-16 11:25:05
    失效访问控制 出现的问题 文件包含/目录遍历 权限绕过(越权) 权限提升(提权) 不安全直接对象的引用 访问控制的(防御)思路 基于角色的访问控制(RBAC) 自由访问控制(DAC) 强访问控制(MAC) 基于权限的...

    失效的访问控制

    这是我在OWASP上几篇文章翻译整理加删减总结出的一个关于失效的访问控制的检查可解决的文章。勉强算个原创吧。

    由于缺乏自动化的检测和应用程序开发人员缺乏有效 的功能测试,因而访问控制缺陷很常见。导致攻击者可以冒充用户、管理员或拥有特权的用户,或者创建、访问、更新或删除任何记录。

    出现的问题

    文件包含/目录遍历

    许多web应用使用文件管理作为它们日常操作的一部分。但他们使用没有被好好设计的输入验证方法,攻击者可以利用(这个漏洞)来修改或写入文件,甚至执行任意代码。

    传统的web服务器和web应用程序用身份验证来控制文件资源访问。web服务器尝试将用户的文件限制在“根目录”或“web文档根”中,后者标识文件系统层面的物理目录。用户必须将此目录十位web应用程序层次结构的基本目录。

    许多web应用程序使用服务器端脚本来包含不同类型的文件。如管理图像,模板,加载静态文本等,但如果未正确验证输入参数(如表单,cookie)这些程序会暴露安全漏洞。这种问题出现在路径遍历/文件包含攻击中。通过利用此类漏洞,攻击者能读取它们通常无法读取的目录或文件,访问web文档根目录之外的数据,或包含来自外部网络的脚本或其他类型文件。

    如臭名昭著的%5c 暴库或dot-dot-slash (../)目录遍历,目录爬升或回溯。

    例子

    http://example.com/getUserProfile.jsp?item=ikki.html 
    http://example.com/getUserProfile.jsp?item=../../../../etc/passwd

    若getUserProfile.jsp是从文件加载静态信息并向用户显示,如果在访问控制不理想的情况下,攻击者可以构造相对路径,读取etc/passwd的文件内容。

    其他地方也可能有类似漏洞如cookie:

    Cookie:USER = 1826cc8f:PSTYLE = GreenDotRed
    Cookie:USER = 1826cc8f:PSTYLE = .. / .. / .. / .. / etc / passwd

    也可能包含外部网站的文件:

    http://example.com/index.php?file=http://www.owasp.org/malicioustxt

    如果可接受协议类参数,也可以构造如下攻击:

    http://example.com/index.php?file=file:///etc/passwd

    或探测本地服务:

    http://example.com/index.php?file=http://localhost:8080http://example.com/index.php?file=http://192.168.0.2:9080

    甚至可以不使用任何目录遍历字符开显示CGI组件源代码:

    http://example.com/main.cgi?home=main.cgi

    main.cgi的组件和普通html静态文件在同一个目录中,在某些情况下,攻击者使用. %00 null等的编码可以绕过扩展名校验。

    关于不同操作系统的路径分隔符

    Linux
    根目录:“/” 
    目录分隔符:“/”
    Windows
    根目录:“<驱动器号>:\”   
    目录分隔符:“\”或“/”
    Mac OS
    根目录:“<驱动器号>:” 
    目录分隔符:“:”

    url编码与双url编码绕过:

    %2e%2e%2f 表示 ../
    %2e%2e / 表示 ../ 
    ..%2f 表示 ../
    %2e%2e%5c 表示 .. \ 
    %2e%2e \ 表示 .. \ 
    ..%5c 代表 .. \ 
    %252e%252e%255c 代表 .. \ 
    ..%255c 代表 .. \等等。

    Unicode/UTF-8编码绕过

    ..%c0%af 表示 ../ 
    ..%c1%9c 代表 .. \

    Windows shell中,解析文件非常灵活,如以下任何内容附加到shell命令中使用的路径会导致函数没有区别:

    • 路径末端的尖括号“>”和“<”
    • 在路径末尾双引号(正确关闭)
    • 无关的当前目录标记,例如“./”或“。\”
    • 具有可能存在或可能不存在的任意项的无关父目录标记
    -  file.txt 
    -  file.txt ... 
    -  file.txt <spaces> 
    -  file.txt“”“” 
    -  file.txt <<< >>> < 
    -  ./././file.txt 
    - nonexistant / ../file.txt

    在任何shell命令或API调用中使用时,下面的符号会被丢弃,其中字符串被视为文件名:

    句号
    空格

    Windows UNC文件路径:用于引用SMB共享上的文件。有时,可以使应用程序引用远程UNC文件路径上的文件。如果是这样,Windows SMB服务器可能会将存储的凭据发送给攻击者,攻击者可以捕获并破解。这些也可以与自引用IP地址或域名一起使用来逃避过滤器,或者用于访问攻击者无法访问的SMB共享上的文件,但可以从Web服务器访问。

    \\ server_or_ip \ path \ to \ file.abc 
    \\\ server_or_ip \ path \ to \ file.abc

    Windows NT设备命名空间:用于指代Windows设备命名空间。某些引用将允许使用不同的路径访问文件系统。

    • 可能相当于驱动器号,例如c:\,甚至是没有指定字母的驱动器卷。

      \\.\GLOBALROOT\Device\HarddiskVolume1\
    • 指机器上的第一个光盘驱动器。

      \\.\CdRom0\

    权限绕过(水平越权)

    用户未经过身份验证访问资源,或注销后仍可访问资源,对不同用户访问的资源没有做很好的校验,如标准用户可访问管理员资源,或访问其他用户私有资源等。

    例子

    下面例子的url是管理员彩蛋的一部分:

     https://www.example.com/admin/addUser.jsp 

    访问这个页面你的HTTP请求如下:

    POST /admin/addUser.jsp HTTP/1.1
    Host: www.example.com
    [other HTTP headers]
    
    userID=fakeuser&role=3&group=grp001

    如果一个非管理员用户发送这个请求到服务器,会执行什么操作,在权限验证和访问控制不理想的情况下,非管理员用户通过构造管理员相应操作的数据包,也能达到管理员的权限。如增加/删除用户等。

    权限提升(垂直越权)

    权限提升是指用户权限从一个阶段提升到另一个阶段的问题,当用户访问的资源比通常情况下访问到的资源更多时,就发生了权限提示漏洞,应用程序应该阻止该权限提升或更改。权限提升一般是由于应用程序自身的缺陷引起的,最后导致程序执行的操作拥有比开发人员或系统管理员预期更多的权限。

    例子

    下面的HTTP POST请求允许属于grp001的用户访问#0001订单:

     POST /user/viewOrder.jsp HTTP/1.1
     Host: www.example.com
     ...
    
     groupID=grp001&orderID=0001

    如果对权限的校验不正常的情况,一个不属于grp001的用户修改groupID参数也可获得查看#0001的权限。

    操纵用户配置权限:下面服务器的响应显示校验成功后返回给用户的HTML中的隐藏字段。

    HTTP/1.1 200 OK
    Server: Netscape-Enterprise/6.0
    Date: Wed, 1 Apr 2006 13:51:20 GMT
    Set-Cookie: USER=aW78ryrGrTWs4MnOd32Fs51yDqp; path=/; domain=www.example.com 
    Set-Cookie: SESSION=k+KmKeHXTgDi1J5fT7Zz; path=/; domain= www.example.com
    Cache-Control: no-cache
    Pragma: No-cache 
    Content-length: 247
    Content-Type: text/html
    Expires: Thu, 01 Jan 1970 00:00:00 GMT
    Connection: close
    
    <form  name="autoriz" method="POST" action = "visual.jsp"> 
    <input type="hidden" name="profile" value="SysAdmin">
    <body onload="document.forms.autoriz.submit()">
    </td>
    </tr>

    如果我们将profile改为”SysAdmin”,可能会变成管理员。

    操纵条件值:在服务器发送错误消息时,该消息包含在一组相应代码中的特定参数中,如:

    @0`1`3`3``0`UC`1`Status`OK`SEC`5`1`0`ResultSet`0`PVValid`-1`0`0` Notifications`0`0`3`Command  Manager`0`0`0` StateToolsBar`0`0`0`    
    StateExecToolBar`0`0`0`FlagsToolBar`0

    如果我们将“PVValid”从-1改为0,那可能代表没有错误,从而通过管理员身份验证

    操纵IP地址:某些网站使用IP地址来限制访问或根据IP地址计算错误登录次数,如:

    X-Forwarded-For: 8.1.1.1

    如果可以修改X-Forwarded-For就可以绕过这种检验

    URL遍历:尝试遍历网站查看是否有页面漏掉权限检验

    /../.././userInfo.html

    弱SessionID:

    若SessionID加密算法很弱,或使用有规律的算法,可能会被攻击者猜到或解密,造成越权。

    不安全直接对象的引用

    当应用程序根据用户提供的输入提供对对象的直接访问时,会发生不安全的直接对象引用。 攻击者可以直接绕过授权并访问系统中的资源,例如数据库记录或文件。

    由于应用程序获取用户提供的输入并使用它来检索对象而不执行足够的授权检查。不安全的直接对象引用允许攻击者通过修改用于直接指向对象的参数值来直接绕过授权和访问资源。这些资源可以是属于其他用户的数据库条目,系统中的文件等。

    例子

    参数值直接用于数据库检索:

    http://foo.bar/somepage?invoice=12345

    参数invoice的值直接进入发票数据库检索,并将结果显示,如不对检索对象进行校验,那么攻击者可以遍历发票编号造成信息泄露。

    参数值直接在系统中操作:

    http://foo.bar/changepassword?user=someuser

    user参数值用于告诉应用程序用户访问哪个功能,若没有对用户本身作出限制,那么用户修改user参数,可能造成越权访问功能。

    访问控制的(防御)思路

    授权是应该授予或拒绝访问特定资源的请求的过程。Web应用程序需要访问控制以允许用户(具有不同的权限)使用该应用程序。他们还需要管理员来管理应用程序访问控制规则以及向用户和其他实体授予权限或权利。提供各种访问控制设计方法。要选择最合适的风险评估,需要执行风险评估以识别特定于您的应用程序的威胁和漏洞,以便适当的访问控制方法适合您的应用程序。

    基于角色的访问控制(RBAC)

    在基于角色的访问控制(RBAC)中,访问决策基于个人在组织或用户群中的角色和职责。

    定义角色的过程通常基于分析组织的基本目标和结构,并且通常与安全策略相关联。例如,在医疗机构中,用户的不同角色可能包括医生,护士,服务员,护士,患者等等。显然,这些成员需要不同级别的访问才能执行其功能,但也需要根据安全政策和任何相关法规(HIPAA,Gramm-Leach-Bliley等)。

    RBAC访问控制框架应该为Web应用程序安全管理员提供确定的“谁可以执行哪些操作,何时,从何处,以何种顺序以及在某些情况下在什么关系环境下“执行操作的能力。

    使用此方法的优点是:

    • 角色是根据组织结构分配的,重点是组织安全策略
    • 使用方便
    • 易于管理
    • 内置于大多数框架中
    • 符合职责分离和最低特权等安全原则

    使用此方法时可能遇到的问题:

    • 必须严格保持角色和访问的文档。
    • 除非有办法将角色与多租户功能要求相关联,例如Active Directory中的OU,否则无法有效实施多租户
    • 存在范围蔓延的趋势,例如可以给出比预期更多的访问和特权。或者,如果未执行适当的访问查看和后续撤销,则用户可能包含在两个角色中。
    • 不支持基于数据的访问控制

    使用RBAC时的注意事项是:

    • 必须使用严格的签名和流程来转让或委派角色。
    • 当用户将其角色更改为另一个角色时,管理员必须确保撤消先前的访问权限,以便在任何给定的时间点,仅在需要知道的基础上将用户分配给那些角色。
    • 必须使用严格的访问控制审查来执行RBAC保证。

    自由访问控制(DAC)

    自由访问控制(DAC)是一种基于用户身份和某些组成员身份限制对信息的访问的方法。访问决策通常基于授权给用户的授权,该授权基于他在认证时呈现的凭证(用户名,密码,硬件/软件令牌等)。在大多数典型的DAC模型中,信息所有者或任何资源都可以自行决定更改其权限 。

    DAC框架可以为Web应用程序安全管理员提供实现细粒度访问控制的能力。该模型可以作为基于数据的访问控制的实现的基础 。

    使用此模型的优点是:

    • 使用方便
    • 易于管理
    • 符合最小特权原则。
    • 对象所有者完全控制授予的访问权限

    使用此方法时可能遇到的问题:

    • 必须严格保持角色和访问的文档。
    • 除非有办法将角色与多租户功能要求相关联,例如Active Directory中的OU,否则无法有效实施多租户
    • 存在范围蔓延的趋势,例如可以给出比预期更多的访问和特权。

    使用DAC时的注意事项是:

    • 在给予信任的同时DAC保证必须使用严格的访问控制审查。

    强访问控制(MAC)

    强制访问控制(MAC)确保组织安全策略的实施不依赖于Web应用程序用户的合规性。MAC通过在信息上分配敏感标签并将其与用户操作的灵敏度级别进行比较来保护信息。MAC通常适用于极其安全的系统,包括多级安全军事应用或关键任务数据应用。

    使用此方法的优点是:

    • 对对象的访问权限取决于对象的敏感性
    • 严格遵守基于需要知识的访问,并且范围蠕变具有最小可能性
    • 只有管理员才能授予访问权限

    使用此方法时可能遇到的问题:

    • 实施起来困难且昂贵
    • 不灵活

    使用MAC时的注意事项是:

    • 在适当和务实的层面上进行分类和敏感性分配
    • 必须执行MAC保证以确保对象的分类处于适当的级别。

    基于权限的访问控制

    基于权限的访问控制中的关键概念是将应用程序操作抽象为一组权限。权限可以被简单地表示为一个基于名称的字符串,例如“读”。通过检查当前用户是否具有与所请求的应用程序动作相关联的许可来做出访问决定。

    用户和许可之间关系可以通过创建用户和权限(称为间接关系满足许可)来表示。在间接模型中,权限授予是指中间实体,例如用户组。当且仅当用户从用户组继承权限时,才将用户视为用户组的成员。间接模型可以更轻松地管理大量用户的权限,因为更改分配给用户组的权限会影响用户组的所有成员。

    在一些基于权限的提供细粒度域对象级访问控制的访问控制系统中,可以将权限分组到类中。假设系统中的每个域对象可以与确定与相应域对象的许可的类关联。在这样的系统中,可以用权限“READ”,“WRITE”和DELETE“定义”DOCUMENT“类;可以用权限”START“,”STOP“和”REBOOT“定义”SERVER“类。

    访问控制验证要求

    描述
    验证最小特权的原则:用户应仅能够访问函数、数据文件、URL、控制器、服务和其他资源,它们处理特定的授权,它们使应用程序免受欺骗和提权。
    验证对敏感记录的访问是否实施了保护措施,这样只有授权的对象或数据才允许访问(例如:防止用户篡改参数或更改其它用户账户)
    验证目录遍历是禁用的,除非故意为之。此外应用程序不应允许发现或泄露文件或目录元数据,例如:Thumbs.db、.DS_Store、.git或.svn
    验证访问控制是否以安全的方式显示失败处理。
    验证表示层访问控制规则是否在服务器端强制执行。
    验证访问控制使用的所有用户和数据属性、策略信息不能被终端用户操纵,除非特别授权。
    验证是否存在集中化机制(包括调用外部授权服务的库),以保护对每种受保护资源的访问。
    验证是否可以记录所有访问控制决定,并记录所有失败的决定。
    验证应用程序或框架是否使用强大的随机数(抵御CSRF令牌)或具有其他事务处理保护机制。
    验证系统能抵御对安全功能、资源或数据的持续访问。例如,考虑使用资源治理器来限制每小时编辑的数量,或阻止整个数据库被单个用户独占。
    验证应用程序是否具有针对较低价值系统的额外授权(例如,升级或自适应认证)或高价值应用程序的职责隔离,以根据应用程序和过去欺诈的风险执行反欺诈控制。
    验证应用程序是否正确强制执行了上下文相关的授权,以进制通过参数篡改进行未授权的操作。
    展开全文
  • Spring Cache扩展:注解失效时间... Spring Cache默认是不支持在@Cacheable上添加过期时间的,可以在配置缓存容器统一指定: @Bean public CacheManager cacheManager( @SuppressWarnings("rawtypes")...
  • Cache

    千次阅读 2016-09-01 23:14:04
    强制性失效 (Compulsory miss): 第一次访问一个块,该块不在 Cache中, 需从下一级存储中调入 Cache, 这就是强制性失效。这种失效也称为冷启动失效,或首次访问失效。(增加块大小,预取) 容量失效 (Capacity miss...
  • 分布式cache系统的应用

    千次阅读 2009-09-28 17:11:00
    1. 问题背景 在商城实践中,我们为了改善用户浏览图片的速度,但同时减少图片存储服务器的访问压力,采用了memcached来作cache集群,达到分担来自前端的请求,实际运营效果不错。但是后来在运营的过程中发现,随着...
  • 接着上几篇博文,继续分析了u-boot的cache、mmu、看门狗等代码实现
  • 1.程序访问局部性   计算机存储层次结构 为提高性能/价格,将各存储器组成一个金字塔式的层次结构,取长补短协调工作 ...•需从(向)存储器中取(存) 数,先访问cache;若在,取自cache •若不在cache...
  • tm:未命中主存的访问时间(包括访问cache未命中的时间和未命中后访问主存的时间,即主存存取周期) e=tcta=1htc+(1−h)tm=1r+(1−r)he= \frac{t_c}{t_a}=\frac{1}{ht_c+(1-h)t_m}=\frac{1}{r+(1-r)h}e=ta​t
  • 浅谈ARM存储系统cache

    千次阅读 2018-03-03 15:12:11
    而一般的SDRAM的存储周期是很慢的,相对于CPU来说,这时,如果我们把程序和数据都存储在SDRAM中,那么CPU在读取指令和数据的时候,就会受到SDRAM速度的限制,大大地制约了整个系统的性能。那么有没有什么改善的办法...
  • Cache与主存之间的全相联映射,直接映射和组相联映射的区别1.高速缓冲存储器的功能、结构与工作原理 高速...目的是提高CPU对存储器的访问速度。为此需要解决2个技术问题:一是主存地址与缓存地址的映象及转换; 二是
  • 学习笔记——Cache访问地址问题

    千次阅读 2013-01-17 18:31:34
    cache是体系结构中很重要的一个设计,也是有关存储体系中的一个重要环节,考虑到现实的应用中,由于开发了虚拟地址这个概念,即每个进程都可以拥有一个完整的虚拟地址空间,这样,CPU在执行两道不同的进程,而进程的...
  • jetcache官网教程

    万次阅读 多人点赞 2018-05-09 22:58:57
    jetcache简介JetCache是一个基于Java的缓存系统封装,提供统一的API和注解来简化缓存的使用。 JetCache提供了比SpringCache更加强大的注解,可以原生的支持TTL、两级缓存、分布式自动刷新,还提供了Cache接口用于...
  • 云客Drupal源码分析之缓存系统Cache

    千次阅读 2016-09-30 15:44:59
    在介绍drupal8的缓存系统前我们先了解一下缓存系统的本质及特性,缓存的存在依赖于两个目的:节省资源和提高速度,起不到这两作用则缓存没有存在的必要,一个结果需要进行大量计算才能得到,而它又不会频繁更新...
  • linux系统之arm架构的CPU与Cache

    千次阅读 2017-04-22 08:06:21
    【摘要】【写作原因】【问题构造】【分析一】总体流程【分析二】get_free_pages与mmap...无论是arm还是powerpc、mips、x86等,提高memory的访问速度都是cpu提高自身性能的重要手段,cache由此而来;无论是Linux还...
  • CACHE一些概念

    千次阅读 2018-03-28 13:34:52
    在缓存(Cache)中发现一个位置,并把新的缓存(Cache)数据存到这个位置的过程。这个处理过程可能包括驱逐(evicting)缓存(Cache)中已存在的数据,从而为新的数据腾出空间。 Associativity 关联 指每个集(Set)里包含...
  • 全栈必备 缓存cache

    千次阅读 2016-10-07 17:02:26
    缓存——cache,是一种挺复杂的技术,除了应用场景之外,更进一步,还要理解命中,Cache Miss,存储成本,索引成本,失效,替代策略的诸多概念,从而了解缓存算法,真正的掌握缓存技术。
  • Cache简介

    千次阅读 2015-12-14 20:45:54
    Cache  Cache一词来源于法语,其原意是“藏匿处,隐秘的地方”,而自从被应用于计算机科学之后,就已经成为了英语中的一个计算机体系结构专有名词。  Sun Microsystems的前首席科学家Billy Joy,作为BSD unix,...
  • 高并发之——Guava Cache

    千次阅读 2019-10-27 11:18:02
    最近需要用到缓存来存放临时数据,又不想采用Redis,Java自带的Map功能太少,发现Google的Guava提供的Cache模块功能很强大,于是选择使用它。 本地缓存 本地缓存作用就是提高系统的运行速度,是一种空间换时间的...
  • 阿里开源的缓存框架JetCache

    千次阅读 2019-04-08 08:01:03
    之前一直在用Spring Cache进行接口数据的缓存,主要是Spring Cache在对具体key缓存失效时间的设置不是很方法,还要自己去扩展,无意中发现了阿里的JetCache。大部分的需求都能满足,并且有一些很实用的功能,今天给...
  • Cache存储器 Cache(高速缓冲存储器) 高速缓冲存储器是位于主存与... (1)Cache原理、命中率、失效率 使用Cache改善系统性能的主要依据是程序的局部性原理。 命中率、失效Cache访问命中率为h(通常1...
  • CPU Cache 机制以及 Cache miss

    千次阅读 2019-06-11 11:09:16
    CPU体系结构之cache小结 ...CPU要访问的数据在Cache中有缓存,称为“命中” (Hit),反之则称为“缺失” (Miss)。 CPU访问它的速度介于寄存器与内存之间(数量级的差别)。实现Cache的花费介于寄...
  • 缓存篇(三)- Spring Cache框架

    千次阅读 2018-10-15 08:11:03
    前两篇我们讲了Guava和JetCache,他们都是缓存的具体实现,今天给大家分析一下Spring框架本身对这些缓存具体实现的支持和融合,使用Spring Cache将大大的减少我们的Spring项目中缓存使用的复杂度,提高代码可读性。...
  • 缓存篇(二)- JetCache

    万次阅读 2018-09-28 19:27:25
    本文将由浅入深,从基本特性介绍,从简单demo使用,到JetCache源码分析,到Spring Aop的源码分析,到如何利用这些知识去自己尝试写一个自己的cache小demo,去做一个全面的概括。 *背景和特性 *用法demo *JetCache...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 63,723
精华内容 25,489
关键字:

当访问cache系统失效时