范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

如何实现接口防刷

  前言本文为描述通过Interceptor以及Redis实现接口访问防刷Demo这里会通过逐步找问题,逐步去完善的形式展示原理通过ip地址+uri拼接用以作为访问者访问接口区分通过在Interceptor中拦截请求,从Redis中统计用户访问接口次数从而达到接口防刷目的如下图所示
  其中,Interceptor处代码处理逻辑最为重要
  /**  * @author: Zero  * @time: 2023/2/14  * @description: 接口防刷拦截处理  */ @Slf4j public class AccessLimintInterceptor  implements HandlerInterceptor {     @Resource     private RedisTemplate redisTemplate;      /**      * 多长时间内      */     @Value("${interfaceAccess.second}")     private Long second = 10L;       /**      * 访问次数      */     @Value("${interfaceAccess.time}")     private Long time = 3L;       /**      * 禁用时长--单位/秒      */     @Value("${interfaceAccess.lockTime}")     private Long lockTime = 60L;       /**      * 锁住时的key前缀      */     public static final String LOCK_PREFIX = "LOCK";       /**      * 统计次数时的key前缀      */     public static final String COUNT_PREFIX = "COUNT";         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {           String uri = request.getRequestURI();         String ip = request.getRemoteAddr(); // 这里忽略代理软件方式访问,默认直接访问,也就是获取得到的就是访问者真实ip地址         String lockKey = LOCK_PREFIX + ip + uri;         Object isLock = redisTemplate.opsForValue().get(lockKey);         if(Objects.isNull(isLock)){             // 还未被禁用             String countKey = COUNT_PREFIX + ip + uri;             Object count = redisTemplate.opsForValue().get(countKey);             if(Objects.isNull(count)){                 // 首次访问                 log.info("首次访问");                 redisTemplate.opsForValue().set(countKey,1,second, TimeUnit.SECONDS);             }else{                 // 此用户前一点时间就访问过该接口                 if((Integer)count < time){                     // 放行,访问次数 + 1                     redisTemplate.opsForValue().increment(countKey);                 }else{                     log.info("{}禁用访问{}",ip, uri);                     // 禁用                     redisTemplate.opsForValue().set(lockKey, 1,lockTime, TimeUnit.SECONDS);                     // 删除统计                     redisTemplate.delete(countKey);                     throw new CommonException(ResultCode.ACCESS_FREQUENT);                 }             }         }else{             // 此用户访问此接口已被禁用             throw new CommonException(ResultCode.ACCESS_FREQUENT);         }         return true;     } } 复制代码在多长时间内访问接口多少次,以及禁用的时长,则是通过与配置文件配合动态设置
  当处于禁用时直接抛异常则是通过在ControllerAdvice处统一处理(这里代码写的有点丑陋)
  下面是一些测试(可以把项目通过Git还原到"【初始化】"状态进行测试)正常访问时
  访问次数过于频繁时
  自我提问上述实现就好像就已经达到了我们的接口防刷目的了但是,还不够为方便后续描述,项目中新增补充Controller,如下所示
  简单来说就是PassCotroller和RefuseController每个Controller分别有对应的get,post,put,delete类型的方法,其映射路径与方法名称一致接口自由对于上述实现,不知道你们有没有发现一个问题就是现在我们的接口防刷处理,针对是所有的接口(项目案例中我只是写的接口比较少)而在实际开发中,说对于所有的接口都要做防刷处理,感觉上也不太可能(写此文时目前大四,实际工作经验较少,这里不敢肯定)那么问题有了,该如何解决呢?目前来说想到两个解决方案拦截器映射规则项目通过Git还原到"【Interceptor设置映射规则实现接口自由】"版本即可得到此案例实现
  我们都知道拦截器是可以设置拦截规则的,从而达到拦截处理目的
  这个AccessInterfaceInterceptor是专门用来进行防刷处理的,那么实际上我们可以通过设置它的映射规则去匹配需要进行【接口防刷】的接口即可
  比如说下面的映射配置
  这样就初步达到了我们的目的,通过映射规则的配置,只针对那些需要进行【接口防刷】的接口才会进行处理
  至于为啥说是初步呢?下面我就说说目前我想到的使用这种方式进行【接口防刷】的不足点:
  所有要进行防刷处理的接口统一都是配置成了 x 秒内 y 次访问次数,禁用时长为 z 秒要知道就是要进行防刷处理的接口,其 x, y, z的值也是并不一定会统一的
  某些防刷接口处理比较消耗性能的,我就把x, y, z设置的紧一点
  而某些防刷接口处理相对来说比较快,我就把x, y, z 设置的松一点
  这没问题吧
  但是现在呢?x, y, z值全都一致了,这就不行了
  这就是其中一个不足点
  当然,其实针对当前这种情况也有解决方案
  那就是弄多个拦截器
  每个拦截器的【接口防刷】处理逻辑跟上述一致,并去映射对应要处理的防刷接口
  唯一不同的就是在每个拦截器内部,去修改对应防刷接口需要的x, y, z值
  这样就是感觉会比较麻烦
  防刷接口映射路径修改后维护问题虽然说防刷接口的映射路径基本上定下来后就不会改变
  但实际上前后端联调开发项目时,不会有那么严谨的Api文档给我们用(这个在实习中倒是碰到过,公司不是很大,开发起来也就不那么严谨,啥都要自己搞,功能能实现就好)
  也就是说还是会有那种要修改接口的映射路径需求
  当防刷接口数量特别多,后面的接手人员就很痛苦了
  就算是项目是自己从0到1实现的,其实有时候项目开发到后面,自己也会忘记自己前面是如何设计的
  而使用当前这种方式的话,谁维护谁蛋疼自定义注解 + 反射咋说呢就是通过自定义注解中定义 x 秒内 y 次访问次数,禁用时长为 z 秒自定义注解 + 在需要进行防刷处理的各个接口方法上在拦截器中通过反射获取到各个接口中的x, y, z值即可达到我们想要的接口自由目的下面做个实现声明自定义注解
  Controlller中方法中使用
  Interceptor处逻辑修改(最重要是通过反射判断此接口是否需要进行防刷处理,以及获取到x, y, z的值)/**  * @author: Zero  * @time: 2023/2/14  * @description: 接口防刷拦截处理  */ @Slf4j public class AccessLimintInterceptor  implements HandlerInterceptor {     @Resource     private RedisTemplate redisTemplate;     /**      * 锁住时的key前缀      */     public static final String LOCK_PREFIX = "LOCK";       /**      * 统计次数时的key前缀      */     public static final String COUNT_PREFIX = "COUNT";         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //        自定义注解 + 反射 实现         // 判断访问的是否是接口方法         if(handler instanceof HandlerMethod){             // 访问的是接口方法,转化为待访问的目标方法对象             HandlerMethod targetMethod = (HandlerMethod) handler;             // 取出目标方法中的 AccessLimit 注解             AccessLimit accessLimit = targetMethod.getMethodAnnotation(AccessLimit.class);             // 判断此方法接口是否要进行防刷处理(方法上没有对应注解就代表不需要,不需要的话进行放行)             if(!Objects.isNull(accessLimit)){                 // 需要进行防刷处理,接下来是处理逻辑                 String ip = request.getRemoteAddr();                 String uri = request.getRequestURI();                 String lockKey = LOCK_PREFIX + ip + uri;                 Object isLock = redisTemplate.opsForValue().get(lockKey);                 // 判断此ip用户访问此接口是否已经被禁用                 if (Objects.isNull(isLock)) {                     // 还未被禁用                     String countKey = COUNT_PREFIX + ip + uri;                     Object count = redisTemplate.opsForValue().get(countKey);                     long second = accessLimit.second();                     long maxTime = accessLimit.maxTime();                       if (Objects.isNull(count)) {                         // 首次访问                         log.info("首次访问");                         redisTemplate.opsForValue().set(countKey, 1, second, TimeUnit.SECONDS);                     } else {                         // 此用户前一点时间就访问过该接口,且频率没超过设置                         if ((Integer) count < maxTime) {                             redisTemplate.opsForValue().increment(countKey);                         } else {                               log.info("{}禁用访问{}", ip, uri);                             long forbiddenTime = accessLimit.forbiddenTime();                             // 禁用                             redisTemplate.opsForValue().set(lockKey, 1, forbiddenTime, TimeUnit.SECONDS);                             // 删除统计--已经禁用了就没必要存在了                             redisTemplate.delete(countKey);                             throw new CommonException(ResultCode.ACCESS_FREQUENT);                         }                     }                 } else {                     // 此用户访问此接口已被禁用                     throw new CommonException(ResultCode.ACCESS_FREQUENT);                 }             }         }         return  true;     } }由于不好演示效果,这里就不贴测试结果图片了项目通过Git还原到"【自定义主键+反射实现接口自由"版本即可得到此案例实现,后面自己可以针对接口做下测试看看是否如同我所说的那样实现自定义x, y, z 的效果嗯,现在看起来,可以针对每个要进行防刷处理的接口进行针对性自定义多长时间内的最大访问次数,以及禁用时长,哪个接口需要,就直接+在那个接口方法出即可感觉还不错的样子,现在网上挺多资料也都是这样实现的但是还是可以有改善的地方先举一个例子,以我们的PassController为例,如下是其实现
  下图是其映射路径关系
  同一个Controller的所有接口方法映射路径的前缀都包含了/pass我们在类上通过注解@ReqeustMapping标记映射路径/pass,这样所有的接口方法前缀都包含了/pass,并且以致于后面要修改映射路径前缀时只需改这一块地方即可这也是我们使用SpringMVC最常见的用法那么,我们的自定义注解也可不可以这样做呢?先无中生有个需求假设PassController中所有接口都是要进行防刷处理的,并且他们的x, y, z值就一样如果我们的自定义注解还是只能加载方法上的话,一个一个接口加,那么无疑这是一种很呆的做法要改的话,其实也很简单,首先是修改自定义注解,让其可以作用在类上
  接着就是修改AccessLimitInterceptor的处理逻辑AccessLimitInterceptor中代码修改的有点多,主要逻辑如下
  与之前实现比较,不同点在于x, y, z的值要首先尝试在目标类中获取其次,一旦类中标有此注解,即代表此类下所有接口方法都要进行防刷处理如果其接口方法同样也标有此注解,根据就近优先原则,以接口方法中的注解标明的值为准/**  * @author: Zero  * @time: 2023/2/14  * @description: 接口防刷拦截处理  */ @Slf4j public class AccessLimintInterceptor implements HandlerInterceptor {     @Resource     private RedisTemplate redisTemplate;       /**      * 锁住时的key前缀      */     public static final String LOCK_PREFIX = "LOCK";       /**      * 统计次数时的key前缀      */     public static final String COUNT_PREFIX = "COUNT";         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {   //      自定义注解 + 反射 实现, 版本 2.0         if (handler instanceof HandlerMethod) {             // 访问的是接口方法,转化为待访问的目标方法对象             HandlerMethod targetMethod = (HandlerMethod) handler;             // 获取目标接口方法所在类的注解@AccessLimit             AccessLimit targetClassAnnotation = targetMethod.getMethod().getDeclaringClass().getAnnotation(AccessLimit.class);             // 特别注意不能采用下面这条语句来获取,因为 Spring 采用的代理方式来代理目标方法             //  也就是说targetMethod.getClass()获得是class org.springframework.web.method.HandlerMethod ,而不知我们真正想要的 Controller //            AccessLimit targetClassAnnotation = targetMethod.getClass().getAnnotation(AccessLimit.class);             // 定义标记位,标记此类是否加了@AccessLimit注解             boolean isBrushForAllInterface = false;             String ip = request.getRemoteAddr();             String uri = request.getRequestURI();             long second = 0L;             long maxTime = 0L;             long forbiddenTime = 0L;             if (!Objects.isNull(targetClassAnnotation)) {                 log.info("目标接口方法所在类上有@AccessLimit注解");                 isBrushForAllInterface = true;                 second = targetClassAnnotation.second();                 maxTime = targetClassAnnotation.maxTime();                 forbiddenTime = targetClassAnnotation.forbiddenTime();             }             // 取出目标方法中的 AccessLimit 注解             AccessLimit accessLimit = targetMethod.getMethodAnnotation(AccessLimit.class);             // 判断此方法接口是否要进行防刷处理             if (!Objects.isNull(accessLimit)) {                 // 需要进行防刷处理,接下来是处理逻辑                 second = accessLimit.second();                 maxTime = accessLimit.maxTime();                 forbiddenTime = accessLimit.forbiddenTime();                 if (isForbindden(second, maxTime, forbiddenTime, ip, uri)) {                     throw new CommonException(ResultCode.ACCESS_FREQUENT);                 }             } else {                 // 目标接口方法处无@AccessLimit注解,但还要看看其类上是否加了(类上有加,代表针对此类下所有接口方法都要进行防刷处理)                 if (isBrushForAllInterface && isForbindden(second, maxTime, forbiddenTime, ip, uri)) {                     throw new CommonException(ResultCode.ACCESS_FREQUENT);                 }             }         }         return true;     }       /**      * 判断某用户访问某接口是否已经被禁用/是否需要禁用      *      * @param second        多长时间  单位/秒      * @param maxTime       最大访问次数      * @param forbiddenTime 禁用时长 单位/秒      * @param ip            访问者ip地址      * @param uri           访问的uri      * @return ture为需要禁用      */     private boolean isForbindden(long second, long maxTime, long forbiddenTime, String ip, String uri) {         String lockKey = LOCK_PREFIX + ip + uri; //如果此ip访问此uri被禁用时的存在Redis中的 key         Object isLock = redisTemplate.opsForValue().get(lockKey);         // 判断此ip用户访问此接口是否已经被禁用         if (Objects.isNull(isLock)) {             // 还未被禁用             String countKey = COUNT_PREFIX + ip + uri;             Object count = redisTemplate.opsForValue().get(countKey);             if (Objects.isNull(count)) {                 // 首次访问                 log.info("首次访问");                 redisTemplate.opsForValue().set(countKey, 1, second, TimeUnit.SECONDS);             } else {                 // 此用户前一点时间就访问过该接口,且频率没超过设置                 if ((Integer) count < maxTime) {                     redisTemplate.opsForValue().increment(countKey);                 } else {                     log.info("{}禁用访问{}", ip, uri);                     // 禁用                     redisTemplate.opsForValue().set(lockKey, 1, forbiddenTime, TimeUnit.SECONDS);                     // 删除统计--已经禁用了就没必要存在了                     redisTemplate.delete(countKey);                     return true;                 }             }         } else {             // 此用户访问此接口已被禁用             return true;         }         return false;     } }
  好了,这样就达到我们想要的效果了
  项目通过Git还原到"【自定义注解+反射实现接口自由-版本2.0】"版本即可得到此案例实现,自己可以测试万一下这是目前来说比较理想的做法,至于其他做法,暂时没啥了解到时间逻辑漏洞这是我一开始都有留意到的问题也是一直搞不懂,就是我们现在的所有做法其实感觉都不是严格意义上的x秒内y次访问次数特别注意这个x秒,它是连续,任意的(代表这个x秒时间片段其实是可以发生在任意一个时间轴上)我下面尝试表达我的意思,但是我不知道能不能表达清楚假设我们固定某个接口5秒内只能访问3次,以下面例子为例
  底下的小圆圈代表此刻请求访问接口按照我们之前所有做法的逻辑走第2秒请求到,为首次访问,Redis中统计次数为1(过期时间为5秒)第7秒,此时有两个动作,一是请求到,二是刚刚第二秒Redis存的值现在过期我们先假设这一刻,请求处理完后,Redis存的值才过期按照这样的逻辑走第七秒请求到,Redis存在对应key,且不大于3, 次数+1接着这个key立马过期再继续往后走,第8秒又当做新的一个起始,就不往下说了,反正就是不会出现禁用的情况按照上述逻辑走,实际上也就是说当出现首次访问时,当做这5秒时间片段的起始第2秒是,第8秒也是但是有没有想过,实际上这个5秒时间片段实际上是可以放置在时间轴上任意区域的上述情况我们是根据请求的到来情况人为的把它放在【2-7】,【8-13】上而实际上这5秒时间片段是可以放在任意区域的那么,这样的话,【7-12】也可以放置而【7-12】这段时间有4次请求,就达到了我们禁用的条件了是不是感觉怪怪的想过其他做法,但是好像严格意义上真的做不到我所说的那样(至少目前来说想不到)之前我们的做法,正常来说也够用,至少说有达到防刷的作用后面有机会的话再看看,不知道我是不是钻牛角尖了路径参数问题假设现在PassController中有如下接口方法
  也就是我们在接口方法中常用的在请求路径中获取参数的套路但是使用路径参数的话,就会发生问题那就是同一个ip地址访问此接口时,我携带的参数值不同按照我们之前那种前缀+ip+uri拼接的形式作为key的话,其实是区分不了的下图是访问此接口,携带不同参数值时获取的uri状况
  这样的话在我们之前拦截器的处理逻辑中,会认为是此ip用户访问的是不同的接口方法,而实际上访问的是同一个接口方法也就导致了【接口防刷】失效接下来就是解决它,目前来说有两种不要使用路径参数这算是比较理想的做法,相当于没这个问题
  但有一定局限性,有时候接手别的项目,或者自己根本没这个权限说不能使用路径参数替换uri我们获取uri的目的,其实就是为了区别访问接口
  而把uri替换成另一种可以区分访问接口方法的标识即可
  最容易想到的就是通过反射获取到接口方法名称,使用接口方法名称替换成uri即可
  当然,其实不同的Controller中,其接口方法名称也有可能是相同的
  实际上可以再获取接口方法所在类类名,使用类名 + 方法名称替换uri即可
  实际解决方案有很多,看个人需求吧真实ip获取在之前的代码中,我们获取代码都是通过request.getRemoteAddr()获取的但是后续有了解到,如果说通过代理软件方式访问的话,这样是获取不到来访者的真实ip的至于如何获取,后续我再研究下http再说,这里先提个醒总结说实话,挺有意思的一开始自己想【接口防刷】的时候,感觉也就是转化成统计下访问次数的问题摆了后面到网上看别人的写法,又再自己给自己找点问题出来后面会衍生出来一推东西出来诸如自定义注解+反射这种实现方式以前其实对注解 + 反射其实有点不太懂干嘛用的而从之前的数据报表导出,再到基本权限控制实现,最后到今天的【接口防刷】一点点来进步去补充自己的知识点而且,感觉写博客真的是件挺有意义的事情它会让你去更深入的了解某个点,并且知识是相关联的,探索的过程中会牵扯到其他别的知识点就像之前的写的【单例模式】实现,一开始就了解到懒汉式,饿汉式后面深入的话就知道其实会还有序列化/反序列化,反射调用生成实例,对象克隆这几种方式回去破坏单例模式又是如何解决的,这也是一个进步的点后续为了保证线程安全问题,牵扯到的synchronized,voliate关键字继而又关联到JVM,JUC,操作系统的东西哈哈

iQOO10系列手机发布,200W快充,V1芯片,诚意满满iQOO10系列手机发布会已经结束,之前爆料的自研芯片V1和200W快充技术都会在iQOO10系列手机上搭载。下面具体来看下参数iQOO系列手机是做游戏手机起家的,对游戏优化的经验小米13系列进度还是最快的,不出意外的话12月左右发布红米k50ultra卢总预热了红米新品,大家可以对照我昨天说的看,一看就懂。红米k50ultra下个月见,后面红米note12系列快充新突破。努比亚z40s努比亚z40s系列发布。40系列显卡曝光汇总4090跑分曝光,4090Ti游戏4K高刷统统兼得近期显卡价格有所回落,有消息称老黄正在清理库存准备40系显卡的发布,30系显卡价格有所下降,而与40系显卡相关的消息也越来越多,接下来就让我们一起看看40系显卡都有哪些值得关注的点7月27日鸿蒙3。0正式来袭,携带一系列新品,鸿3。0系统不见nova系据了解,华为将在7月27日发布华为鸿蒙OS系统(HarmonyOS)3。0版本,对于华为鸿蒙OS系统3。0版本再也期待不过了,机型也好像推出了第一批和第二批。第一批如下(排名不分前王子文个子不高但很挺拔,一身白色挂脖西装裤简单利落,越看越美白色作为简单基础的颜色,适合各种肤色各个年龄段的人选择,作为典雅纯洁的代表颜色,白色的单品不只能营造出青春活力的学生气息,还可以展现优雅干练的女强人气质,一年四季都可以找到合适的白目前热门的3款电动车,多项核心科技加持,续航200公里以上您在阅读前请点击上面的关注二字,后续会为您提供更多有价值的相关内容,感谢您的支持。电动车作为有庞大市场的产品,它和汽车手机一样,也都会迭代更新,而且是越来越好,而往往新出的车型,也iPadOS15。6正式版升级,检测不到充电器问题已修复,建议升级苹果今天向iPhone手机用户推送了iOS15。6正式版升级更新,同时向iPad平板电脑推送了iPadOS15。6正式版升级更新,推送升级的版本号为19G71。与iOS15。6正式夏季炎热出汗多,最该多喝这汤,汤汁鲜美,助力孩子长高个一年四季,每个季节的气候都不一样,夏季以炎热天气为主,雨水也非常充沛,今年是非常炎热的夏天,尤其是进入三伏天,感受到夏天的气息,让人苦不堪言,每天都是35摄氏度的气温,只要我们稍微女人不管差不差钱,夏天备齐这2裤2裙就够,高级百搭又显瘦有多少女性每季忙着追逐潮流,买买买掏空钱包?又有多少女性每每看着衣柜,感慨无衣可穿?无止境买买买伤害钱包,买得多而无用,更是徒增烦恼。不如精炼一下,选择最值得入手的单品,投资在质感中国男足丢人丢到国外,遭外媒羞辱建议中国队退出洲际比赛在刚刚过去的东亚杯第一轮比赛中,中国男足03完败在韩国队脚下。比输球更令人难以接受的,是中国男足在球场上孱弱无力的表现,被韩国队压制得完全没有还手之力,最终耻辱性输掉了比赛,令人非湖人仍对欧文抱有兴趣,哈登2年6860万美元续约76人湖人仍对得到凯里欧文抱有兴趣北京时间7月21日,根据ESPN报道,湖人目前仍对得到凯里欧文抱有兴趣。尽管湖人三巨头前几日进行了电话会议,但据ESPN某知名记者透露,湖人仍然在追求凯
不舒服的时候可以去确认下是否感染,如何查找附近的核酸采样点?如果感觉自己出现感染新冠病毒的相关症状,又不确认自己是感冒还是感染新冠病毒,建议应尽快去附近的核酸采样点进行检测确认,以免错过第一时间,流动的时候带来不必要的扩散。怎么查找自己附近华为手机将可检测核酸,中科院已研发出便携式检测系统!惊喜就在两小时前,司马南先生在头条上发表了一条大消息手机测核酸,来了!这真是一条惊爆的好消息!此消息一出,粉丝们也纷纷炸开了锅于是,小编也特意查了查原来,中科院科学家研发出了一款MS2取消常态化核酸后,核检机构何去何从?多地相关项目宣告终止,朴石医学已无财产可供执行12月6日,北京调整了全市核酸检测查验措施,进入商超商务楼宇及各类公共场所,可不查验核酸检测阴性证明。在此之前,上海广州深圳重庆成都等地也先后优化了核酸查验政策。随着全国多地疫情政王哲林305布莱德索267上海送宁波12连败12月11日消息,CBA常规赛继续进行,上海迎战宁波,两队实力差距比较大,最终,上海12588轻松战胜宁波,在自己取得4连胜的同时,送给对手12连败。比赛开始后上海进入状态,开局他CBA恢复主客场赛制,这一刻等待得太久,广东队迎来转机CBA恢复主客场赛制,这一刻等待得太久,广东队迎来转机本赛季CBA第三阶段,将恢复主客场赛制,这一消息已经得到了证实。这对于联赛而言,对于各支球队而言,甚至对于广大无数球迷而言,无5人狂轰78分,广东集体暴走!胡明轩险酿大错,郭士强季后赛悬了第2阶段首场比赛,面对老对手北京队,广东统治力十足,大胜对手17分,取得了第2阶段的开门红,也开启了自己第2阶段的旅程!大胜北京队赢得漂亮,可以看出广东队的状态在复苏,球队又签下了凯尔特人107123勇士,如何评价这场比赛?本场比赛,勇士球员克莱汤普森出战35分钟,26投14中,其中三分球11投4中,罚球2投2中,得到34分5篮板2助攻2抢断1封盖。库里全场21投12中,三分11中6,得到32分6板7高血压的病因是什么?朋友问我吴医生,我确诊高血压了,怎么得的高血压?我为什么得了高血压?那么高血压的病因是什么呢?得了高血压高血压分为原发性高血压和继发性高血压两种。其中继发性高血压是其他疾病导致的高韩版纸钞屋2,劫匪出叛徒,人质逃脱,信息量大继6月份的韩版纸钞屋第一季后,网飞(Netfix)又更新了第二季。而且,一连更六集。不得不说,网飞的格局得有多大。相比第一季,第二季更有看点,剧情反转多,信息量大。01教授身份险曝李某峰被拘退圈后,当事女主兴风作浪成最大赢家,呼吁圈内抵制大家好,我是六姐,来点娱见。2022年9月11日,官方媒体正式发布男星李某峰嫖娼被拘的通报,至今,李某峰事件已经在娱乐圈尘埃落定,来得快去得也快,娱乐圈这个滚轮就是这样。最终以李某神仙姐姐在人间头条创作挑战赛娱评大赏神仙姐姐,神仙妹妹,总之,刘亦菲上辈子大概率是从仙界下凡的。她一家子都带有古典美,从外婆开始就像是仙女下凡,无论是小姨还是刘妈妈,个个都是神仙颜值,神仙姐姐本