实现接口防刷,最强方案在这!

2024-01-30 01:20

本文主要是介绍实现接口防刷,最强方案在这!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1前言

本文为描述通过Interceptor以及Redis实现接口访问防刷Demo

这里会通过逐步找问题,逐步去完善的形式展示

2原理

  • 通过ip地址+uri拼接用以作为访问者访问接口区分

  • 通过在Interceptor中拦截请求,从Redis中统计用户访问接口次数从而达到接口防刷目的

如下图所示

图片

3工程

其中,Interceptor处代码处理逻辑最为重要

图片

/**  * @time: 2023/2/14  * @description: 接口防刷拦截处理  */  
@Slf4j  
public class AccessLimintInterceptor  implements HandlerInterceptor {  @Resource  private RedisTemplate<String, Object> 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还原到“【初始化】”状态进行测试)

  • 正常访问时

图片

图片

  • 访问次数过于频繁时

图片

图片

4自我提问

上述实现就好像就已经达到了我们的接口防刷目的了

但是,还不够

为方便后续描述,项目中新增补充Controller,如下所示

图片

简单来说就是

  • PassCotrollerRefuseController

  • 每个Controller分别有对应的get,post,put,delete类型的方法,其映射路径与方法名称一致

接口自由

  • 对于上述实现,不知道你们有没有发现一个问题

  • 就是现在我们的接口防刷处理,针对是所有的接口(项目案例中我只是写的接口比较少)

  • 而在实际开发中,说对于所有的接口都要做防刷处理,感觉上也不太可能(写此文时目前大四,实际工作经验较少,这里不敢肯定)

  • 那么问题有了,该如何解决呢?目前来说想到两个解决方案

拦截器映射规则

项目通过Git还原到"【Interceptor设置映射规则实现接口自由】"版本即可得到此案例实现

我们都知道拦截器是可以设置拦截规则的,从而达到拦截处理目的

图片

1.这个AccessInterfaceInterceptor是专门用来进行防刷处理的,那么实际上我们可以通过设置它的映射规则去匹配需要进行【接口防刷】的接口即可

2.比如说下面的映射配置

图片

3.这样就初步达到了我们的目的,通过映射规则的配置,只针对那些需要进行【接口防刷】的接口才会进行处理

4.至于为啥说是初步呢?下面我就说说目前我想到的使用这种方式进行【接口防刷】的不足点:

所有要进行防刷处理的接口统一都是配置成了 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的值)

/**  * * @time: 2023/2/14  * @description: 接口防刷拦截处理  */  
@Slf4j  
public class AccessLimintInterceptor  implements HandlerInterceptor {  @Resource  private RedisTemplate<String, Object> 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的值要首先尝试在目标类中获取

其次,一旦类中标有此注解,即代表此类下所有接口方法都要进行防刷处理

如果其接口方法同样也标有此注解,根据就近优先原则,以接口方法中的注解标明的值为准

/**  * @time: 2023/2/14  * @description: 接口防刷拦截处理  */  
@Slf4j  
public class AccessLimintInterceptor implements HandlerInterceptor {  @Resource  private RedisTemplate<String, Object> 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】"版本即可得到此案例实现,自己可以测试万一下

这是目前来说比较理想的做法,至于其他做法,暂时没啥了解到

5时间逻辑漏洞

这是我一开始都有留意到的问题

也是一直搞不懂,就是我们现在的所有做法其实感觉都不是严格意义上的x秒内y次访问次数

特别注意这个x秒,它是连续,任意的(代表这个x秒时间片段其实是可以发生在任意一个时间轴上)

我下面尝试表达我的意思,但是我不知道能不能表达清楚

假设我们固定某个接口5秒内只能访问3次,以下面例子为例

图片

底下的小圆圈代表此刻请求访问接口

按照我们之前所有做法的逻辑走

  1. 第2秒请求到,为首次访问,Redis中统计次数为1(过期时间为5秒)

  2. 第7秒,此时有两个动作,一是请求到,二是刚刚第二秒Redis存的值现在过期

  3. 我们先假设这一刻,请求处理完后,Redis存的值才过期

  4. 按照这样的逻辑走

  5. 第七秒请求到,Redis存在对应key,且不大于3, 次数+1

  6. 接着这个key立马过期

  7. 再继续往后走,第8秒又当做新的一个起始,就不往下说了,反正就是不会出现禁用的情况

按照上述逻辑走,实际上也就是说当出现首次访问时,当做这5秒时间片段的起始

第2秒是,第8秒也是

但是有没有想过,实际上这个5秒时间片段实际上是可以放置在时间轴上任意区域的

上述情况我们是根据请求的到来情况人为的把它放在【2-7】,【8-13】上

而实际上这5秒时间片段是可以放在任意区域的

那么,这样的话,【7-12】也可以放置

而【7-12】这段时间有4次请求,就达到了我们禁用的条件了

是不是感觉怪怪的

想过其他做法,但是好像严格意义上真的做不到我所说的那样(至少目前来说想不到)

之前我们的做法,正常来说也够用,至少说有达到防刷的作用

后面有机会的话再看看,不知道我是不是钻牛角尖了

6路径参数问题

假设现在PassController中有如下接口方法

图片

也就是我们在接口方法中常用的在请求路径中获取参数的套路

但是使用路径参数的话,就会发生问题

那就是同一个ip地址访问此接口时,我携带的参数值不同

按照我们之前那种前缀+ip+uri拼接的形式作为key的话,其实是区分不了的

下图是访问此接口,携带不同参数值时获取的uri状况

图片

这样的话在我们之前拦截器的处理逻辑中,会认为是此ip用户访问的是不同的接口方法,而实际上访问的是同一个接口方法

也就导致了【接口防刷】失效

接下来就是解决它,目前来说有两种

  1. 不要使用路径参数

这算是比较理想的做法,相当于没这个问题

但有一定局限性,有时候接手别的项目,或者自己根本没这个权限说不能使用路径参数

  1. 替换uri

  • 我们获取uri的目的,其实就是为了区别访问接口

  • 而把uri替换成另一种可以区分访问接口方法的标识即可

  • 最容易想到的就是通过反射获取到接口方法名称,使用接口方法名称替换成uri即可

  • 当然,其实不同的Controller中,其接口方法名称也有可能是相同的

  • 实际上可以再获取接口方法所在类类名,使用类名 + 方法名称替换uri即可

  • 实际解决方案有很多,看个人需求吧

7真实ip获取

在之前的代码中,我们获取代码都是通过request.getRemoteAddr()获取的

但是后续有了解到,如果说通过代理软件方式访问的话,这样是获取不到来访者的真实ip的

至于如何获取,后续我再研究下http再说,这里先提个醒

8总结

说实话,挺有意思的,一开始自己想【接口防刷】的时候,感觉也就是转化成统计下访问次数的问题摆了。后面到网上看别人的写法,又再自己给自己找点问题出来,后面会衍生出来一推东西出来,诸如自定义注解+反射这种实现方式。

以前其实对注解 + 反射其实有点不太懂干嘛用的,而从之前的数据报表导出,再到基本权限控制实现,最后到今天的【接口防刷】一点点来进步去补充自己的知识点,而且,感觉写博客真的是件挺有意义的事情,它会让你去更深入的了解某个点,并且知识是相关联的,探索的过程中会牵扯到其他别的知识点,就像之前的写的【单例模式】实现,一开始就了解到懒汉式,饿汉式

后面深入的话就知道其实会还有序列化/反序列化,反射调用生成实例,对象克隆这几种方式回去破坏单例模式,又是如何解决的,这也是一个进步的点,后续为了保证线程安全问题,牵扯到的synchronized,voliate关键字,继而又关联到JVM,JUC,操作系统的东西。

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

这篇关于实现接口防刷,最强方案在这!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/658705

相关文章

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P