第十一章:Kubernetes API服务器的安全防护

本章内容包括:

  • 了解认证机制
  • ServiceAccounts是什么及使用的原因
  • 了解基于角色(RBAC)的权限控制插件
  • 使用角色和角色绑定
  • 使用集群角色和集群角色绑定
  • 了解默认角色及其绑定

1 了解认证机制

在前面的内容中,我们说到API服务器可以配置一个到多个认证的插件(授权插件同样可以)。API服务器接收到的请求会经过一个认证插件的列表,列表中的每个插件都可以检查这个请求和尝试确定谁在发送这个请求。列表中的第一个插件可以提取请求中客户端的用户名、用户ID和组信息,并返回给API服务器。API服务器会停止调用剩余的认证插件并直接进入授权阶段。

目前有几个认证插件是直接可用的。它们使用以下方法获取客户端的身份认证:

  • 客户端证书
  • 传入在HTTP头重的认证token
  • 基础的HTTP认证
  • 其他
    启动API服务器时,通过命令行选项可以开启认证插件。

1.1 用户和组

认证插件会返回已经认证过用户的用户名和用户组。kubernetes不会在任何地方存储这些信息,这些信息被用来验证用户是否被授权执行某个操作。

了解用户

kubernetes区分了两种连接到API服务器的客户端:

  • 真实的人
  • pod(pod中运行的应用)
    这两类客户端都使用上述的认证插件进行认证。用户应该被管理在外部系统中,例如单点登录系统(SSO),但是pod使用一种service accounts的机制,该机制被创建和存储在集群中作为ServiceAccount资源。没有资源代表用户账户,这也就意味着不能通过API服务器来创建、更新或删除用户。但可以通过RBAC(基于角色的访问控制)来管理用户的权限。

了解组

正常用户和serviceAccount都可以属于一个或多个组。我们已经将过认证插件会连同用户名和用户ID返回组。组可以一次给多个用户赋予权限,而不是必须单独给用户赋予权限。

由插件返回的组仅仅是表示组名称的字符串,但是系统内置的组会有一些特殊的含义。

  • system:unauthenticated 组⽤于所有认证插件都不会认证客户端⾝份的请求
  • system:authenticated 组会⾃动分配给⼀个成功通过认证的⽤户。
  • system:serviceaccounts 组包含所有在系统中的ServiceAccount。
  • system:serviceaccounts 组包含所有在系统中的ServiceAccount。

1.2 ServiceAccount介绍

现在已经了解到了API服务器要求客户端在服务器上执行操作之前对自己进行身份验证,了 解 了 是 怎 么 通 过 发 送pod/var/run/secrets/kubernetes.io/serviceaccount/token ⽂件内容来进⾏⾝份认证的。这个⽂件通过加密卷挂载进每个容器的⽂件系统中。

但是这个文件代表了什么呢?每个pod上都与一个ServiceAccount相关联,它代表了运行在pod中应用程序的身份证明。token文件持有ServiceAccount的认证token。

应用程序使用这个token连接API服务器时,身份认证插件会对ServiceAccount进行身份认证,并将ServiceAccount的用户名传回API服务器内部。ServiceAccount用户名格式像这样system:serviceaccount:<namespace>:<service account name>

API服务器将这个用户名传给已配置好的授权插件,这决定该应用程序所尝试执行的操作是否被ServiceAccount允许执行。

ServiceAccount只不过是一种运行在pod中的应用程序和API服务器身份认证的一种方式。如前所述,应用程序通过在请求中传递ServiceAccount token来实现这一点。

了解ServiceAccount资源

ServiceAccount就像Pod、Secret、Configmap等一样都是资源,它们作用在单独的命名空间,为每个命名空间自动创建一个默认的ServiceAccount。可以像其他资源一样查看ServiceAccount

kubectl get sa
NAME      SECRETS   AGE
default   1         1d

当前命名空间只包含default ServiceAccount,其他额外的ServiceAccount可以在需要时添加。每个pod都与一个ServiceAccount相关联,但是多个pod可以使用相同的一个sa,且只能使用相同命名空间的sa。

ServiceAccount如何和授权进行绑定

在pod的manifest文件中,可以用指定账户名称的方式指定一个ServiceAccount。如果不显式的指定,pod会使用命名空间中默认的ServiceAccount。spec.serviceAccountName: default

可以通过将不同的ServiceAccount赋值给pod来控制每个pod可以访问的资源。当API服务器接收到一个带有认证token的请求时,服务器会用这个token来验证发送请求的客户端所关联的Service Account是否允许执行请求的操作。API服务器通过管理员配置好的系统级别认证插件来获取这些信息。其中一个现成的授权插件是基于角色控制的插件(RBAC)。

1.3 创建ServiceAccount

我们已经知道了可以自定义ServiceAccount,但是为什么要自定义呢,使用默认的不就好了吗?其中一个显而易见的原因就是集群安全性。不需要读取任何集群元数据的pod应该运行在一个受限制的账户下,这个账户不允许它们检索或修改部署在集群中的任何资源。需要检索元数据的pod应该运行在只允许读取这些对象元数据的ServiceAccount下。反之,需要修改这些对象的pod应该在它们自己的ServiceAccount下运行,这些Service Account允许修改API对象。

下面让我们来看下如何使用ServiceAccount。

$ kubectl describe sa 
Name:                crc
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  crc-public  # 这些会被自动的添加到使用这个ServiceAccount的所有pod中crc-vpc
Mountable secrets:   crc-token-pcg46 # 如果强制使用挂载在密钥,那么使用这个ServiceAccount的pod只能挂载这些密钥
Tokens:              crc-token-pcg46  # 认证token,第一个token挂载在容器内$ kubectl describe secret crc
Name:         crc
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: defaultkubernetes.io/service-account.uid: 322faf17-27aa-4c1c-b7d8-705538d40811Type:  kubernetes.io/service-account-tokenData
====
ca.crt:     1025 bytes
namespace:  7 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6InVpZnRrdVUzNTVRJWa

当创建好ServiceAccount之后,查看token secret,会发现其中包含的东西与默认的secret是一致的,但内容肯定有所不同。ServiceAccount中使用额身份认证token使用的是JWT token(JSON Web Token)。

了解ServiceAccount上的可挂载密钥

通过kubectl describe命令查看ServiceAccount时,token会显示在可挂载列表中。在之前我们了解了如何创建密钥并且把它们挂载进一个pod里。在默认情况下,pod可以挂载任何它需要的密钥。但是我们通过对ServiceAccount进行配置,让pod只允许挂载ServiceAccount中列出的可挂载密钥。

apiVersion: v1
kind: ServiceAccount
metadata:annotations:kubernetes.io/enforce-mountable-secrets: "true"name: my-serviceaccountnamespace: my-namespace

如 果 ServiceAccount 被 加 上 了 这 个 注 解 , 任 何 使 ⽤这 个ServiceAccount的pod只能挂载进ServiceAccount的可挂载密钥——这些 pod不能使⽤其他的密钥。

了解ServiceAccount的镜像拉取密钥

Service也可以包含镜像拉取密钥的list。还记得在第六章时所使用的镜像拉取密钥吗?

apiVersion: v1
kind: Pod
metadata:name: private-pod
spec:imagePullSecrets:- name: mydockerhubsecret  # 指定Secret名称containers:- image: username/private:tagname: main

ServiceAccount的镜像拉取密钥和它的可挂载密钥表现有些轻微不同。和可挂载密钥不同的是,ServiceAccount中的镜像拉取密钥不是⽤来确定⼀个pod可以使⽤哪些镜像拉取密钥的。添加到ServiceAccount中的镜像拉取密钥会⾃动添加到所有使⽤这个ServiceAccount的pod中。向ServiceAccount中添加镜像拉取密钥可以不必对每个pod都单独进⾏镜像拉取密钥的添加操作。

请注意:如果没有设置RBAC授权插件的话,默认给了ServiceAccount全部的权限。

如果集群没有使⽤合适的授权,创建和使⽤额外的ServiceAccount并没有多⼤意义,因为即使默认的ServiceAccount也允许执⾏任何操作。在这种情况下,使⽤ServiceAccount的唯⼀原因就是前⾯讲过的加强可挂载密钥,或者通过ServiceAccount提供镜像拉取密钥。如果使⽤RBAC授权插件,创建额外的ServiceAccount实际上是必要的,我们会在后⾯讨论RBAC授权插件的使⽤。

2 通过基于角色的权限控制加强集群安全

从1.6版本开始,集群安全性显著提高。在早期版本中,如果你设法从集群中的⼀个pod获得了⾝份认证token,就可以使⽤这个token在集群中执⾏任何你想要的操作。如果在⾕歌上搜索,可以找到演⽰如何使⽤ pathtraversal(或者directory traversal)攻击的例⼦(客户端可以检索位于We b服务器的We b根⽬录之外的⽂件)。通过这种⽅式可以获取token,并⽤这个token在不安全的 Kubernetes集群中运⾏恶意的pod。

但是在1.8版本中,RBAC授权插件升级为GA(通用可用性),并且默认在集群上开启。RBAC会阻止未授权的用户查看和修改集群状态。除非授予默认的ServiceAccount额外的特权,否则默认的ServiceAccount不允许查看集群状态,更不用说以任何方式取修改集群状态。

注意 除了RBAC插件,Kubernetes也包含其他的授权插件,⽐如基于属性的访问控制插件(ABAC)、WebHook插件和⾃定义插件实现。但是,RBAC插件是标准的。

2.1 介绍RBAC授权插件

Kubernetes API服务器可以配置使用一个授权插件来检查是否允许用户请求的动作执行。因为API服务器对外暴露了REST接口,用户可以通过向服务器发送HTTP请求来执行动作,通过在请求汇总包含认证凭证来进行认证(认证token、用户名和密码或者客户端证书)。

了解动作

但是有什么动作?如你所了解的,REST客户端发送GET、POST、PUT、DELETE和其他类型的HTTP请求到特定的URL路径上,这些路径表⽰特定的REST资源。在Kubernetes中,这些资源是Pod、Service、Secret,等等。以下是Kubernetes请求动作的⼀些例⼦:

  • 获取pod创建服务
  • 创建服务
  • 更新密钥

这些⽰例中的动词(get、create、update)映射到客户端请求的 HTTP⽅法(GET、POST、PUT)上。名词(Pod、Service、Secret)显然是映射到Kubernetes上的资源。

例如RBAC这样的授权插件运⾏在API服务器中,它会决定⼀个客户端是否允许在请求的资源上执⾏请求的动词。

HTTP方法单一资源动词集合的动词
GET、HEADget(以及watch用于监听)list(以及watch)
POSTcreaten/a
PUTuodaten/a
PATCHpatchn/a
DELETEdeletedeletecollection
除了可以对全部资源类型应⽤安全权限,RBAC规则还可以应⽤于特定的资源实例(例如,⼀个名为myservice的服务),并且后⾯你会看到权限也可以应⽤于non-resource(⾮资源)URL路径,因为并不是 API服务器对外暴露的每个路径都映射到⼀个资源(例如 /api路径本⾝或服务器健康信息在的路径/healthz)。

了解RBAC插件

顾名思义,RBAC授权插件将用户角色作为决定用户能否执行操作的关键因素。主体(一个人、一个Service或一组用户或ServiceAccount)和一个或多个角色相关联,每个角色被允许在特定的资源上执行特定的动词。

通过RBAC插件管理授权是简单的,这⼀切都是通过创建四种RBAC特定的Kubernetes资源来完成的,我们会在下⾯学习这个过程。

2.2 介绍RBAC资源

Role(⾓⾊)和ClusterRole(集群⾓⾊),它们指定了在资源上可以执⾏哪些动词。RoleBinding ( ⾓ ⾊ 绑 定 ) 和 ClusterRoleBinding ( 集群 ⾓ ⾊ 绑定),它们将上述⾓⾊绑定到特定的⽤户、组或ServiceAccounts上。⾓⾊定义了可以做什么操作,⽽绑定定义了谁可以做这些操作。
在这里插入图片描述

角色和集群角色,或者角色绑定和集群角色绑定之间的区别在于角色和角色绑定是命名空间的资源,而集群角色和集群角色绑定时集群级别的资源。

从图中可以看到,多个⾓⾊绑定可以存在于单个命名空间中(对于⾓⾊也是如此)。同样地,可以创建多个集群绑定和集群⾓⾊。图中显⽰的另外⼀件事情是,尽管⾓⾊绑定是在命名空间下的,但它们也可以引⽤不在命名空间下的集群⾓⾊,但不可用绑定其他命名空间下的角色。
在这里插入图片描述

可以在APIServer启动选项中使用--authorization-mode=RBAC,Node开启RABC及node授权插件,node授权插件专门为Kubernetes节点设计的授权机制,确保节点只能访问和修改与其自身相关的资源。

2.3 使用Role和RoleBinding

Role资源定义了哪些操作可以在哪些资源上执行。下⾯的代码清单定义了⼀个Role,它允许⽤户获取并列出foo命名空间中的服务。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadate:namespace: fooname: service-reader
rules:
- apiGroups: [""]   # Service是核心apiGroup的资源,所有没有apiGroup名verbs: ["get","list"]  # 获取独立的Service并且列出所有允许的服务resources: ["services"] # 这条规则和服务有关,必须使用复数形式

这个Role资源会在foo命名空间中创建出来。在第8章中,你了解到每个资源类型属于⼀个API组,在资源清单(manifest)的apiVersion字段中指定API组(以及版本)。在⾓⾊定义中,需要为定义包含的每个规则涉及的资源指定apiGroup。如果你允许访问属于不同API组的资源,可以使⽤多种规则。

绑定角色到ServiceAccount

⾓⾊定义了哪些操作可以执⾏,但没有指定谁可以执⾏这些操作。要做到这⼀点,必须将⾓⾊绑定⼀个到主体,它可以是⼀个 user(⽤户)、⼀个ServiceAccount或⼀个组(⽤户或ServiceAccount的组)。

apiVersion: rbac.authorization.k8s.io/v1 
kind: RoleBinding 
metadata: name: read-nodes 
roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: service-readersubjects: - kind: ServiceAccount name: my-service-account namespace: default- kind: ServiceAccount name: sa2 namespace: default

2.4 使用ClusterRole和ClusterRoleBinding

除了这些命名空间⾥的资源,还存在两个集群级别的RBAC资源:ClusterRole和ClusterRoleBinding,它们不在命名空间⾥。让我们看看为什么需要它们。

⼀个常规的⾓⾊只允许访问和⾓⾊在同⼀命名空间中的资源。如果你希望允许跨不同命名空间访问资源,就必须要在每个命名空间中创建⼀个Role和RoleBinding。如果你想将这种⾏为扩展到所有的命名空间(集群管理员可能需要),需要在每个命名空间中创建相同的 Role和RoleBinding。当创建⼀个新的命名空间时,必须记住也要在新的命名空间中创建这两个资源。

正如前面所了解到的,一些特定的资源完全不在命名空间中。API服务器也会对外暴露一些不表示资源的URL路径(例如/healthz)。常规角色不能对这些资源或非资源型URL进行授权,但是ClusterRole可以。

ClusterRole是⼀种集群级资源,它允许访问没有命名空间的资源和⾮资源型的URL,或者作为单个命名空间内部绑定的公共⾓⾊,从⽽避免必须在每个命名空间中重新定义相同的⾓⾊。

允许访问集群级别的资源

可以使⽤ClusterRole来允许集群级别的资源访问。让我们来了解⼀下如何允许pod列出集群中的PersistentVolume。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadate:name: service-reader
rules:
- apiGroups: [""]   verbs: ["get","list"]  resources: ["persistentvolumes"] 

需要将ClusterRole绑定到ServiceAccount来允许它这样做。ClusterRole可以通过常规的RoleBinding(⾓⾊绑定)来和主体绑定,但绑定后不能访问非命名空间资源。尽管你可以创建⼀个RoleBinding并在你想开启命名空间资源的访问时引⽤⼀个ClusterRole,但是不能对集群级别(没有命名空间的)资源使⽤相同的⽅法。必须始终使⽤ClusterRoleBinding来对集群级别的资源进⾏授权访问。

apiVersion: rbac.authorization.k8s.io/v1 
kind: ClusterRoleBinding 
metadata: name: read-nodes 
roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: service-readersubjects: - kind: ServiceAccount name: my-service-account amespace: foo

在这里插入图片描述

记住⼀个RoleBinding不能授予集群级别的资源访问权限,即使它引⽤了⼀个ClusterRoleBinding。

允许访问非资源型URL

我们已经提过,API服务器也会对外暴露⾮资源型的URL。访问这些URL也必须要显式地授予权限;否则,API服务器会拒绝客户端的请求 。 通 常 , 这 个 会 通 过 system:discoveryClusterRole 和 相 同 命 名 的ClusterRoleBinding帮你⾃动完成,它出现在其他预定义的ClusterRoles和ClusterRoleBindings中

$ kubectl get clusterrole system:discovery -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:annotations:rbac.authorization.kubernetes.io/autoupdate: "true"name: system:discovery
rules:
- nonResourceURLs:   # 指向非资源型URL为不是资源- /api- /api/*- /apis- /apis/*- /healthz- /livez- /openapi- /openapi/*- /readyz- /version- /version/verbs:- get

对于⾮资源型URL,使⽤普通的HTTP动词,如post、put和 patch,⽽不是create或update。动词需要使⽤⼩写的形式指定。

同样有一个ClusterRoleBinding绑定ClusterRole

root:~$ kubectl get clusterrolebinding system:discovery -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:annotations:rbac.authorization.kubernetes.io/autoupdate: "true"name: system:discovery
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: system:discovery
subjects:
- apiGroup: rbac.authorization.k8s.iokind: Groupname: system:authenticated   # 绑定到认证用户,说明认证过后的用户都能访问

2.5 使用ClusterRole来授权访问指定命名空间中的资源

ClusterRole不是必须⼀直和集群级别的ClusterRoleBinding捆绑使⽤。它们也可以和常规的有命名空间的RoleBinding进⾏捆绑。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadate:name: service-reader
rules:
- apiGroups: [""]   verbs: ["get","list"]  resources: ["persistentvolumes"] 

这个集群角色能做什么,这取决于它是和ClusterRoleBinding还是和RoleBinding绑定(可以和其中的⼀个进⾏绑定)。如果你创建了⼀个ClusterRoleBinding并在它⾥⾯引⽤了ClusterRole,在绑定中列出的主体可以在所有命名空间中查看指定的资源。相反,如果你创建的是⼀个RoleBinding,那么在绑定中列出的主体只能查看在RoleBinding命名空间中的资源。

使用ClusterRoleBinding
在这里插入图片描述

使用RoleBinding
在这里插入图片描述

2.6 总结Role、ClusterRole、Rolebinding和ClusterRoleBinding的组合

我们已经介绍了许多不同的组合,可能很难记住何时去使⽤对应的每个组合。下面这张图可能会帮助你更好的记忆。
在这里插入图片描述

2.7 了解默认的ClusterRole和ClusterRoleBinding

Kubernetes提供了⼀组默认的ClusterRole和ClusterRoleBinding,每次API服务器启动时都会更新它们。这保证了在你错误地删除⾓⾊和绑定,或者Kubernetes的新版本使⽤了不同的集群⾓⾊和绑定配置时,所有的默认⾓⾊和绑定都会被重新创建。
在这里插入图片描述

view、edit、admin和cluster-admin ClusterRole是最重要的⾓⾊,它们应该绑定到⽤户定义pod中的ServiceAccount上。

⽤view ClusterRole允许对资源的只读访问

默认的view ClusterRole,它允许读取⼀个命名空间中的⼤多数资源,除了Role、RoleBinding和 Secret。你可能会想为什么Secrets不能被读取?因为Secrets中的某⼀个可能包含⼀个认证token,它⽐定义在view ClusterRole中的资源有更⼤的权限,并且允许⽤户伪装成不同的⽤户来获取额外的权限(权限扩散)。

⽤edit ClusterRole允许对资源的修改

edit ClusterRole,它允许你修改⼀个命名空间中的资源,同时允许读取和修改Secret。但是,它也不允许查看或修改Role和RoleBinding,这是为了防⽌权限扩散。

⽤admin ClusterRole赋予⼀个命名空间全部的控制权

⼀个命名空间中的资源的完全控制权是由admin ClusterRole赋予的。有这个ClusterRole的主体可以读取和修改命名空间中的任何资源,除了ResourceQuota和命名空间资源本⾝。edit和admin ClusterRole之间的主要区别是能否在命名空间中查看和修改Role和RoleBinding。

注意 为了防⽌权限扩散,API服务器只允许⽤户在已经拥有⼀个⾓⾊中列出的所有权限(以及相同范围内的所有权限)的情况下,创建和更新这个⾓⾊。

⽤cluster-admin ClusterRole得到完全的控制

通 过 将 cluster-admin ClusterRole 赋 给 主 体 , 主 体 可以 获 得Kubernetes集群完全控制的权限。正如你前⾯了解那样,adminClusterRole不允许⽤户修改命名空间的ResourceQuota对象或者命名空间资源本⾝。如果你想允许⽤户这样做,需要创建⼀个指向cluster-admin ClusterRole的RoleBinding。这使得RoleBinding中包含的⽤户能够完全控制创建RoleBinding所在命名空间上的所有⽅⾯。

如何授予⽤户⼀个集群中所有命名 空 间 的 完 全 控 制 权 。 就 是 通 过 在ClusterRoleBinding ⽽ 不 是RoleBinding中引⽤clusteradmin ClusterRole。

了解其他默认的ClusterRole

默认的ClusterRole列表包含了⼤量其他的ClusterRole,它们以 system:为前缀。这些⾓⾊⽤于各种Kubernetes组件中。在它们之中,可以找到如system:kube-scheduler之类的⾓⾊,它明显是给调度器使⽤的,system:node是给Kubelets组件使⽤的,等等。

虽然Controller Manager作为⼀个独⽴的pod来运⾏,但是在其中运⾏的每个控制器都可以使⽤单独的ClusterRole和ClusterRoleBinding(它们以system:Controller:为前缀)。

这些系统的每个ClusterRole都有⼀个匹配的ClusterRoleBinding,它会 绑 定 到 系 统 组 件 ⽤ 来 ⾝ 份认 证 的 ⽤ 户 上 。 例 如 , system:kube-schedulerClusterRoleBinding 将 名 称 相 同 的 ClusterRole 分 配 给system:kube-scheduler⽤户,它是调度器作为⾝份认证的⽤户名。

2.8 理性地授予授权权限

在默认情况下,命名空间中的默认ServiceAccount除了未经⾝份验证 的 ⽤ 户 没 有 其 他 权 限 ( 你 可 能 记 得 前 ⾯ 的⽰ 例 之 ⼀ ,system:discovery ClusterRole和相关联的绑定 允许任何⼈对⼀些⾮资源型的URL发送GET请求)。因此,在默认情况下,pod甚⾄不能查看集群状态。应该授予它们适当的权限来做这些操作。

显然,将所有的ServiceAccounts赋予cluster-adminClusterRole是⼀个坏主意。和安全问题⼀样,我们最好只给每个⼈提供他们⼯作所需要的权限,⼀个单独权限也不能多(最⼩权限原则)。

为每个pod创建特定的ServiceAccoun

⼀个好的想法是为每⼀个pod(或⼀组pod的副本)创建⼀个特定ServiceAccount,并且把它和⼀个定制的Role(或ClusterRole)通过RoleBinding联系起来(不是ClusterRoleBinding,因为这样做会给其他命名空间的pod对资源的访问权限,这可能不是你想要的)。

如果你的⼀个pod(应⽤程序在它内部运⾏)只需要读取pod,⽽其他的pod也需要修改它们,然后创建两个不同的ServiceAccount,并且让这些pod通过指定在pod spec中的serviceAccountName属性来进⾏使⽤,和你在本章的第⼀部分了解的那样。不要将这两个pod所需的所有必要权限添加到命名空间中的默认ServiceAccount上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/390980.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构链表2(常考习题1)(C语言)

移除链表元素&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 解题思路&#xff1a; 情况1&#xff1a; 情…

python dash框架

Dash 是一个用于创建数据分析型 web 应用的 Python 框架。它由 Plotly 团队开发&#xff0c;并且可以用来构建交互式的 web 应用程序&#xff0c;这些应用能够包含图表、表格、地图等多种数据可视化组件。 Dash 的特点&#xff1a; 易于使用&#xff1a;Dash 使用 Python 语法…

深入解析 KMZ 文件的处理与可视化:从数据提取到地图展示项目实战

文章目录 1. KMZ 文件与 KML 文件简介1.1 KMZ 文件1.2 KML 文件 2. Python 环境配置与依赖安装3. 代码实现详解3.1 查找 KMZ 文件3.2 解压 KMZ 文件3.3 解析 KML 文件3.4 可视化 KMZ 数据 4. 项目实战4.1. 数据采集4.2. 项目完整代码 5. 项目运行与结果展示6. 总结与展望 在处理…

将后台传来的数据,转成easyui-tree所需格式

easyui 中文文档 EasyUI Tree组件需要一个包含特定属性&#xff08;如id, text, children等&#xff09;的JSON对象数组来初始化。 而后台返回的数据&#xff0c;它可能不是我们直接能拿来用的。 方式一&#xff1a;使用loadFilter函数处理来自Web Services的JSON数据。 $(#…

功能实现——通过阿里云 OSS 实现文件管理

目录 1.需求分析2.阿里云 OSS 开通与配置2.1.登录阿里云官网2.2.搜索 OSS 服务并开通2.3.OSS 配置 3.在项目使用阿里云 OSS3.1.项目环境搭建3.2.代码实现3.2.1.将本地文件上传到阿里云 OSS3.2.2.将前端传入的文件上传到阿里云 OSS3.2.3.下载文件到本地2.3.4.流式下载3.2.4.OSSC…

本地部署文生图模型 Flux

本地部署文生图模型 Flux 0. 引言1. 本地部署1-1. 创建虚拟环境1-2. 安装依赖模块1-3. 创建 Web UI1-4. 启动 Web UI1-5. 访问 Web UI 0. 引言 2024年8月1日&#xff0c;blackforestlabs.ai发布了 FLUX.1 模型套件。 FLUX.1 文本到图像模型套件&#xff0c;该套件定义了文本到…

【收录率高丨最快会后3-4个月EI检索 | 往届均已EI检索】第四届光学与通信技术国际学术会议(ICOCT 2024,8月9-11)

欢迎参加第四届光学与通信技术国际学术会议&#xff08;ICOCT 2024&#xff09;&#xff0c;该会议将于2024年8月9-11日在南京举办。自2021年首次会议以来&#xff0c;ICOCT已经发展成为光学和通信领域较有影响力的国际会议之一&#xff0c;聚焦最前沿的技术进展与未来发展趋势…

【Redis 进阶】哨兵 Sentinel(重点理解流程和原理)

Redis 的主从复制模式下&#xff0c;一旦主节点由于故障不能提供服务&#xff0c;需要人工进行主从切换&#xff0c;同时大量的客户端需要被通知切换到新的主节点上&#xff0c;对于上了一定规模的应用来说&#xff0c;这种方案是无法接受的&#xff0c;于是 Redis 从 2.8 开始…

“八股文“在现代编程面试中的角色重塑:助力、阻力还是桥梁?

&#x1f308;所属专栏&#xff1a;【其它】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的点…

AI人工智能开发环境配置

AI人工智能 为什么使用Python来开发AI 人工智能被认为是未来的趋势技术。 已经有了许多应用程序。 因此&#xff0c;许多公司和研究人员都对此感兴趣。 但是这里出现的主要问题是&#xff0c;在哪种编程语言中可以开发这些 AI 应用程序&#xff1f; 有各种编程语言&#xff0c…

Python 实现股票指标计算——LON

LON - 铁龙长线 1 公式 LC : REF(CLOSE,1); VID : SUM(VOL,2)/(((HHV(HIGH,2)-LLV(LOW,2)))*100); RC : (CLOSE-LC)*VID; LONG : SUM(RC,0); DIFF : SMA(LONG,10,1); DEA : SMA(LONG,20,1); LON : DIFF-DEA; LONMA : MA(LON,10); LONT : LON, COLORSTICK; 2 数据准备…

练题模块环境搭建

文章目录 1.数据库表设计1.practice_set 套卷2.practice_set_detail 套卷细节3.practice_info 练习信息4.practice_detail 练习详情5.E-R图 2.架构设计&#xff08;三层架构&#xff09;3.练题微服务架构搭建1.创建一个练题微服务模块1.创建一个maven项目2.把src删除&#xff0…

Halcon 二维匹配

匹配&#xff1a;在训练图像中呈现一个所谓的模板。系统从这个模板中派生出一个模型&#xff0c;通过使用该模型来定位于搜索图像中的相似模板对象。此方法能够处理打光、杂乱、位置和旋转变换的图像。 匹配优点&#xff1a;鲁棒性和灵活性。匹配不需要对目标进行任何形式的分割…

假期BUUCTF小练习3

文章目录 [极客大挑战 2019]BuyFlag[BJDCTF2020]Easy MD5[HCTF 2018]admin第一种方法 直接登录第二种方法 flack session伪造第三种方法Unicode欺骗 [MRCTF2020]你传你&#x1f40e;呢[护网杯 2018]easy_tornadoSSTI注入 [ZJCTF 2019]NiZhuanSiWei [极客大挑战 2019]BuyFlag 一…

vmware虚拟机linux服务器的IP需要重启才能生效问题

vmware虚拟机linux服务器的IP需要重启才能生效问题 问题说明处理办法关闭&禁用网络管理 再次重启linux服务器&#xff0c;IP显示正常 问题说明 用vmware虚拟的linux服务器&#xff0c;配置了静态IP&#xff0c;但是每次重启liunx&#xff0c;IP都不是设置的静态IP&#xf…

[GWCTF 2019]我有一个数据库1

打开题目&#xff0c;一串乱码&#xff0c;不认识的汉字 打开题目地址&#xff0c;用dirsearch对网站进行扫描&#xff0c;发现几个目录。 打开&#xff0c;其中一个显示为是一个MySQL数据库Version 4.8.1。 发现该数据给具有文件包含漏洞&#xff0c;输入以下代码验证存在 h…

java面向对象编程入门

一、前言&#xff1a; 在Java中&#xff0c;面向对象编程&#xff08;Object-Oriented Programming, OOP&#xff09;是一种核心的编程范式。Java的设计和开发都是基于面向对象的思想。面向对象编程的主要目的是提高代码的可重用性、灵活性和可维护性。以下是Java面向对象编程…

Neutralinojs教程项目实战初体验(踩坑指南),干翻 electron

Neutralinojs 项目实战初体验&#xff08;踩坑指南&#xff09;&#xff0c;干翻 electron 大家好我是csdn的red润 Neutralinojs 官方文档 卧槽卧槽&#xff0c;&#xff01;这个年轻人居然用浏览器把电脑关机了_哔哩哔哩_bilibili正是在下 本教程搭建的是纯原生项目&#x…

LeetCode每日一题_3143.正方形中的最多点数

解题思路&#xff1a;自己&#xff1a;先把points里的点拿来求出坐标系的离原点最远的点&#xff0c;然后根据最远距离新建一个数组&#xff0c;然后把points的点都在新建的数组上标记出来。然后再便利从边长为0的正方形开始&#xff0c;里面是否有重复的标签。但是代码写不出来…

vulhub-wordpress

1.打开wordpress关卡&#xff0c;选择简体中文 添加信息——点击安装WordPress 安装完成——登录 点击外观——编辑主题 可以加入一句话木马&#xff0c;但是我写入的是探针文件 也可以去上传一个带有木马的主题 上传之后会自动解压 1.php就是里面的木马文件