用户身份认证

2023-05-16

0. 背景

计算机本身无法判断坐在显示器前的使用者的身份,也无法确认网络的另一端的是谁。为了明确是谁在访问服务器,必须让客户端自报家门。

通常核对一些登录者本人的信息:

  • 密码:只有本人知道的字符串信息
  • 动态令牌:仅限本人持有的设备内显示的一次性密码
  • 数字证书:仅限本人(终端)持有的信息
  • 生物认证:指纹和虹膜等本人生理信息
  • 身份证号、手机号等:仅限本人持有的信息

1. Basic 认证

Basic 身份认证,是 HTTP 1.0 中引入的认证方案之一。虽然方案比较古老,实现简单,同时存在安全缺陷。通过核对用户名、密码的方式,来实现用户身份的验证。

核心概念

  • Userid
  • Password
  • Realm:认证保护域,其实就是指当前认证的保护范围

关于realm:同一个 server,访问受限的资源多种多样,比如资金信息、机密文档等。可以针对不同的资源定义不同的 realm,并且只允许特定的用户访问。跟Linux下的账户、分组体系很像。

认证流程

在进行 BASIC 认证的过程中,HTTP 的请求头字段会包含 Authorization 字段,Authorization: Basic <用户凭证>,该<用户凭证>是 userid 和 password 的组合而成的 Base64 编码。

GET /securefiles/ HTTP/1.1

Host: www.example.com

Authorization: Basic aHR0cHdhdGNoOmY=

BASIC 认证流程图:

1. 用户在浏览器中访问了受限制的网页资源,但是没有提供用户的身份信息

2. 服务端接收到请求后返回 401 应答码(Unauthorized,未被授权的)要求进行身份验证,并附带提供了一个认证域(Access Authentication)WWW-Authenticate 说明如何进行验证的方法,例如 WWW-Authenticate: Basic realm="Secure Area"Basic 就是验证的模式,而 realm="Secure Area" 则为保护域(告知认证的范围),用于与其他请求 URI 作区别

3. 浏览器收到应答后,会显示该认证域给用户并提示输入用户名和密码,此时用户可以选择录入信息后确定或取消操作

4. 用户输入了用户名和密码后,浏览器会在原请求头新增认证消息字段 Authorization 并重新发送请求,过程如下:

  • 将用户名和密码拼接为 用户名:密码 格式的字符串
  • 将字符串编码为 Base64
  • 拼接 Basic,设置为 Authorization 字段,假设用户名为 admin,密码为 password,则拼接后为 admin:password,使用 Base64 编码后为 YWRtaW46cGFzc3dvcmQ=,那么最终在 HTTP 头部里会是这样:
Authorization: Basic YWRtaW46cGFzc3dvcmQ=

5. 服务端接收了该认证后并返回了用户请求的网页资源。如果用户凭证非法或无效,服务器可能会再次返回 401 应答码,客户端就需要再次输入用户名和密码

缺陷

Basic 认证的安全缺陷比较明显,它通过明文传输用户的密码,在 http 等非加密通信的线路上进行 Basic 认证的过程中如果被人监听,被盗的可能性极高。

除了安全缺陷,Basic 认证还存在无法吊销认证的情况。

2. Digest 认证

“摘要”式认证( Digest authentication)是一个简单的认证机制,最初是为HTTP协议开发的,因而也常叫做HTTP摘要,在 RFC2671 中描述。其身份验证机制很简单,它在密码发出前,先对其应用哈希函数,这相对于 HTTP Basic 认证发送明文而言,更安全。

Digest 认证同样使用质询/响应的方式(challenge/response),即一开始一方会先发送需要认证的请求给另一方,接着使用从另一方接收到的质询码计算生成响应码,最后将响应码返回给对方进行认证的方式。

参数介绍

  • username:用户名
  • realm:同上
  • nonce:服务器发给客户端的随机的字符串,服务器每次产生一个摘要质询时,这个参数都是不一样的。nonce 通常是由一些数据通过 md5 运算构造的。这样的数据通常包括时间标识和服务器的机密短语。这确保每个 nonce 都有一个有限的生命期(也就是过了一些时间后会失效,并且以后再也不会使用),而且是独一无二的(即任何其它的服务器都不能产生一个相同的 nonce)。
nonce = BASE64(time-stamp MD5(time-stamp : ETag : private-key))
  • cnonce:客户端发送给服务器的随机字符串,使得双方都可以查验对方的身份,并对消息的完整性提供一些保护

  • nc:nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量。例如,在响应的第一个请求中,客户端将发送“nc=00000001”。这个指示值的目的是让服务器保持这个计数器的一个副本,以便检测重复的请求

  • qop:质量保护,值一般为auth或auth-int,影响摘要算法。“auth”表示只进行身份查验, “auth-int”表示进行查验外,还有一些完整性保护。
  • opaque:服务端指定的值,客户端需要原值返回。
  • algorithm:摘要算法,值为 MD5 或 MD5-sess,默认为 MD5
  • uri:客户端想要访问的 uri,考虑到经代理转发后 Request-URI 的值可能会修改,所以事先复制一份
  • response:客户端根据算法算出的摘要值。

认证流程

1. 浏览器发送http报文请求一个受保护的资源。

2. 服务端的 web 容器将 http 响应报文的响应码设为 401,响应头部比 Basic 模式复杂:

WWW-Authenticate: Digest realm="myTomcat", qop="auth", nonce="xxxxxxxxxxx", opaque="xxxxxxxx"

3. 浏览器弹出对话框让用户输入用户名和密码,浏览器对用户名、密码、nonce值、HTTP请求方法、被请求资源URI等组合后进行MD5运算,把计算得到的摘要信息发送给服务端。请求头部类似如下:

Authorization: Digest username="xxxxx", realm="myTomcat", qop="auth", nonce="xxxxx", uri="xxxx", cnonce="xxxxxx", nc=00000001, response="xxxxxxxxx", opaque="xxxxxxxxx"

其中 Authorization 内必须包含 username、realm、nonce、uri 和 responce。

4. 服务端 web 容器获取 HTTP 报文头部相关认证信息,从中获取到 username,根据 username 获取对应的密码,同样对用户名、密码、nonce 值、HTTP 请求方法、被请求资源 uri 等组合进行 MD5 运算,计算结果和 response 进行比较,如果匹配则认证成功并返回相关资源,否则再执行 2,重新进行认证。

5. 以后每次访问都要带上认证头部。

计算方法

1. 基本算法

RFC 2069定义,由服务器生成随机数来维护安全性的摘要认证架构。

HA1 = MD5(A1) = MD5(username : realm : password)

HA2 = MD5(A2) = MD5(method : uri)

response = MD5(HA1 : nonce : HA2)

2. 安全增强算法

RFC 2617 引入一系列安全增强的选项;“保护质量”(qop)、随机数计数器由客户端增加、以及客户生成的随机数。这些增强为了防止如选择明文攻击的密码分析。

如果 qop 的值为 "auth",那么:

HA1 = MD5(A1) = MD5(username : realm : password)

HA2 = MD5(A2) = MD5(method : uri)

response = MD5(HA1 : nonce : nc : cnonce : HA2)

如果 qop 的值为 "auth-int",那么:

HA1 = MD5(A1) = MD5(username : realm : password)

HA2 = MD5(A2) = MD5(method : uri : MD5(entityBody))

response = MD5(HA1 : nonce : nc : cnonce : HA2)

如果没有指定 qop,将以基本算法计算。

缺陷

  • RFC 2617 中的许多安全选项都是可选的。如果服务器没有指定保护质量(qop),客户端将以降低安全性的早期的 RFC 2069 的模式操作。
  • Digest 认证容易受到中间人攻击。举例而言,一个中间人攻击者可以告知客户端使用 Basic 认证或早期的 RFC 2069 Digest 认证模式。进一步而言,Digest 认证没有提供任何机制帮助客户端验证服务器的身份。
  • 一些服务器要求密码以可逆加密算法存储。但是,仅存储用户名、realm、和密码的摘要是可能的。
  • 它阻止了使用强密码哈希函数保存密码(因为无论是密码、或者用户名、realm、密码的摘要都要求是可恢复的)。

3. SSL 客户端认证

SSL 客户端认证是借由 HTTPS 的客户端证书完成认证的方式。凭借客户端证书认证,服务器可确认访问是否来自已经登录的客户端。

认证步骤

  1. 接收到需要认证资源的请求,服务器会发送 Certificate Request 报文,要求客户端提供客户端证书。
  2. 用户选择将发送的客户端证书后,客户端会把客户端证书信息以Client Certificate 报文方式发送给服务器。
  3. 服务器验证客户端证书验证通过后方可领取证书内客户端的公开密钥,然后开始 HTTPS 加密通信。

双因素认证

多数情况下,SSL 客户端认证不会仅依靠证书完成认证,一般会和基于表单认证组合成一种双因素认证方式使用。SSL 客户端证书用来认证客户端计算机,密码用来确定用户本人。

4. 基于表单认证

由于使用的便利性和安全性问题,HTTP 协议标准提供的 Basic 认证和 Digest 认证几乎不怎么使用。另外,SSL 客户端认证虽然具有高度的安全等级,但因为导入及维持费用等问题,还尚未普及。所以多数情况下基于表单认证。

Session-Cookie 认证

 流程

  1. 客户端把用户 ID 和密码等登录信息放入报文的实体部分,通常是以 POST 方法把请求发送给服务器。而这时,会使用 HTTPS 通信来进行 HTML 表单画面的显示和用户输入数据的发送。
  2. 服务器会发放用以识别用户的 Session ID。通过验证从客户端发送过来的登录信息进行身份认证,然后把用户的认证状态和 Session ID 绑定后记录在服务器端。向客户端返回响应时,会在首部字段 Set-Cookie 内写入 Session ID。(为减轻跨站脚本攻击造成的损失,建议事先在 Cookie 内加上 httponly 属性。)
  3. 客户端接收到从服务器发来的 Session ID 后,会将其作为 Cookie 保存在本地。下次向服务器发送请求时,浏览器会自动发送 Cookie,所以 Session ID 也随之发送到服务器。服务器可通过验证收到的 Session ID 识别用户和其认证状态。

优点

  1. Cookie 简单易用,在不受用户干预或过期处理的情况下,Cookie 通常是客户端上持续时间最长的数据保留形式
  2. Session 数据存储在服务端,相较于 JWT 方便进行管理,也就是当用户登录和主动注销,只需要添加删除对应的 Session 就可以了,方便管理

缺点

  1. 非常不安全,Cookie 将数据暴露在浏览器中,增加了数据被盗的风险(容易被 CSRF 等攻击)
  2. Session 存储在服务端,增大了服务端的开销,用户量大的时候会大大降低服务器性能
  3. 用户认证后,服务端做认证记录,如果认证的记录被保存在内存中,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权资源,这样在分布式的应用上,相应的限制了负载均衡的能力,也意味着限制了应用的扩展能力

Token 认证

 流程

  1. 用户输入登录信息并请求登录
  2. 服务端收到请求,验证用户输入的登录信息
  3. 验证成功后,服务端会签发一个 Token(通常包含用户基础信息、权限范围和有效时间等),并把这个 Token 返回给客户端
  4. 客户端收到 Token 后需要把它存储起来,比如放在 localStorage 或 sessionStorage 里(一般不放 Cookie 因为可能会有跨域问题,以及安全性问题)
  5. 后续客户端每次向服务端请求资源的时候,将 Token 附带于 HTTP 请求头 Authorization 字段中发送请求
  6. 服务端收到请求后,去校验客户端请求中 Token,如果验证成功,就向客户端返回请求的数据,否则拒绝返还

优点

  1. 服务端无状态:Token 机制在服务端不需要存储会话(Session)信息,因为 Token 自身包含了其所标识用户的相关信息,这有利于在多个服务间共享用户状态
  2. 支持跨域跨程序调用,因为 Cookie 是不允许跨域访问的,而 Token 则不存在这个问题
  3. 有效避免 CSRF 攻击(因为不需要 Cookie),但是会存在 XSS 攻击中被盗的风险,但是可选择 Token 存储在标记为 httpOnly 的 Cookie 中,能够有效避免浏览器中的 JS 脚本对 Cookie 的修改

缺点

  • 正常情况下比 Session ID 更大,消耗更多流量,挤占更多宽带
  • 相比较于 Session-Cookie 认证来说,Token 需要服务端花费更多时间和性能来对 Token 进行解密验证,其实 Token 相较于 Session—Cookie 来说就是一个时间换空间的方案

JWT 认证

JSON Web Token

原理

服务器认证后,生成一个 JSON 对象,返回给用户。

此后,用户与服务端通信的时候,都要返回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。

数据格式

JWT 是 JSON 格式的被加密了的字符串,中间用(.)分隔成三个部分:

  • Header 头部
  • Payload 负载
  • Signature 签名

其中 Header 和 Payload 加密的算法是 Base64URL。

Base64URL 算法跟 Base64 算法基本类似,但有一些小的不同。

JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+/=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-/替换成_。这就是 Base64URL 算法。

Header

Header 部分是一个JSON 对象,描述 JWT 的元数据,通常是下面的样子:

{

  "alg": "HS256",

  "typ": "JWT"

}

其中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT

Payload

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。

  • iss (issuer):签发人

  • exp (expiration time):过期时间

  • sub (subject):主题

  • aud (audience):受众

  • nbf (Not Before):生效时间

  • iat (Issued At):签发时间

  • jti (JWT ID):编号

除了官方字段,还可以在这个部分定义私有字段:

{

  "sub": "1234567890",

  "name": "John Doe",

  "admin": true

}

Signature

Signature 部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

HMACSHA256(base64UrlEncode(Header) + '.' + base64UrlEncode(Payload), secret);

特点

  1. JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

  2. JWT 不加密的情况下,不能将秘密数据写入 JWT。

  3. JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

  4. JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

  5. JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

  6. 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

单点登录

单点登录(Single Sign-on)又称 SSO,是指在多系统应用群中登录单个系统,便可在其他所有系统中得到授权而无需再次登录。

同域 SSO

当存在两个相同域名下的系统 A a.abc.com 和系统 B b.abc.com 时,以下为他们实现 SSO 的步骤:

  1. 用户访问某个子系统时(例如 a.abc.com),如果没有登录,则跳转至 SSO 认证中心提供的登录页面进行登录
  2. 登录认证后,服务端把登录用户的信息存储于 Session 中,并为用户生成对应的会话身份凭证附加在响应头的 Set-Cookie 字段中,随着请求返回写入浏览器中,并回跳到设定的子系统链接中
  3. 下次发送请求时,当用户访问同域名的系统 B 时,由于 A 和 B 在相同域名下,也是 abc.com,浏览器会自动带上之前的 Cookie。此时服务端就可以通过该 Cookie 来验证登录状态了。

这实际上使用的就是 Session-Cookie 认证的登录方式。

跨域 SSO

目前大多数企业的系统都是部署在不同域名下的,显然同域 SSO 并不能满足。

单点登录的标准流程要使用到 CAS。

CAS(Central Authentication Service)中央授权服务,本身是一个开源协议,分为 1.0 版本和 2.0 版本。1.0 称为基础模式,2.0 称为代理模式,适用于存在非 Web 应用之间的单点登录。

CAS 重要概念:

  • Server:CAS 服务器,即 SSO 服务器。
  • Service:Web 应用服务器。
  • TGT(Ticket Grangting Ticket:TGT 是 CAS 为用户签发的 登录票据,拥有了 TGT,用户就可以证明自己在 CAS 成功登录过。TGT 封装了 Cookie 值以及此 Cookie 值对应的用户信息。当 HTTP 请求到来时,CAS 以此 Cookie 值(TGC)为 key 查询缓存中是否有 TGT,如果有,则表示用户已登录过。
  • TGC(Ticket Granting Cookie):CAS Service 生成 TGC 放入自己的 Session 中,而 TGC 就是这个 Session 的唯一标识(SessionID),以 Cookie 形式放到浏览器端,是 CAS Service 用来明确用户身份的凭证。TGC 和 TGT 的关系相当于 key: value => TGC => TGT。
  • ST(Service Ticket:ST 是 CAS 为用户签发的访问某个 Service 的票据。用户访问 Service 时,Service 发现用户没有 ST,则要求用户去 CAS 获取 ST。用户向 CAS 发出 ST 的请求,CAS 发现用户有 TGT,则签发一个 ST,返回给用户。用户拿着 ST 去访问 Service,Service 拿 ST 去 CAS 验证,验证通过后,允许用户访问资源。

CAS 流程

详细流程:

  1. 用户访问 app1 系统,app1 系统是需要登录的,但用户现在没有登录,app1 的 service 会返回 302 重定向到 CAS 服务器。
  2. 跳转到 CAS server,即 SSO 登录系统,由于请求没有携带 TGC,所以 SSO 系统也判定为没有登录,弹出用户登录页。
  3. 用户填写用户名、密码,SSO 系统进行认证后,将登录状态写入 SSO 的 session,创建全局会话,产生了 TGC:TGT 键值对,同时生成一个 ST。
  4. SSO 将 TGC 放在 Set-Cookie 中,将 ST 携带在 URL query 中,然后浏览器跳转到 app1 系统,同时将 ST 作为参数传递给 app1 系统。
  5. app1 系统拿到 ST 后,从后台向 SSO 发送请求,验证 ST 是否有效。
  6. 验证通过后,app1 系统将登录状态写入 session 并设置 app1 域下的 Cookie。

至此,跨域单点登录就完成了。以后我们再访问 app1 系统时,会携带 app1 的登录态 Cookie,app1 就是登录的。接下来,如果访问 app2 系统时,流程如下:

  1. 用户访问 app2 系统,app2 系统没有登录,跳转到 SSO。
  2. 由于请求中携带了 TGC,SSO 判定为已经登录了,不需要重新登录认证。
  3. SSO 生成新的 ST,浏览器跳转到 app2 系统,并将 ST 作为参数传递给 app2。
  4. app2 拿到 ST,后台访问 SSO,验证 ST 是否有效。
  5. 验证成功后,app2 将登录状态写入 session,并在 app2 域下写入 Cookie。

这样,app2 系统不需要走登录流程,就已经是登录了。SSO,app1 和 app2 在不同的域,它们之间的session 不共享也是没问题的。 

参考资料

https://juejin.cn/post/6844903586405564430
https://zh.wikipedia.org/wiki/HTTP%E6%91%98%E8%A6%81%E8%AE%A4%E8%AF%81
https://www.cnblogs.com/xiongmaomengnan/p/6671206.html
https://tsejx.github.io/blog/authentication/
https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
https://developer.aliyun.com/article/636281
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用户身份认证 的相关文章

  • HTTP请求/响应报文结构

    HTTP请求 响应报文结构 HTTP请求报文 一个HTTP请求报文由四个部分组成 xff1a 请求行 请求头部 空行 请求数据 1 请求行 请求行由请求方法字段 URL字段和HTTP协议版本字段3个字段组成 xff0c 它们用空格分隔 比如
  • C语言练习笔记 ~结构体2 ~ 结构体在内存中的对齐说明

    文章目录 1 结构体变量在内存中的对齐说明例1 1个char型变量例2 2个char型变量例3 1个int型变量例4 1个char型变量和1个int型变量例5 3个char型变量和1个int型变量例6 5个char型变量和1个int型变量例
  • 思岚激光雷达+cartographer建图

    系统环境 xff1a Ubuntu18 04 ROS Melodic gcc 7 5 0 1 安装思岚ROS包 1 1 clone并编译 cd catkin ws src git clone https github com Slamtec
  • 使用PyTorch+functorch计算并可视化NTK矩阵

    2022年3月 xff0c PyTorch发布了PyTorch1 11和functorch functorch灵感来自于Google JAX xff0c 旨在提供vmap和autodiff转换配合PyTorch使用 本文将演示如何使用PyT
  • libcurl异步请求+http长连接池

    由于公司项目 xff0c 需要localhost的形式高并发的http访问本机服务 xff0c 所以面临了两方面的问题 xff1a 1 http短连接会造成大量的time wait xff0c 影响服务器的性能 2 libcurl easy
  • VC实现http发送get和post请求

    VC实现http发送get和post请求 get请求 首先通过前面介绍的抓包工具获取请求的详细内容 xff0c 然后再通过VC拼接Header xff0c 函数如下 xff1a bool CXXX http get eng mode lt
  • 链表(图文详解)

    链表的概念 链表是一种物理存储结构上非连续 xff0c 非顺序的存储结构 xff0c 数据元素的逻辑顺序是通过链表中的指针链接次序实现的 链表的结构是多式多样的 xff0c 当时通常用的也就是两种 xff1a 无头单向非循环列表 xff1a
  • PCB上能上锡的那层叫什么?

  • C++常用数学函数

    C 43 43 中有个头文件math h xff0c 它是数学函数库 一些数学计算的公式的具体实现是放在math h里 xff0c 为了方便大家使用 xff0c 特在此总结常用的一些函数 1 三角函数 double sin double d
  • LimeSDR实验教程(6) 发射GPS

    下载程序 xff1a git clone https github com osqzss gps sdr sim git 编译安装 xff1a cd gps sdr sim gcc gpssim c lm O3 o gps sdr sim
  • 如何理解引用作为函数的返回值?

    如何理解引用作为函数的返回值 xff1f 1 引用作为函数的返回值时 xff0c 必须在定义函数时在函数名前将 amp 2 用引用作函数的返回值的最大的好处是在内存中不产生返回值的副本 span class token comment 代码
  • 自制合成孔径雷达(2) SDR实现的对比(SDR实现测速雷达)

    我今天查了查资料 xff1a 技术干货 xff1a 用LimeSDR Mini制作一台软件定义多普勒雷达 搜狐汽车 搜狐网 查阅一些文献后 xff0c 笔者想探寻减少雷达系统所需的昂贵模拟前端部件数量的可能性 设计灵感来自于Gregory
  • 自制合成孔径雷达(3) doppler代码解读

    上一篇帖子 xff0c 看完了基于SDR的多普勒雷达 xff0c 就可以看看硬件雷达的多普勒测速的DSP代码了 先看一下这个图 xff1a 我们需要的多普勒频移的测量结果是从混频器 xff08 Multiply Conjugate xff0
  • 各类SDR的USB接口一致性测试

    最近用高带宽示波器测了好几个SDR产品的USB2接口一致性 由于探头数量只有1个 xff0c 所以不能测全所有的项目 但已经包含了最主要的USB眼图 xff08 信号质量 xff09 项目 测试场景 xff1a 待测件包含 xff1a 1
  • Portapack应用开发教程(十八)NavTex接收 D

    上回说到 xff0c 我现在已经做到用自己的gnuradio流图从音频信号做fsk解调 xff0c 得到方波 然后用c程序把方波转为二进制数 又用python把二进制数转为最终的字母 但是遗留问题是python解码 xff0c 起始位如果错
  • Portapack应用开发教程(十八)NavTex接收 E

    我现在已经成功把两部分解码的代码合并到一起 实现的功能是从stdout取出方波的采样点幅度 xff0c 然后把它转为解码输出 include lt stdio h gt include lt string gt include lt mat
  • 使用RTL-SDR和Matlab Simulink玩转软件无线电(二十一)

    3 13 扫描频谱 xff1a 把 25MHz 到 1 75GHz 的信号都收下来 这一节我们会做本章最后一个练习 xff0c 使用一个 RTL SDR 扫描整个频率范围内的信号 对于大多数 RTL SDR 设备来说 xff08 R820T
  • SDR# (SDRSharp)代码讲解 (一)

    SDR 也称SDRSharp 与Linux平台下常用的GQRX类似 xff0c 是目前Windows平台上最常用的频谱观察 xff0c 音频解调软件 xff0c 支持AM FM SSB等多种调制方式 以SDRSharp为基础又派生出了其它一
  • 自动跟随机器人教程(一)(树莓派、Arduino教程)

    机器人购买链接 xff1a https item taobao com item htm spm 61 a1z38n 10677092 0 0 59a21debCqLXYP amp id 61 532012951368 接下来打算发布一款自
  • 自动跟随机器人教程(二)硬件组装

    本机器人结构应该说比较简单 xff0c 除了上述图片里的4样东西外 xff0c 就是一个USB摄像头和一块航模专用12V锂电池 xff08 与电机电压一致 xff09 xff0c 一共6样东西 所有这些东西都不需要螺丝固定 xff0c 多数

随机推荐

  • LimeSDR 中文教程 (一)

    行业应用及合作请联系 j shao 64 limemicro com xff08 本文所有图片请参考Myriadrf官网原文 xff1a https myriadrf org blog limesdr made simple part 1
  • Linux系统——fork()函数详解(看这一篇就够了!!!)

    fork 函数详解 包看包会 xff01 xff01 xff01 1 fork 简介 函数原型 xff1a pid t fork void xff1b pid t为int类型 xff0c 进行了重载pid t getpid 获取当前进程的
  • HttpURLConnection详解、JSON的使用

    1 Http网络请求方法 Http的请求方法代表了客户端想对服务器进行的操作 xff0c 比如 xff1a POST GET HEAD PUT DELETE TRACE OPTIONS 常用的不过于CRUD四个 增 xff1a PUT 删
  • printf二进制输出

    include lt stdio h gt include lt conio h gt include lt stdlib h gt void main int i 61 31 char s 10 itoa i s 2 转换成字符串 xff
  • 秒懂HTTP之基本认证(Basic Authentication)

    版权申明 非商业目的注明出处可自由转载 博文地址 xff1a https blog csdn net ShuSheng0007 article details 89598299 出自 xff1a shusheng007 系列文章 xff1a
  • Linux内核学习(一)8086编程模型

    本文主要介绍Intel8086系列的编程模型 xff0c 包括分段与分页机制 任务切换过程以及中断处理系统 作为Linux内核学习曲线的起点 xff0c 本文的侧重点在于对于每个主题 xff0c 硬件上是如何实现的 xff0c 以及为软件
  • Ubuntu网络编程——TCP/IP

    常识 xff1a 裸机 xff1a 没有安装操作系统的计算机 如果想在裸机上运行自己所编写的程序 xff0c 就必须用机器语言写程序 桌面操作系统 xff1a windows macOS Linux 服务器操作系统 xff1a Linux
  • RoboMaster电控学习笔记——电机控制(1-CAN)

    Robomaster官方提供了一系列性能强大的直流无刷减速电机及配套电调 xff0c 这里介绍三款步兵上用的电机 amp 电调 M3508电机 amp C620电调 xff0c GM6020电机 xff08 内部集成电调 xff09 xff
  • linux下 在同一个线程建立TCP连接

    要实现在一个线程里建立TCP连接 xff0c 需要注意accept应在connect之后 xff0c 所以我将accept放在了tcp client里 这样 xff0c 才能得到accept返回的fd xff0c 从而进行read span
  • 【cpprestsdk】浅谈cpprestsdk线程池及使用

    cpprestsdk根据include文件夹可以看到共包含两部分内容 xff1a 1 pplx 2 cpprest pplx threadpool h源代码中创建线程池有两种方式 1 通过construct接口创建 xff0c 返回一个un
  • 丹尼带你入坑无人机3 - 四轴配件简介

    知道你的四轴里面每个小东东都是干嘛用的吗 xff1f 麻雀虽小 xff0c 五脏得全 简单说 xff0c 飞控就是大脑 xff0c 它能知道每一时刻无人机的状态 xff0c 并且给下一时刻需要作出的动作发出指令 电调就好比是神经单元 xff
  • Linux内核简单分析(2)——进程调度与切换

    进程的调度与切换是一个很复杂的话题 xff0c 这里我更关心内核是如何实现的 xff0c 而不是使用了什么策略 xff0c 所以只讲进程的组织和切换方式 xff0c 而对调度程序的实现和算法不作分析 进程调度可参考 xff1a Linux进
  • 【矩阵路径】不知道回溯怎么写?进来看模板就对了!

    矩阵路径 不知道回溯怎么写 xff1f 进来看模板就对了 xff01 这几天做了几道回溯算法的题目 xff0c 发现理解递归关键步骤的结果很重要 xff0c 试图摸索出一套模板 xff0c 思考的方法都是搭建好框架 xff0c 然后逐步细想
  • gloox 获取花名册和联系人出席信息

    gloox 之 RosterManager 此类实现了jabber iq roster名空间中的Jabber XMPP花名册操作 它继承了 IqHandler PresenceHandler SubscriptionHandler 和 Pr
  • TCP/IP网络编程笔记--套接字和标准I/O

    一 定义 xff1a 标准I O是标准C库提供的对文件操作的函数接口 二 常见的标准I O函数 xff1a 1 fopen xff08 xff09 函数原型 xff1a FILE fopen xff08 const char path xf
  • C语言位运算符:与、或、异或、取反、左移和右移

    文章转载于 博客园 博主 夜真寒 链接地址 xff1a http www cnblogs com yezhenhan archive 2011 11 06 2238452 html 语言位运算符 xff1a 与 或 异或 取反 左移和右移
  • Linux系统之常用命令

    这几天在看教学视频 xff0c 里面在讲一些linux系统常用的命令 xff0c 虽然有一部分都很熟悉了 xff0c 但也有一些不太熟悉 xff0c 因此来总结一下 注 xff1a 本文并非介绍了linux下所有常用的命令 xff0c 而是
  • C++学习笔记--尽量以const,enum,inline替换#define

    本文内容整理自 Effective C 43 43 中文版 xff0c 主要讲述 C 43 43 中在一些场合使用 const enum inline 来替换 define 所带来的好处 1 const 当我们编写这样一条代码 xff1a
  • ROS分布式通信(可以查看话题但主机接受不到从机传输的消息)

    提示 xff1a 想要将nano上的传感器数据发回pc端从机进行计算 xff0c 但是pc端计算完后发布话题 xff0c nano上的主机可以查看到这个话题但却收不到消息 xff08 已经在主机配置好相应的消息类型 xff09 前言 提示
  • 用户身份认证

    0 背景 计算机本身无法判断坐在显示器前的使用者的身份 xff0c 也无法确认网络的另一端的是谁 为了明确是谁在访问服务器 xff0c 必须让客户端自报家门 通常核对一些登录者本人的信息 xff1a 密码 xff1a 只有本人知道的字符串信