全面介绍SSO(单点登录)

全面介绍SSO(单点登录)

SSO英文全称Single SignOn,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。它是目前比较流行的企业业务整合的解决方案之一。

一、 实现机制

当用户第一次访问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录;根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返回给用户一个认证的凭据--ticket;用户再访问别的应用的时候就会将这个ticket带上,作为自己认证的凭据,应用系统接受到请求之后会把ticket送到认证系统进行校验,检查ticket的合法性。如果通过校验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了。

二、使用SSO的好处

  • 方便用户 用户使用应用系统时,能够一次登录,多次使用。用户不再需要每次输入用户名称和用户密码,也不需要牢记多套用户名称和用户密码。单点登录平台能够改善用户使用应用系统的体验。
  • 方便管理员 系统管理员只需要维护一套统一的用户账号,方便、简单。相比之下,系统管理员以前需要管理很多套的用户账号。每一个应用系统就有一套用户账号,不仅给管理上带来不方便,而且,也容易出现管理漏洞。
  • 简化应用系统开发 开发新的应用系统时,可以直接使用单点登录平台的用户认证服务,简化开发流程。单点登录平台通过提供统一的认证平台,实现单点登录。因此,应用系统并不需要开发用户认证程序。

三、SSO实现方案

常见的跨域登录问题

1、对于同一个根域下的登录问题

如果我们的站点有不止一个业务,那么他们可能部署在不同的机器上,也往往需要不同的域名进行区分。但是所有的业务又都是依赖于一套账户体系,那么我们这时候需要通过一次登录解决所有站点的登录问题,那么我们这个时候可以使用一个最笨的方法:那就是一次登录成功,将Cookie写到根域下,那么这样所有的站点就能实现,同一个根域下的Cookie共享,自然实现了“单点登录”。

2、对于多个根域下的登录问题

如果是多个根域名,那么这种情况下上面的机制就不能实现“单点登录”了。因为之所以上面可以实现“单点登录”的效果。是因为浏览器和Http协议的支持。但是对于跨根域的站点之间进行Cookie的共享是比较复杂的。

  • 方法1:登录成功之后将Cookie回写到多个域名下。

这种办法可能十分简单,你可以通过后端的response写,也可以用前端js去写,但是必须有对所有需要“单点登录”的站点进行逐一的写入。用脚想这种办法也是行不通的,因为你需要维护一个站点的列表,维护工作十分复杂,同时对于增加站点也会特别痛苦。对于Cookie的销毁也是十分复杂的,因为还是要对所有域名下的Cookie进行删除。也就是说将原来需要做的工作增加了n倍。对于小型站点这种办法是可取的。

  • 方法2:jsonp

搞过前端的可能都知道用jsonp可以做跨域的请求,而我们解决的就是多个域下的统一登录的问题,好像很顺理成章的样子。但是,登录是Server端做的吧?我们在Client端做跨域的处理,这怎么看也不是很合理。同时这种办法需要很大的维护成本,每一次请求都要去固定的域下取相应的Cookie之后再做请求。想想维护有头疼。

  • 方法3 :引入一个中间态的Server

这种办法算是一个简化版的SSO,实现思想也十分的“狡猾”。但是对于小网站做跨域登录的处理却十分的有用,具体思路如下:

首先,我们有两个域名要实现单点登录,同时我们需要一个中间的Server。

  1. 我们有一个系统域名为xulingbo.net,当我们登录的时候访问xulingbo.net/wp-login进行登录,登录成功之后将Cookie回写到xulingbo这个域名下。
  2. 我们还有一个系统域名为javaWeb.com,当我们访问inside-javaWeb的时候,我们没有Cookie,那么请求跳转到中间系统jump。此时需要将当前域名带到参数中便于jump校验。这个jump系统是在xulingbo域下的即:jump.xulingbo.net。这时候就能拿到之前写在xulingbo域下的Cookie。
  3. jump系统在收到了xulingbo域下的Cookie之后,取出xulingbo域下的Cookie,并redirect请求jump.inside-javaWeb.net,这个接口也是在jump系统中,请求后jump系统将Cookie回写到inside-javaWeb域名下,这样就实现了简易的单点登录。 如下图所示:

412b61e65710c49baac98e523320a5a.png

但是这种方式不是很灵活,对于数据传输的安全性没有保障,并且在销毁Cookie的时候无能为力,只能全部遍历的销毁。

  • 方法4:基于CAS的SSO系统

CAS全称为:Central Authentication Service,是一款不错的针对web应用的单点登录框架,包括java,.net,PHP,Prel,Apache,uPortal,Ruby等。。实现的机制不算复杂但是思想十分灵巧。用CAS也可以快速实现单点登录。盗图一张说明sso单个域的登录和验证流程:

6f754e860e7e983d51d5a4e4f8c1454.png

CAS主要分为CAS Client 和CAS Server ,其中Client主要是内嵌在需要SSO登录站点的拦截器或过滤器上。

  1. 首先浏览器向站点1发起请求。
  2. 站点1发现当前请求没有合法的Cookie,那么重定向到CAS Server上,也就是SSO Server。
  3. CAS Server展示登录界面,要求用户登录。
  4. 用户登录后,会写CAS Server的Cookie到浏览器,同时生产ticket,利用一个302跳转到CASClient。这样能保证用户无感知。
  5. CAS Client利用生成的ticket发送到CAS Server进行验证,验证通过后,站点1生成自己的Cookie并回写到用户浏览器,然后进行登录成功的跳转。

这样就能保证当前浏览器在站点1的域名下,有站点1的Cookie,同时当前浏览器也有CAS Server的Cookie。 接下来看下站点2的登录:

8a4b2a2c9291be766d5efca2be43115.png

站点2,在进行登录时和站点1初次登录流程一致,但是在访问CAS Server的时候,由于当前浏览器已经有了CAS Server的Cookie,那么直接校验通过返回ticket。 ticket通过302跳转跳转到CAS Client上,之后的流程就和站点1是一样的了。如果此时认证失败,那么需要重新走一次登录的过程。

注意的问题: 1、CAS Server的Cookie劫持问题,如果CAS Server的Cookie被劫持掉,那么就相当于拿到了一切,所以必须要用HTTPS实现这个过程。 2、ticket的使用,ticket只能被使用一次,一次校验后立即失效。同时需要有时效性,一般5分钟。最后ticket生成规则要随机,不能被碰撞出来。 3、对于各自系统自己的Session,也可以依赖于SSO,这样就能保证所有的Session规则一致,便于集中控制。

注:运营系统也是采用这种方式处理的 基于当前现状,单点登录系统可以有一下处理

  • 调用Soa服务实现登录登出 缺点:得自己实现判断用户是否登录、session是否过期;缺乏权限控制,得自己实现 优点:实现简单
  • 自己在web服务实现登录登录功能 安全性偏低
  • 使用Spring Security + Oauth2实现登录登录功能 优点:企业级,安全性高 提供了多种安全验证方式 可以处理复杂的权限控制

四、Spring Security 介绍

  • Spring Security是什么?

Spring security 是一个强大的和高度可定制的身份验证和访问控制框架,它提供了基于javaEE的企业应有个你软件全面的安全服务。它是保护基于Spring的应用程序的事实上的标准。主要作用是“认证”和“授权”(或者访问控制)。 在身份验证层,Spring Security 的支持多种认证模式。

  • 核心功能 1、认证(你是谁) 2、授权(你能干什么) 3、攻击防护(防止伪造身份)
  • 什么是Spring Security验证?
  1. 提示用户输入用户名和密码进行登录。
  2. 该系统 (成功) 验证该用户名的密码正确。
  3. 获取该用户的环境信息 (他们的角色列表等).
  4. 为用户建立安全的环境。
  5. 用户进行,可能执行一些操作,这是潜在的保护的访问控制机制,检查所需权限,对当前的安全的环境信息的操作。

验证流程介绍

  1. 用户名和密码进行组合成一个实例UsernamePasswordAuthenticationToken (一个Authentication接口的实例, 我们之前看到的).
  2. 令牌传递到AuthenticationManager实例进行验证。
  3. 该AuthenticationManager完全填充Authentication实例返回成功验证。
  4. 安全环境是通过调用 SecurityContextHolder.getContext().setAuthentication(…), 传递到返回的验证对象建立的。

五、OAUTH2

  • 名词定义
  1. Third-party application:第三方应用程序,本文中又称"客户端"(client)
  2. HTTP service:HTTP服务提供商,本文中简称"服务提供商"
  3. Resource Owner:资源所有者,本文中又称"用户"(user)。
  4. User Agent:用户代理,通常就是指浏览器。
  5. Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。
  6. Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。
  • OAuth的思路

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。“客户端"不能直接登录"服务提供商”,只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。 "客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。

  • 运行流程

(A)用户打开客户端以后,客户端要求用户给予授权。 (B)用户同意给予客户端授权。 (C)客户端使用上一步获得的授权,向认证服务器申请令牌。 (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。 (E)客户端使用令牌,向资源服务器申请获取资源。 (F)资源服务器确认令牌无误,同意向客户端开放资源。 不难看出来,上面六个步骤之中,B是关键,即用户怎样才能给于客户端授权。有了这个授权以后,客户端就可以获取令牌,进而凭令牌获取资源。

结合上图,使用oauth2保护你的应用,可以分为简易的分为三个步骤

  1. 配置资源服务器 Authorization Service.
  2. 配置认证服务器 Resource Service.
  3. 配置spring security

所有获取令牌的请求都将会在Spring MVC controller endpoints中进行处理,并且访问受保护 的资源服务的处理流程将会放在标准的Spring Security请求过滤器中(filters)。 下面是配置一个授权服务必须要实现的endpoints: -AuthorizationEndpoint:用来作为请求者获得授权的服务,默认的URL是/oauth/authorize. -TokenEndpoint:用来作为请求者获得令牌(Token)的服务,默认的URL是/oauth/token.

  • 客户端的授权模式

客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。

  1. 授权码模式(authorization code)
  2. 简化模式(implicit)
  3. 密码模式(resource owner password credentials)
  4. 客户端模式(client credentials)

授权模式讲解

  • 授权码模式

授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。

它的步骤如下:

(A)用户访问客户端,后者将前者导向认证服务器。

(B)用户选择是否给予客户端授权。

(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。

(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。

(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

下面是上面这些步骤所需要的参数。 A步骤中,客户端申请认证的URI,包含以下参数:

  • –response_type:表示授权类型,必选项,此处的值固定为"code"
  • –client_id:表示客户端的ID,必选项
  • –redirect_uri:表示重定向URI,可选项
  • –scope:表示申请的权限范围,可选项
  • –state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
demo:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com
复制代码

C步骤中,服务器回应客户端的URI,包含以下参数: --code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。 --state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
复制代码

D步骤中,客户端向认证服务器申请令牌的HTTP请求,包含以下参数:

  • –grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
  • –code:表示上一步获得的授权码,必选项。
  • –redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
  • –client_id:表示客户端ID,必选项。

E步骤中,认证服务器发送的HTTP回复,包含以下参数:

  • –access_token:表示访问令牌,必选项。
  • –token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
  • –expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  • –refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
  • –scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。

常见的第三方登录也是采用这种方法,先请求得到code,然后再通过code去获取令牌。

  • 简化模式 简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

它的步骤如下: (A)客户端将用户导向认证服务器。

(B)用户决定是否给于客户端授权。

(C)假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。

(D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。

(E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。

(F)浏览器执行上一步获得的脚本,提取出令牌。

(G)浏览器将令牌发给客户端。

下面是上面这些步骤所需要的参数。

A步骤中,客户端发出的HTTP请求,包含以下参数:

  • -response_type:表示授权类型,此处的值固定为"token",必选项。
  • -client_id:表示客户端的ID,必选项。
  • -redirect_uri:表示重定向的URI,可选项。
  • -scope:表示权限范围,可选项。
  • -state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

下面是一个例子:

GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1Host: server.example.com
复制代码

C步骤中,认证服务器回应客户端的URI,包含以下参数:

  • -access_token:表示访问令牌,必选项。
  • -token_type:表示令牌类型,该值大小写不敏感,必选项。
  • -expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  • -scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
  • -state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

下面是一个例子:

HTTP/1.1 302 FoundLocation: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600
复制代码
  • 密码模式

密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。 在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

它的步骤如下:

(A)用户向客户端提供用户名和密码。

(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。

(C)认证服务器确认无误后,向客户端提供访问令牌。

B步骤中,客户端发出的HTTP请求,包含以下参数:

-grant_type:表示授权类型,此处的值固定为"password",必选项。

-username:表示用户名,必选项。

-password:表示用户的密码,必选项。

-scope:表示权限范围,可选项。

下面是一个例子:

POST /token HTTP/1.1Host: server.example.comAuthorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JWContent-Type: application/x-www-form-urlencodedgrant_type=password&username=johndoe&password=A3ddj3w
复制代码

C步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。

HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8Cache-Control: no-storePragma: no-cache{"access_token":"2YotnFZFEjr1zCsicMWpAA","token_type":"example","expires_in":3600,"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA","example_parameter":"example_value"}
复制代码

其它的认证介绍参考下面参考地址。

  • 客户端模式 客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

它的步骤如下:

(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。

(B)认证服务器确认无误后,向客户端提供访问令牌。

A步骤中,客户端发出的HTTP请求,包含以下参数:

-granttype:表示授权类型,此处的值固定为"clientcredentials",必选项。

-scope:表示权限范围,可选项。

POST /token HTTP/1.1Host: server.example.comAuthorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JWContent-Type: application/x-www-form-urlencodedgrant_type=client_credentials
复制代码

认证服务器必须以某种方式,验证客户端身份。 B步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。

HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8Cache-Control: no-storePragma: no-cache{"access_token":"2YotnFZFEjr1zCsicMWpAA","token_type":"example","expires_in":3600,"example_parameter":"example_value"}
复制代码

附上我自己写的一个spring-security+oauth2项目,可参考使用,反正我自己的项目用上这个了。github.com/jiezaizone/…

另一种单点登录方式:Keycloak单点登录

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

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

相关文章

亮相史上规模最大高交会,Coremail展现邮件技术创新实力

11月19日,第二十五届中国国际高新技术成果交易会在深圳落下帷幕,作为国内邮件行业引领者,Coremail受邀参展。 展览现场,Coremail邮件解决方案及系列产品受到了众多参观者与业内人士的关注与好评。Coremail XT6邮件系统技术成熟&a…

【JavaEE初阶】——Linux 基本使用和 web 程序部署(下)

文章目录 前言一、Linux 常用命令 1.1 ls 命令 1.2 pwd 命令 1.3 cd 命令 1.4 touch 命令 1.5 cat 命令 1.6 mkdir 命令 1.7 rm 命令 1.8 cp 命令 1.9 mv 命令 1.10 man 命令 1.11 less 命令 1.12 head 命令 1.13 tail 命…

玻色量子事件活动

2023年 2023.7 玻色量子携最新相干光量子计算机惊艳亮相2023数字经济大会 2023.6 打造“新型计算数据中心”!玻色量子与科华数据(002335.SZ)携手共创 2023.6 玻色量子“天工量子大脑”亮相中关村论坛,大放异彩 2023.5 100量…

基于mvc的大学生家教信息网站系统php+vue

运行环境:phpstudy/wamp/xammp等 开发语言:php 后端框架:Thinkphp5 前端框架:vue.js 服务器:apache 数据库:mysql 数据库工具:Navicat/phpmyadmin 开发软件:hbuilderx/vscode/Dreamweaver/PhpSt…

029 - STM32学习笔记 - ADC(三) 独立模式单通道DMA采集

029 - STM32学习笔记 - 单通道DMA采集(三) 单通道ADC采集在上节中学习完了,这节在上节的内容基础上,学习单通道DMA采集。程序代码以上节的为基础,需要删除NVIC配置函数、中段服务子程序、R_ADC_Mode_Config()函数中使能…

华为鸿蒙开发(HarmonyOs开发):超详细的:DevEco Studio 的安装和配置 、华为第三方包依赖:SDK软件包的安装、Nodejs的导入配置

2023年11月28日20:00:00 ⚠️⚠️HarmonyOs 开发工具 ⚠️⚠️ ⚠️⚠️DevEco Studio 的安装和配置⚠️⚠️ 文章目录 一、打开鸿蒙开发工具官网二、下载 DevEco Studio三、配置 DevEco Studio四、错误处理 ⚠️⚠️⚠️❤️❤️ 关注了解更多 一、打开鸿蒙开发工具官网 下面…

泛微E-Office SQL注入漏洞复现

0x01 产品简介 泛微E-Office是一款标准化的协同 OA 办公软件,泛微协同办公产品系列成员之一,实行通用化产品设计,充分贴合企业管理需求,本着简洁易用、高效智能的原则,为企业快速打造移动化、无纸化、数字化的办公平台。 0x02 漏…

【Python小游戏】推荐8款自由的Python游戏项目

推荐8款自由的Python游戏项目 今天给大家推荐8款不错的Python小游戏,这些小游戏所有项目文件(包括所需的所有代码、图像和音频文件),给大家已经放到平台的下载频道,需要的可以注意一下文末的链接地址。 下面给大家简单…

智能优化算法应用:基于蝙蝠算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于蝙蝠算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于蝙蝠算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝙蝠算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

ELk部署,保姆级教学超详细!!!

Elk(Elasticsearch, Logstash, Kibana)是一套日志收集、存储和展示方案,是由Elastic公司开发的开源软件组合。 Elasticsearch:是一个分布式的搜索和分析引擎。它能够处理大量的数据,并提供快速、准确的搜索结果&#x…

63 权限提升-Linux脏牛内核漏洞SUID信息收集

目录 演示案例:Linux提权自动化脚本利用-4个脚本Linux提权SUID配合脚本演示-AliyunLinux提权本地配合内核漏洞演示-MozheLinux提权脏牛内核漏洞演示-Aliyun,Vulnhub涉及资源: linux提权相对windows提权方法相对少一些,linux提权方法相对来讲有七八种方式…

stm32 TIM

一、TIM简介 TIM(Timer)定时器定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时定时器不仅具备基本的定时中断功能&…

FFmpeg介绍

官方网站:http://www.ffmpeg.org/ 项目组成 libavformat 封装模块,封装了Protocol层和Demuxer、Muxer层,使得协议和格式对于开发者来说是透明的。FFmpeg能否支持一种封装格式的视频的封装与解封装,完全取决于这个库&#xff0c…

QT中的 容器(container)-大全

一、介绍 Qt库提供了一套通用的基于模板的容器类&#xff0c;可以用这些类存储指定类型的项。比如&#xff0c;你需要一个大小可变的QString的数组&#xff0c;则使用QVector<QString>。 这些容器类比STL&#xff08;C标准模板库&#xff09;容器设计得更轻量、更安全并…

光伏电站开发流程

随着人们对可再生能源的关注度不断提高&#xff0c;光伏电站的开发流程也变得越来越重要。光伏电站是一种利用太阳能发电的设施&#xff0c;它可以有效地减少化石能源的消耗&#xff0c;同时也可以为环保事业做出贡献。 首先&#xff0c;要进行光伏电站的开发&#xff0c;需要选…

PWM 正玄波形 通过C语言生成

#include <stdio.h> #include <math.h> #include <stdint.h>#define SAMPLE_POINT_NUM (200) /* 需要生成的点的个数 */ #define SINE_MAX (255) /* sin 函数幅值 */ #define PI (3.14…

pytorch训练模型内存溢出

1、训练模型命令命令 如下所示是训练命名实体识别的命令&#xff0c;在win10系统下执行 activate pytorch cd F:\Python\github\ultralytics-main\submain\pytorch_bert_bilstm_crf_ner-main f: python main.py --bert_dir"../model_hub/chinese-bert-wwm-ext/" --…

TIME_WAIT状态TCP连接导致套接字无法重用实验

理论相关知识可以看一下《TIME_WAIT相关知识》。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h> #include<errno.h> #include<syslog.h> #inc…

Echarts legend图例配置项 设置位置 显示隐藏

Echarts 官网完整配置项 https://echarts.apache.org/zh/option.html#legend 配置项 legend: { }设置图例为圆形 icon: circle,//设置图例为圆形设置图例位置 top: 20%//距离顶部百分之20//y:bottom 在底部显示设置图例 宽度 高度 itemWidth: 10,//设置图例宽度 itemHeight: …

每日一练【移动零】

一、题目描述 283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 二、题目解析 可以…