Loading [MathJax]/jax/output/CommonHTML/config.js
部署DeepSeek模型,进群交流最in玩法!
立即加群
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >CefSharp请求资源拦截及自定义处理

CefSharp请求资源拦截及自定义处理

作者头像
w4ngzhen
发布于 2023-10-18 10:44:10
发布于 2023-10-18 10:44:10
1.5K00
代码可运行
举报
文章被收录于专栏:编译思想编译思想
运行总次数:0
代码可运行

CefSharp请求资源拦截及自定义处理

前言

在CefSharp中,我们不仅可以使用Chromium浏览器内核,还可以通过Cef暴露出来的各种Handler来实现我们自己的资源请求处理。

什么是资源请求呢?简单来说,就是前端页面在加载的过程中,请求的各种文本(js、css以及html)。在以Chromium内核的浏览器上,我们可以使用浏览器为我们提供的开发者工具来检查每一次页面加载发生的请求。

准备

鉴于本文的重心是了解CefSharp的资源拦截处理,所以我们不讨论前端的开发以及客户端嵌入CefSharp组件的细节。我们首先完成一个基本的嵌入CefSharp的WinForm程序:该程序界面如下,拥有一个地址输入栏和一个显示网页的Panel:

并且编写一个极其简单的页面,该页面会请求1个js资源和1个css资源:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
demo:
    - index.html
    - test1.js
    - test1.css

这几个文件的代码都十分简单:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
body
{
    background-color: aqua
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myFunc() {
    return 'test1 js file';
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Home</title>
    <!-- 如下记载js、css资源 -->
    <script type="text/javascript" src="test1.js"></script>
    <link type="text/css" rel="stylesheet" href="test1.css"/>
</head>
<body>
<h1>Resource Intercept Example</h1>
<h2 id="result"></h2>
<script>
    // 调用test1.js中的myFunc
    document.getElementById('result').innerHTML = myFunc();
</script>
</body>
</html>

代码很简单,效果也很容易知道,页面加载后,页面背景色为aqua,页面上会显示文本“test1 js file”。同时,当我们使用开发工具,刷新页面,能够看到对应的资源加载:

CefSharp资源拦截及自定义处理

完成上述准备后,我们进入正文:资源拦截及自定义处理。首先我们需要对目标的理解达成一致,资源拦截是指我们能够检测到上图中的html、js还有css的资源请求事件,在接下来的Example中,因为我们是使用的客户端程序,所以会在请求的过程中弹出提示;自定义处理是指,在完成拦截提示后,我们还能够替换这些资源,这里我们设定完成拦截后,可以把js和css换为我们想要另外的文件:test2.js和test2.css:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myFunc() {
    return 'test2 js file';
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
body
{
    background-color: beige
}

即我们希望拦截并替换后,页面上的文字不再是之前的,而是“test2 js file”,页面的背景色是beige。

IRequestHandler

在CefSharp中,要想对请求进行拦截处理,最为核心的Handler就是IRequestHandler这个接口,查看官方的源码,会发现里面有数个方法的定义,通过阅读官方的summary,我们可以聚焦到如下的两个定义(注释本人进行了删减):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>
/// Called before browser navigation.
/// 译:在浏览器导航前调用
/// If the navigation is allowed <see cref="E:CefSharp.IWebBrowser.FrameLoadStart" /> and <see cref="E:CefSharp.IWebBrowser.FrameLoadEnd" />
/// will be called. If the navigation is canceled <see cref="E:CefSharp.IWebBrowser.LoadError" /> will be called with an ErrorCode
/// value of <see cref="F:CefSharp.CefErrorCode.Aborted" />.
/// </summary>
bool OnBeforeBrowse(
  IWebBrowser chromiumWebBrowser,
  IBrowser browser,
  IFrame frame,
  IRequest request,
  bool userGesture,
  bool isRedirect);

/// <summary>
/// Called on the CEF IO thread before a resource request is initiated.
/// 在一个资源请求初始化前在CEF IO线程上调用
/// </summary>
IResourceRequestHandler GetResourceRequestHandler(
  IWebBrowser chromiumWebBrowser,
  IBrowser browser,
  IFrame frame,
  IRequest request,
  bool isNavigation,
  bool isDownload,
  string requestInitiator,
  ref bool disableDefaultHandling);

于是,我们继承一个默认的名为RequestHandler的类(请区分DefaultRequestHandler),只重写上述的两个方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public class MyRequestHandler : RequestHandler
{
    protected override bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture,
        bool isRedirect)
    {
        // 先调用基类的实现,断点调试
        return base.OnBeforeBrowse(chromiumWebBrowser, browser, frame, request, userGesture, isRedirect);
    }

    protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame,
        IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
    {
        // 先调用基类的实现,断点调试
        return base.GetResourceRequestHandler(
            chromiumWebBrowser, browser, frame, request, isNavigation, 
            isDownload, requestInitiator, ref disableDefaultHandling);
    }
}   

然后完成对该Handler的注册:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 this._webBrowser = new ChromiumWebBrowser(string.Empty)
{
    RequestHandler = new MyRequestHandler()
}; 

打上断点,开始访问我们的Example:index.html。这里会发现,OnBeforeBrowse调用了一次,而GetResourceRequestHandler会调用3次。检查OnBeforeBrowse中的request参数内容,是一次主页的请求,而GetResourceRequestHandler中的3次分别是:主页html资源、test1.js和test1.css。

结合官方注释和调试的结果,我们可以得出结论:要进行导航的拦截,我们可以重写OnBeforeBrowse方法,要想进行资源的拦截,我们需要实现自己的ResourceRequestHandler。

IResourceRequestHandler

查看IResourceRequestHandler的定义,我们再次聚焦一个函数定义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>
/// Called on the CEF IO thread before a resource is loaded. To specify a handler for the resource return a <see cref="T:CefSharp.IResourceHandler" /> object
/// </summary>
/// <returns>To allow the resource to load using the default network loader return null otherwise return an instance of <see cref="T:CefSharp.IResourceHandler" /> with a valid stream</returns>
IResourceHandler GetResourceHandler(
  IWebBrowser chromiumWebBrowser,
  IBrowser browser,
  IFrame frame,
  IRequest request);

该定义从注释可以看出,如果实现返回null,那么Cef会使用默认的网络加载器来发起请求,或者我们可以返回一个自定义的资源处理器ResourceHandler来处理一个合法的数据流(Stream)。也就是说,对于资源的处理,要想实现自定义的处理(不是拦截,拦截到目前为止我们可以在上述的两个Handler中进行处理)我们还需要实现一个IResourceHandler接口的实例,并在GetResourceHandler处进行返回,Cef才会在进行处理的时候使用我们的Handler。所以在GetResourceHandler中,我们进行资源的判断,如果是想要替换的资源,我们就使用WinForm提供的OpenFileDialog来选择本地的js或是css文件,并传给我们自定义的ResourceHandler,如果不是想要拦截的资源或是用户未选择任何的文件就走默认的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MyResourceRequestHandler : ResourceRequestHandler
{
    protected override IResourceHandler GetResourceHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request)
    {
        if (request.Url.EndsWith("test1.js") || request.Url.EndsWith("test1.css"))
        {
            MessageBox.Show($@"资源拦截:{request.Url}");

            string type = request.Url.EndsWith(".js") ? "js" : "css"; // 这里简单判断js还是css,不过多编写
            string fileName = null;
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = $@"{type}文件|*.{type}"; // 过滤
                openFileDialog.Multiselect = true;
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    fileName = openFileDialog.FileName;
                }
            }

            if (string.IsNullOrWhiteSpace(fileName))
            {
                // 没有选择文件,还是走默认的Handler
                return base.GetResourceHandler(chromiumWebBrowser, browser, frame, request);
            }
            // 否则使用选择的资源返回
            return new MyResourceHandler(fileName);
        }

        return base.GetResourceHandler(chromiumWebBrowser, browser, frame, request);
    }
}

IResourceHandler

根据上文,我们进一步探究IResourceHandler,对该Handler,官方有一个默认的实现:RequestHandler,该Handler通过阅读源码可以知道是网络加载的Handler,这里为了实现我们自定义拦截策略,我们最好单独实现自己的IResourceHandler。对于该接口,有如下的注释:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>
/// Class used to implement a custom resource handler. The methods of this class will always be called on the CEF IO thread.
/// Blocking the CEF IO thread will adversely affect browser performance. We suggest you execute your code in a Task (or similar).
/// To implement async handling, spawn a new Task (or similar), keep a reference to the callback. When you have a
/// fully populated stream, execute the callback. Once the callback Executes, GetResponseHeaders will be called where you
/// can modify the response including headers, or even redirect to a new Url. Set your responseLength and headers
/// Populate the dataOut stream in ReadResponse. For those looking for a sample implementation or upgrading from
/// a previous version <see cref="T:CefSharp.ResourceHandler" />. For those upgrading, inherit from ResourceHandler instead of IResourceHandler
/// add the override keywoard to existing methods e.g. ProcessRequestAsync.
/// </summary>
public interface IResourceHandler : IDisposable
{ ... }

该类的注释意思大致为:我们可以通过实现该接口来实现自定义资源的处理类。该类中的方法总是在CEF的IO线程中调用。然而,阻塞CEF IO线程将会不利于浏览器的性能。所以官方建议开发者通过把自己的处理代码放在Task(或是类似的异步编程框架)中异步执行,然后在完成或取消(失败)时,在异步中调用callback对应的操作函数(continue、cancel等方法)。当你拥有一个完全填充(fully populated)好了的Stream的时候,再执行callback(这一步对应Open方法)。一旦callback执行了,GetResponseHeaders这个方法将会调用,于是你可以在这个方法里面对Reponse的内容包括headers进行修改,或者甚至是重定向到一个新的Url。设置你自己的reponseLength和headers。接下来,通过在ReadResponse(实际上即将作废,而是Read)函数中,实现并填充dataOut这个Stream。最终CEF会对该Stream进行读取数据,获得资源数据。

事实上,该Handler的实现可以有很多花样,这里我们实现一个最简单的。

Dispose

对于通常进行资源释放的Dispose,因为我们这里只是一个Demo,所以暂时留空。

Open(ProcessRequest)

官方注释指出,ProcessRequest将会在不久的将来弃用,改为Open。所以ProcessRequest我们直接返回true。对于Open方法,其注释告诉我们:

  • 要想要立刻进行资源处理(同步),请设置handleRequest参数为true,并返回true
  • 决定稍后再进行资源的处理(异步),设置handleRequest为false,并调用callback对应的continue和cancel方法来让请求处理继续还是取消,并且当前Open返回false。
  • 要立刻取消资源的处理,设置handleRequest为true,并返回false。

也就是说,handleRequest的true或false决定是同步还是异步处理。若同步,则Cef会立刻通过Open的返回值true或false来决定后续继续进行还是取消。若为异步,则Cef会通过异步的方式来检查callback的调用情况(这里的callback实际上是要我们创建Task回调触发的)。这里我们选择同步的方式(选择异步也没有问题)编写如下的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public bool Open(IRequest request, out bool handleRequest, ICallback callback)
{
    handleRequest = true;
    return true;
}
GetResponseHeaders

在上小节中我们已经完成了对资源数据的入口(Open)的分析。既然我们已经告诉了Cef我们准备开始进行资源请求的处理了,那么接下来我们显然需要着手进行资源的处理。根据前面的概要注释,我们需要实现GetResponseHeaders方法,因为这是资源处理的第二步。该方法的注释如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>
/// Retrieve response header information. If the response length is not known
/// set <paramref name="responseLength" /> to -1 and ReadResponse() will be called until it
/// returns false. If the response length is known set <paramref name="responseLength" />
/// to a positive value and ReadResponse() will be called until it returns
/// false or the specified number of bytes have been read.
/// 
/// It is also possible to set <paramref name="response" /> to a redirect http status code
/// and pass the new URL via a Location header. Likewise with <paramref name="redirectUrl" /> it
/// is valid to set a relative or fully qualified URL as the Location header
/// value. If an error occured while setting up the request you can call
/// <see cref="P:CefSharp.IResponse.ErrorCode" /> on <paramref name="response" /> to indicate the error condition.
/// </summary>
void GetResponseHeaders(IResponse response, out long responseLength, out string redirectUrl);

Summary翻译解释如下:获取响应头信息。如果响应的数据长度未知,则设置responseLength-1,然后CEF会一直调用ReadResponse(即将废除,实际上是Read方法)直到该Read方法返回false。如果响应数据的长度是已知的,可以直接设置responseLength长度为一个正数,然后ReadResponseRead)将会一直调用,直到该Read方法返回false或者在已经读取的数据的字节长度达到了设置的responseLength的值。当然你也可以通过设置response.StatusCode值为重定向的值(30x)以及redirectUrl为对应的重定向Url来实现资源重定向。

在本文中,我们采取简单的方式:直接返回资源的长度,然后交给下一步的Read方法来进行真正的资源处理。在该步骤中,我们编写获取本地文件字节数据来实现js和css文件的本地加载,并且将该数据保存在该ResourceHanlder实例私有变量中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void GetResponseHeaders(IResponse response, out long responseLength, out string redirectUrl)
{
    using (FileStream fileStream = new FileStream(this._localResourceFileName, FileMode.Open, FileAccess.Read))
    {
        using (BinaryReader binaryReader = new BinaryReader(fileStream))
        {
            long length = fileStream.Length;
            this._localResourceData = new byte[length];
            // 读取文件中的内容并保存到私有变量字节数组中
            binaryReader.Read(this._localResourceData, 0, this._localResourceData.Length);
        }
    }

    responseLength = this._localResourceData.LongLength;
    redirectUrl = null;
}
Read

该方法的定义和注释如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>
/// Read response data. If data is available immediately copy up to
/// dataOut.Length bytes into dataOut, set bytesRead to the number of
/// bytes copied, and return true. To read the data at a later time keep a
/// pointer to dataOut, set bytesRead to 0, return true and execute
/// callback when the data is available (dataOut will remain valid until
/// the callback is executed). To indicate response completion set bytesRead
/// to 0 and return false. To indicate failure set bytesRead to &lt; 0 (e.g. -2
/// for ERR_FAILED) and return false. This method will be called in sequence
/// but not from a dedicated thread.
/// 
/// For backwards compatibility set bytesRead to -1 and return false and the ReadResponse method will be called.
/// </summary>
bool Read(Stream dataOut, out int bytesRead, IResourceReadCallback callback);

Summary的翻译大致为:读取响应数据。如果数据是可以立即获得的,那么可以直接将dataOut.Length长度的字节数据拷贝到dataOut这个流中,然后设置bytesRead的值为拷贝的数据字节长度值,最后再返回true。如果开发者希望继续持有dataOut的引用(注释是pointer指针,但是个人觉得这里写为指向该dataOut的引用更好)然后在稍后填充该数据流,那么可以设置bytesRead0,通过异步方式在数据准备好的时候执行callback的操作函数,然后立刻返回true。(dataOut这个流会一直保持不被释放直到callback被调用为止)。为了让CEF知道当前的响应数据已经填充完毕,需要设置bytesRead0然后返回false。要想让CEF知道响应失败,需要设置bytesRead为一个小于零的数(例如ERR_FAILED: -2),然后返回false。这个方法将会依次调用但不是在一个专有线程。

根据上述的注释,总结如下:

  • bytesRead > 0,return true:填充了数据,但Read还会被调用
  • bytesRead = 0,return false:数据填充完毕,当前为最后一次调用
  • bytesRead < 0,return false:出错,当前为最后一次调用
  • bytesRead = 0,return true:CEF不会释放dataOut流,在异步调用中准备好数据后调用callback

针对本例,我们增加一个该类的私有变量_dataReadCount用于标识已读的资源数据字节量并在构造函数中初始化为0。

每次在Read中进行读取的时候,首先检查剩余待读取字节数this._localResourceData.LongLength - this._dataReadCount,如果该值为零,则表明已经将所有的数据通过dataOut拷贝给了外围,此时设置bytesRead为0,直接返回false;若剩余值大于0,则需要继续进行拷贝操作,但需要注意的是dataOut并不是一个无限大的流,而是一个类似于缓存的流,它的Length值为2^16 = 65536,所以我们需要设置bytesRead来让外围知道我们实际在这个流中放了多少字节的数据。同时在使用Stream.WriteAPI的时候,需要设置正确的offset和count。

最终,Read的实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public bool Read(Stream dataOut, out int bytesRead, IResourceReadCallback callback)
{
    int leftToRead = this._localResourceData.Length - this._dataReadCount;
    if (leftToRead == 0)
    {
        bytesRead = 0;
        return false;
    }

    int needRead = Math.Min((int)dataOut.Length, leftToRead); // 最大为dataOut.Lenght
    dataOut.Write(this._localResourceData, this._dataReadCount, needRead);
    this._dataReadCount += needRead;
    bytesRead = needRead;
    return true;
}
其他的几个方法

对于Cancel和Skip方法,在本例不会调用,所以这里使用默认实现,不进行讨论,感兴趣的伙伴可以自己去研究。

最终效果

通过上文的代码设计和编写,我们最终完成了一个简单的资源拦截及自定义处理的Example。首先我们在不进行资源拦截的情况下,加载我们的web页面:

可以看到界面中呈现“test1 js file”的字样以及背景色为海蓝色。接下来我们开启资源拦截,再次加载页面,在加载过程中会有对应资源的拦截时的弹窗以及我们需要选择我们自定义的资源文件:

完成处理后,得到如下的显示页面:

源码

本Example的源码已经开源在Github上,整个Demo较为简单,主要是对本文的验证

链接

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-08-232,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
AWS CDK | IaC 何必只用 Yaml
近年来基础设施即代码(IaC)的方式被越来越多的开发者和管理者所采用,各大公有云都提供了使用 IaC 管理自己云资源的方式,如 AWS 的 CloudFormation、阿里云的 ROS 等,而第三方的 Terraform 也有各大公有云的 Provider。越来越多像我一样的云资源运维和管理者开始采用 IaC 的方式对云资源进行创建、运维和管理。
郭旭东
2021/02/01
2.1K0
基于AWS EKS的K8S实践 - 集群搭建
基于AWS EKS的K8S实践系列文章是基于企业级的实战文章,一些设置信息需要根据公司自身的网络等要求进行设置,如果大家有问题讨论或咨询可以后台私信我或者加入知识星球问我,知识星球的加入方式在文章末尾。
shysh95
2023/08/23
6220
基于AWS EKS的K8S实践 - 集群搭建
AMBERSQUID 云原生挖矿恶意软件疑似与印尼黑客有关
Sysdig 的研究人员发现了一种新的云原生挖矿攻击行动,并将其命名为 AMBERSQUID。攻击针对不太常用的 AWS 服务,如 AWS Amplify、AWS Fargate 和 Amazon SageMaker。这些不常见的服务往往意味着其安全性也会被忽视,AMBERSQUID 可能会让受害者每天损失超过 1 万美元。
FB客服
2023/10/06
4730
AMBERSQUID 云原生挖矿恶意软件疑似与印尼黑客有关
基于AWS EKS的K8S实践 - 如何打通云企业网集群内外服务调用
service 通常用作集群内服务之前的通信,ingress 通常用于暴露给集群外的服务使用。
shysh95
2023/08/23
4490
基于AWS EKS的K8S实践 - 如何打通云企业网集群内外服务调用
在 EKS 上管理 NodeGroup
最初使用的 NodeGroup 的 InstantType 规格太低,不太好用,所以需要增加一个新的 NodeGroup 。
云云众生s
2024/03/27
1600
弹性 Kubernetes 服务:Amazon EKS
Amazon EKS(Amazon Elastic Kubernetes Service)是一项托管服务,允许您在 AWS 云上运行 Kubernetes,而无需设置、管理或维护自己的控制平面和节点。
网络技术联盟站
2023/03/13
3.8K0
弹性 Kubernetes 服务:Amazon EKS
AWS 容器服务的安全实践
随着微服务的设计模式得到越来越多开发者的实践,容器和微服务已经在生产环境中开始了规模化的部署。在这一过程中,也面临着越来越多的挑战。比如说,很多的微服务之间是相互依赖的,我们需要有更多的手段和方式来进行微服务的计划,扩展和资源管理,另外微服务之间的隔离更少,它们通常会共享内核或者网络,也对安全性提出了更高的要求。
我是阳明
2021/06/25
2.9K0
AWS 容器服务的安全实践
零停机给Kubernetes集群节点打系统补丁
Salesforce 的 Einstein Vision 和语言服务部署在 AWS Elastic Kubernetes Service(EKS) 集群上。其中有一个最主要的安全和合规性需求,就是给集群节点的操作系统打补丁。部署服务的集群节点需要通过打补丁的方式进行系统的定期更新。这些补丁减少了可能让虚拟机暴露于攻击之下的漏洞。
深度学习与Python
2021/06/08
1.3K0
零停机给Kubernetes集群节点打系统补丁
AWS简单搭建使用EKS二
紧接AWS简单搭建使用EKS一,eks集群简单搭建完成。需要搭建有状态服务必然就用到了storageclass 存储类,这里用ebs记录以下
对你无可奈何
2023/02/15
1.6K0
EKS 的 VPC 详解
通过 eksctl 创建集群,默认情况下会创建一个专门的 VPC 以及相关的资源,看起来较为复杂,所以有必要了解一下默认的 VPC ,然后才能更好的实现更个性化的配置。
云云众生s
2024/03/27
3350
创建 EKS 管理员
EKS 管理员不仅需要登录管理控制台,也需要通过 eksctl 管理集群,还需要能够管理 EC2 和 CloudFormation 等资源,所以需要较高的权限。
云云众生s
2024/03/27
2070
[工作随笔]Python 和 CDK的aws-route53那些事
AWS CDK,与使用 YAML(或 JSON)的声明式方法相比,CDK 允许您命令式声明基础设施。主要语言为 TypeScript,同时也支持另外几种语言。
DriverZeng
2022/10/31
1K0
[工作随笔]Python 和 CDK的aws-route53那些事
配置语言的黄金时代
我认为我们当前所认知的 DevOps 即将走到尽头。至少,其中的 Ops 会如此。随着云基础设施成为应用程序关注的重点,越来越多的 ops 任务由云本身完成或内置于应用程序中。剩下的就是供应和管理应用程序所需的基础设施。这关系到所有的相关附属内容,例如安全性和网络。
深度学习与Python
2021/03/12
3.3K0
从Wiz Cluster Games 挑战赛漫谈K8s集群安全
11月初,云安全公司WIZ发起了一项名为“EKS Cluster Games”的CTF挑战赛[1],引发了众多云安全爱好者的参与。本次挑战赛的主题是关于容器集群的攻击技巧。比赛共包括5个场景,整体存在一定的难度,非常值得挑战和学习。
云鼎实验室
2023/12/16
6020
从Wiz Cluster Games 挑战赛漫谈K8s集群安全
AWS CDK 漏洞使黑客能够接管 AWS 账户
Aquasec 的安全研究人员最近在 AWS Cloud Development Kit (CDK) 中发现了一个关键漏洞,该漏洞可能允许攻击者获得对目标 AWS 账户的完全管理访问权限。
星尘安全
2024/10/28
1720
AWS CDK 漏洞使黑客能够接管 AWS 账户
Deploy TiDB on AWS EKS
how to deploy a TiDB cluster on AWS Elastic Kubernetes Service (EKS) ?
杨漆
2021/03/09
1.2K0
Deploy TiDB on AWS EKS
资源 | Parris:机器学习算法自动化训练工具
选自GitHub 机器之心编译 参与:刘晓坤、路雪、蒋思源 Parris 是一个自动化训练机器学习算法的工具。如果各位读者经常需要构建并训练机器学习模型,且花费很多时间来设置运行服务器,使用远程登录服务以监控进程等。那么这个工具将对大家十分有帮助,甚至我们都不需要使用 SSH 访问服务器以完成训练。机器之心简要介绍了该工具,更详细的内容请查看该 GitHub 项目。 项目地址:https://github.com/jgreenemi/Parris 安装 我们需要一个 AWS 账户,并将 AWS 证书加载到工
机器之心
2018/05/10
3.1K0
配置 Windows 节点组
创建 cluster 时我们没有指定 --install-vpc-controllers 参数,所以我们需要首先安装 vpc controller :
云云众生s
2024/03/27
1510
K8S-Node自动扩容项目CA源码分析(上)
上一篇文章介绍了 k8s 自动扩缩容的三种方式:HPA、VPA、CA,以及各自的使用场景和架构。本文针对 CA 做源码分析。
kinnylee
2022/07/02
1.2K0
基础设施即代码的历史与未来
基础设施即代码(Infrastructure as Code)是软件开发中一个引人入胜的领域。虽然作为一门学科,它相对年轻,但在其短暂的存在期间,它已经经历了几次具有开创性意义的转变。我认为它是当今软件开发创新最热门的领域之一,许多参与者——从大型科技公司到初创企业——都在创造新的方法。如果完全实现,这些方法有可能彻底改变我们编写和部署软件的方式。
云云众生s
2024/03/27
4590
相关推荐
AWS CDK | IaC 何必只用 Yaml
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验