Spring Security OAuth2.0 实现分布式系统的认证和授权

Spring Security OAuth2.0 实现分布式系统的认证和授权

  • 1. 基本概念
    • 1.1 什么是认证?
    • 1.2 什么是会话?
      • 1.2.1 基于 session 的认证方式
      • 1.2.2 基于 token 的认证方式
    • 1.3 什么是授权?
      • 1.3.1 授权的数据模型
    • 1.4 RBAC 介绍
  • 2. Spring Security
    • 2.1 Spring Security 介绍
    • 2.2 Spring Security 工作原理
      • 2.2.1 结构总览
      • 2.2.2 认证的流程
        • 2.2.2.1 认证流程
        • 2.2.2.2 AuthenticationProvider 介绍
        • 2.2.2.3 UserDetailsService 介绍
        • 2.2.2.4 PasswordEncoder 介绍
      • 2.2.3 授权流程
        • 2.2.3.1 授权流程
        • 2.2.3.2 授权决策
      • 2.2.4 会话
      • 2.2.5 授权
        • 2.2.5.1 web授权
        • 2.2.5.1 方法授权
  • 3.分布式系统认证方案
    • 3.1 什么是分布式系统
    • 3.2 分布式认证需求
    • 3.3 分布式认证方案
      • 3.3.1 选型分析
      • 3.3.2 技术方案
  • 4. OAuth 2.0
    • 4.1 OAuth2.0 介绍
    • 4.2 Spring Cloud Security OAuth 2.0
    • 4.2.1 环境介绍
  • 5.Spring Security OAuth2.0 实现分布式系统认证和授权示例源码
  • 参考文献

1. 基本概念

1.1 什么是认证?

为什么要认证

认证是为了保护系统的隐私数据和资源。

什么是认证

判断用户的身份是否合法的过程。

常见的认证方式有哪些

  • 用户名密码登录
  • 二维码登录
  • 手机短信登录
  • 指纹认证

1.2 什么是会话?

什么是会话

会话就是系统为了保持当前用户的登录状态所提供的机制。

常见的会话机制

  • 基于 session 的方式
  • 基于 token 的方式

两种实现方式的对比

基于 session 的认证方式由 Servlet 规范定制,服务器要存储 session 信息要占用内存资源,客户端需要支持 cookie;
基于 token 的认证方式则一般不需要服务器存储 token,并且不限制客户端的存储方式。

如今移动互联网时代更多类型的客户端需要接入系统,系统多是采用前后端分离的架构实现,所以基于 token 的方式更适合。

1.2.1 基于 session 的认证方式

基于 session 的认证方式如下图
基于session的认证方式

基于 session 的认证交互流程

用户认证成功后,在服务端生成用户相关的数据保存在 session(当前会话) 中,发给客户端 的 session_id 存放到 cookie 中, 这样用户客户端请求时带上 session_id 就可以验证服务端是否存在 session 数据,以此完成用户的合法校验,当用户退出系统或 session 过期销毁时,客户端的 session_id 也就无效了。

1.2.2 基于 token 的认证方式

基于 token 的认证方式如下图
基于token的认证方式

基于 token 的认证交互流程

用户认证成功后,服务端生成一个 token 发给客户端,客户端可以放到 cookie 或 localStorage 等存储中,每次请求时带上 token,服务端收到 token 通过校验后即可确认用户身份。

1.3 什么是授权?

为什么要授权

是为了更细粒度的对隐私数据进行划分。

什么是授权

授权是用户认证通过根据用户权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。

1.3.1 授权的数据模型

授权可以简单的理解为 Who 对 What(Which) 进行 How 操作。

关键的概念

  • Who,即主体(Subject):主体一般是用户,也可以是程序,需要访问系统中的资源。
  • What,即资源(Resource):系统菜单、页面、按钮、代码方法、系统商品信息、系统订单信息等。系统菜单、页面、按钮、代码方法都属于系统功能资源,对于web系统每个功能资源通常对应一个URL;系统商品信息、系统订单信息都属于实体资源(数据资源),实体资源由资源类型和资源实例组成,比如商品信息为资源类型,商品编号为 001 的商品为资源实例。
  • How,权限/许可(Permission):规定了用户对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个代码方法的调用权限、编号为 001 的用户的修改权限等,通过权限可知用户对哪些资源都有哪些操作许可。

主体、资源、权限关系如下图
主体、资源、权限关系

主体、角色、权限关系如下图
主体、角色、权限

1.4 RBAC 介绍

如何实现授权?

业界通常基于 RBAC 的实现授权。

基于角色的访问控制

RBAC 基于角色的访问控制 (Role Based Access Control) 是按角色授权。

例如:主体的角色为总经理可以查询企业运营报表,查询员工工资信息等,访问控制流程如下:
基于角色的访问控制

当需要修改角色的权限时就需要修改授权相关的代码,系统的可扩展性差。

基于资源的访问控制

RBAC 基于资源的访问控制 (Resource Based Access Control) 是按资源(或权限)进行授权。
基于资源的访问控制

优点:系统设计时定义好查询工资的权限标识,即使查询工资所需要的角色变化为总经理和部门经理也不需要修改授权代码,系统的可扩展性强。

2. Spring Security

2.1 Spring Security 介绍

Spring Security 是一个能够为基于 Spring 的企业级应用系统提供声明式的安全访问控制解决方案的安全框架。由于它是 Spring 生态系统中的一员,因此它伴随整个 Spring 生态系统不断修正、升级,在 Spring Boot 项目中加入 Spring Security 更是十分简单,使用 Spring Security 减少了为企业系统安全控制编写大量重复代码的工作。

2.2 Spring Security 工作原理

2.2.1 结构总览

Spring Security 所解决的问题就是安全访问控制,而安全访问控制功能其实就是对所有进入系统的请求进行拦截,校验每个请求是否能够访问它所期望的资源。一般实现的方式有 Filter 和 AOP。Spring Security 对 web 资源的保护是靠 Filter 实现的。

当初始化 Spring Security 时,会创建一个名为 SpringSecurityFilterChain 的 Servlet 过滤器,类型为 org.springframework.security.web.FilterChainProxy, 它实现了 javax.servlet.Filter, 因此外部的请求会经过此类。

Spring Security 过滤器链结构
Spring Security 过滤器链结构

  • AuthenticationManager:用于用户认证
  • AccessDecisionManager:用于权限校验

FilterChainProxy 是一个代理,真正起作用的是 FilterChainProxy 中 SecurityFilterChain 所包含的各个 Filter,同时这些 Filter 作为 bean 被 Spring 管理,它们是 Spring Security 的核心,各有各的职责,但它们并不直接处理用户的认证,也不直接处理用户的授权,而是把它们交给了认证管理器 (AuthenticationManager)和决策管理器 (AccessDecisionManager) 进行处理。

FilterChainProxy相关类的UML
FilterChainProxy相关类的UML

Spring Security 功能的实现主要是由一系列的过滤器链相互配合完成
SecurityFilterChain

  • SecurityContextPersistenceFilter:这个 Filter 是整个拦截过程的入口和出口 (也就是第一个和最后一个拦截器),会在请求开始时从配置好的 SecurityContextRepository 中获取 SecurityContext,然后把它设置给 SecurityContextHolder。在请求完成后将 SecurityContextHolder 持有的 SecurityContext 再保存到配置好的 SecurityContextRepository,同时清除 SecurityContextHolder 所持有的 SecurityContext。
  • UsernamePasswordAuthenticationFilter:用于处理来自表单提交的认证,该表单必须提供对应的用户名和密码。其内部还有登录成功或失败后进行处理的 AuthenticationSuccessHandler 和 AuthenticationFailureHandler,这些都可以根据需求做相关的改变。
  • FilterSecurityInterceptor: 是用于保护 web 资源的,使用 AccessDecisionManager 对当前用户进行授权访问。
  • ExceptionTranslationFilter:能够捕获来自 FilterChain 的所有异常,并进行处理,但是它只会处理两类异常,AuthenticationException 和 AccessDecisionException,其他的异常它会继续抛出。

2.2.2 认证的流程

2.2.2.1 认证流程

认证流程

  1. 用户提交用户名、密码被 SecurityFilterChain 中的 UsernamePasswordAuthenticationFilter 过滤器获取到,封装为请求 Authentication,通常情况下是 UsernamePasswordAuthenticationToken 这个实现类。
  2. 然后过滤器将 Authentication 提交至认证管理器 (AuthenticationManager) 进行认证
  3. 认证成功后, AuthenticationManager 身份管理器返回一个被填充了信息的 (包括上面提供的权限信息、身份信息、细节信息、但密码通常会被移除)Authentication 实例。
  4. SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication, 通过 SecurityContextHolder.getContext().setAuthentication() 方法设置到其中。

AuthenticationManager 接口(认证管理器) 是认证相关的核心接口,也发起认证的出发点,他的实现类为 ProviderManager。而 Spring Security 支持多种认证方式,因此 ProviderManager 维护着一个 List<AuthenticationProvider> 列表,存放多种认证方式,最终实际的认证工作是由 AuthenticationProvider 完成的。

Web 表单的对应的 AuthenticationProvider 实现类为 DaoAuthenticationProvider, 它的内部又维护着一个 UserDetailsService 负责 UserDetails 的获取。最终 AuthenticationProvider 将 UserDetails 填充至 Authentication。

认证核心组件的大体关系
认证核心组件的大体关系

2.2.2.2 AuthenticationProvider 介绍

AuthenticationProvider 处理了认证的逻辑,它会去比对 UserDetailsService 提取到的用户密码和用户提供的密码是否一致。认证通过会将 Authentication(UsernamePasswordAuthenticationToken实现) 返回。

2.2.2.3 UserDetailsService 介绍

UserDetailsService 负责根据用户名提取用户信息 UserDetails(包含密码)
可以通过将自定义的 UserDetailsService 公开为 spring bean 来定义自定义身份验证。

2.2.2.4 PasswordEncoder 介绍

常见的 PasswordEncoder

  • BCryptPasswordEncoder
  • Pbkdf2PasswordEncoder
  • SCryptPasswordEncoder

2.2.3 授权流程

2.2.3.1 授权流程

Spring Security 可以通过 http.authorizeRequests() 对 web 请求进行授权保护。Spring Security 使用标准 Filter 建立了对 web 请求的拦截,最终实现对资源的授权访问。

Spring Security 的授权流程
授权流程

授权相关主要的过滤器

  • FilterSecurityInterceptor: 获取资源所需要的权限、用户所具有的权限
  • SecurityMetadataSource:
  • AccessDecisionManager: 对比获取资源所需要的权限和用户所具有的权限

授权流程

  1. 拦截请求:已认证用户访问受保护的web资源将被SecurityFilterChain中的FilterSecurityInterceptor 的子类拦截。
  2. 获取资源访问策略:FilterSecurityInterceptor 会从 SecurityMetadataSource 的子类 DefaultFilterInvocationSecurityMetadataSource 获取要访问当前资源所需要的权限 Collection<ConfigAttribute>。
  3. 最后,FilterSecurityInterceptor会调用 AccessDecisionManager 进行授权决策,若决策通过,则允许访问资源,否则将禁止访问。
2.2.3.2 授权决策

AccessDecisionManager 采用投票的方式来确定是否能够访问受保护资源的权限。
授权决策

SpringSecurity 内置了三个基于投票的 AccessDecisionManager实现类, 默认使用 AffirmativeBased

  • AffirmativeBased
  • ConsensusBased
  • UnanimousBased

AffirmativeBased 执行逻辑

  1. 只要 AccessDecisionVoter的投票为 ACCESS_GRANTED 则同意用户进行访问;
  2. 如果全部弃权,也表示通过;
  3. 如果没有一个人投赞成票,但是有人投反对票,则将抛出 AccessDeniedException.

ConsensusBased 执行逻辑

  1. 如果赞成票多余反对票则表示通过;
  2. 反过来,如果反对票多于赞成票则将抛出 AccessDeniedException;
  3. 如果赞成票与反对票相同且不等于 0,并且属性 allowIfEqualGrantedDeniedDecisions 的值为 true,则表示通过,否则将抛出异常 AccessDeniedException。参数 allowIfEqualGrantedDeniedDecisions 默认值为 true;
  4. 如果所有的 AccessDecisionVoter 都弃权了,则将视参数 allowIfAllAbstainDecisions 的值而定,如果该值为true则表示通过,否则将抛出异常 AccessDecisionException,参数 allowIfAllAbstainDecisions 的值默认为 false.

UnanimousBased 执行逻辑

  1. 如果受保护对象配置的某一个 ConfigAttribute 被任意的 AccessDecisionVoter 反对了,则将抛出 AccessDeniedException。
  2. 如果没有反对票,但是有赞成票,则表示通过。
  3. 如果全部弃权了,则将视参数 allowIfAllAbstainDecisions 的值而定,true 则通过,false 则抛出 AccessDeniedException。

Spring Security 也内置了一些投票者实现类

  • RoleVoter
  • AuthenticatedVoter
  • WebExpressionVoter

2.2.4 会话

用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保存在会话中。

Spring Security 提供会话管理,认证通过后将身份信息放入 SecurityContextHolder 上下文,SecurityContext 与当前线程进行绑定,方便用户获取用户身份。

会话机制

  • always:如果没有 session 存在就创建一个
  • ifRequired:如果需要就创建一个 Session (默认) 登录时。
  • never:Spring Security 将不会创建 session, 但是如果应用中其他地方创建了 session ,那么Spring Security 将会使用它。
  • stateless:Spring Security 将绝对不会创建 session,也不会使用session

默认情况下,Spring Security 会为每个登录成功的用户新建一个 session, 就是 IfRequired

stateless 适用于 Rest API 及其无状态认证机制。

安全会话cookie

  • httpOnly: 如果为 true,浏览器脚本将无法访问 cookie
  • secure: 如果为 true, 则 cookie 将仅通过 HTTPS 连接发送

2.2.5 授权

授权的方式包括 web 授权和方法授权,web 授权是通过 url 拦截进行实现,方法授权是通过方法拦截进行授权。他们都会调用 accessDecisionManager 进行授权决策,若为 web 授权则拦截器为 FilterSecurityInterceptor;若为方法授权则拦截器为 MethodSecurityInterceptor。如果同时通过 web 授权和方法授权则先执行 web 授权,执行方法授权。最后决策通过,则允许访问资源,否则将禁止访问。
授权

授权方式

  • web 授权:通过 url 拦截授权
  • 方法授权: 通过方法拦截授权
2.2.5.1 web授权

推荐使用基于资源的授权。
配置权限拦截时,应该将具体的权限拦截放到正则表达式的拦截前。

http.authorizeRequests() 保护 URL 常用的方法

  • authenticated() 保护 URL,需要用户登录
  • permitAll() 指定 URL 无需保护,一般应用与静态资源文件
  • hasRole(String role) 限制单个角色访问,角色将被增加 “ROLE_”,所以 “ADMIN” 将和 “ROLE_ADMIN” 进行比较。
  • hasAuthority(String authority) 限制单个权限访问
  • hasAnyRole(String… roles) 允许多个角色访问
  • hasAnyAuthority(String… authorities) 允许多个权限访问
  • access(String attribute) 该方法使用 SpEL 表达式,所以可以创建复杂的限制
  • haslpAddress(String ipaddressExpression) 限制IP地址或子网
2.2.5.1 方法授权

从 Spring Security 2.0 版本开始,它支持服务层方法的安全性的支持

  • @PreAuthorize 方法执行前拦截
  • @PostAuthorize 方法执行后拦截
  • @Secured

可以在任何 @Configuration 实例上使用 @EnableGlobalMethodSecurity 注释来启用基于注解的安全性。

@Secured 使用

  • @Secured(“IS_AUTHENTICATED_ANONYMOUSLY”): 不需要登录就可以访问
  • @Secured(“ROLE_TELLER”):需要角色为 TELLER 才可以访问

@PreAuthorize 使用

  • @PreAuthorize(“hasAuthority(‘p1’)”):拥有p1 权限才可以访问

3.分布式系统认证方案

3.1 什么是分布式系统

随着软件环境和需求的变化,软件的架构由单体结构演变为分布式架构,具有分布式架构的系统叫分布式系统。

分布式系统的运行通常依赖网络,它将单体结构的系统分为若干服务,服务之间通过网路交互来完成用户的业务,当前流行的微服务架构就是分布式系统架构。

分布式系统架构
分布式系统架构

分布式系统的特点

  1. 分布性:每个部分都可以独立部署,服务之间交互通过网络进行通信。
  2. 伸缩性:每个部分都可以集群方式部署,并可针对部分节点进行硬件及软件扩容,具有一定的伸缩能力
  3. 共享性:每个部分都可以作为共享资源对外提供服务,多个部分可能有操作共享资源的情况。
  4. 开放性:每个部分根据需求都可以对外发布共享资源的访问接口,并可允许第三方系统访问。

3.2 分布式认证需求

分布式系统的每个服务都会有认证、授权的需求,如果每个服务都实现一套认证授权逻辑会非常冗余,考虑分布式系统共享性的特点,需要由独立的认证服务处理系统认证授权的请求;考虑分布式系统开放性的特点,不仅对系统内部服务提供认证,对第三方系统也要提供认证。

分布式认证的需求总结:

  • 统一认证授权
  • 应用接入认证

统一认证授权

提供独立的认证服务,统一处理认证授权。
无论是不同类型的用户,还是不同种类的客户端(web端、H5、APP),均采用一致的认证、权限、会话机制,实现统一认证授权。
要实现统一则认证方式必须可扩展,支持各种认证需求,比如:用户名密码认证、短信验证码、二维码、人脸识别等认证方式,并可以非常灵活的切换。

应用接入认证

应提供扩展和开放的能力,提供安全的系统对接机制,并可开放部分 API 给接入第三方使用,一方应用(内部系统服务)和三方应用(第三方应用)均采用统一机制接入。

3.3 分布式认证方案

3.3.1 选型分析

1.基于 Session 的认证方式

  • Session 复制
  • Session 黏贴
  • Session 集中存储

总的来说,基于 session 认证的认证方式,可以更好的在服务端对会话进行控制,且安全性较高,但是 session 机制方式基于 cookie,在复杂多样的移动客户端上不能有效的使用,并且无法跨域,另外随着系统的扩展需提高 session 的复制、黏贴及存储的容错性。

2.基于token的认证方式

基于 token 的认证方式,服务端不用存储认证数据,易维护扩展性强,客户端可以把token存在任意地方,并且可以实现 web 和 app 统一认证机制。其缺点也很明显,token 由于自包含信息,因此一般数据量较大,而且每次请求都需要传递,因此比较占带宽,另外,token的签名操作也会给 cpu 带来额外的处理负担。

3.3.2 技术方案

根据选型的分析,决定采用基于 token 的认证方式,它的优点是:

  1. 适合统一认证的机制,客户端、一方应用、三方应用都遵循一致的认证机制。
  2. token 认证方式对第三方应用的接入更适合,因为它更开放,可使用当前有流行的开放协议 Oauth 2.0 、JWT 等。
  3. 一般情况下服务端无需存储会话信息,减轻了服务器的压力。

分布式系统认证技术方案
分布式系统认证流程

分布式系统认证流程描述

  1. 用户通过接入方(应用)登录,接入方采取 OAuth2.0 方式在统一认证服务中认证
  2. 认证服务调用验证该用户的身份是否合法,并获取用户权限信息。
  3. 认证服务获取接入方权限信息,并验证接入方是否合法。
  4. 若登录用户以及接入方都合法,认证服务生成 jwt 令牌返回给接入方,其中 jwt 中包含了用户权限及接入方权限。
  5. 后续,接入方携带 jwt 令牌通过网关对微服务资源进行访问。
  6. 网关对令牌解析、并验证接入方的权限是否能够访问本次请求的微服务。
  7. 如果接入方的权限没问题,网关将原请求header中附加解析后的明文Token,并将请求转发至微服务。
  8. 微服务收到请求,明文token中包含登录用户的身份和权限信息。因此后续微服务自己可以干两件事:1,用户授权拦截(看当前用户是否有权访问该资源)2,将用户信息存储进当前线程上下文(有利于后续业务逻辑随时获取当前用户信息)

流程所涉及到认证服务、网关这两个组件职责如下:

  1. 统一认证服务:它承载了OAuth2.0接入方认证、登入用户的认证、授权以及生成令牌的职责,完成实际的用户认证、授权功能。
  2. 网关:作为系统的唯一入口,网关为接入方提供定制的API集合,它可能还具有其它职责,如身份验证、监控、负载均衡、缓存等。网关方式的核心要点是,所有的接入方和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。

4. OAuth 2.0

4.1 OAuth2.0 介绍

OAuth (开放授权) 是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。

OAuth 2.0 是 OAuth 协议的延续版本,但不向后兼容 OAuth 1.0,即完全废止 OAuth 1.0。

OAuth2.0 认证过程
OAuth2的认证流程

OAuth 4.0 角色

  1. 客户端:本身不存储资源,需要通过资源拥有者的授权去请求资源服务器的资源。
  2. 资源拥有者:通常为用户,也可以是应用程序,即该资源的拥有者。
  3. 授权服务器:用于服务提供商对资源拥有的身份进行认证、对访问资源进行授权,认证成功后会给客户端发放令牌,作为客户端访问资源服务器的凭据。
  4. 资源服务器:存储资源的服务器。

现在还有一个问题,服务提供商能允许随便一个客户端就接入到他们的授权服务器吗?答案是否定的,服务提供商会给准入的接入方一个身份,用于接入时的凭据:

  • client_id: 客户端标识
  • client_secret: 客户端密钥

因此准确的来说,授权服务器对两种 OAuth2.0 中的两个角色进行认证授权,分别是 资源拥有者、客户端。

4.2 Spring Cloud Security OAuth 2.0

4.2.1 环境介绍

Spring-Security-OAuth2.0 是对 OAuth2.0 的一种实现,并且和 Spring Security 相辅相成,与 Spring Cloud 体系的集成也非常便利。

OAuth 2.0 的服务提供方涵盖两个服务:

  • 授权服务(Authorization Server,也叫认证服务)
  • 资源服务(Resource Server)

授权服务(Authorization Server,也叫认证服务)应包含对接入端以及用户的合法性进行验证并颁发 token 等功能。对令牌的请求端点由 Spring MVC 控制器实现,下面是配置一个认证服务必须要 实现的 endpoint:

  • AuthorizationEndpoint:服务用于认证请求。默认 URL /oauth/authorize
  • TokenEndpoint:服务于访问令牌的请求。默认 URL /oauth/token

资源服务(Resource Server):应包含对资源的保护功能,对非法请求进行拦截,对请求中 token 进行解析鉴权等,下面的过滤器用于实现 OAuth 2.0 资源服务

  • OAuth2AuthenticationProcessingFilter 用来对请求给出的身份令牌解析鉴权。

认证流程

  1. 客户端请求授权服务进行认证
  2. 认证通过后由授权服务颁发令牌
  3. 客户端携带令牌 token 请求资源服务
  4. 资源服务器校验令牌的合法性,合法即返回资源信息。

5.Spring Security OAuth2.0 实现分布式系统认证和授权示例源码

Spring Cloud Alibaba 集成 Spring Security OAuth2.0源码

参考文献

黑马程序员
OAuth2.0官方文档

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

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

相关文章

Spring-Spring之AOP底层原理解析---实践(动态代理)

动态代理 代理模式的解释&#xff1a;为其他对象提供一种代理以控制对这个对象的访问&#xff0c;增强一个类中的某个方法&#xff0c;对程序进行扩展。 cglib动态代理 方式一&#xff1a; public class UserService {public void test() {System.out.println("test..…

hadoop 大数据环境配置 配置jdk, hadoop环境变量 配置centos环境变量 hadoop(五)

1. 遗漏一步配置系统环境变量&#xff0c;下面是步骤&#xff0c;别忘输入更新系统环境命令 2. 将下载好得压缩包上传至服务器&#xff1a; /opt/module 解压缩文件存放地址 /opt/software 压缩包地址 3. 配置环境变量&#xff1a; 在/etc/profile.d 文件夹下创建shell文件 …

【Nginx】CentOS 安装Nignx

CentOS上安装Nginx&#xff1a; 1. 打开终端&#xff1a;使用SSH或者直接在服务器上打开终端。 2. 更新系统&#xff1a;运行以下命令以确保您的系统软件包列表是最新的&#xff1a; sudo yum update3. 安装Nginx&#xff1a;运行以下命令以安装Nginx&#xff1a; sudo yum…

性能测试 —— Jmeter分布式测试的注意事项和常见问题

Jmeter是一款开源的性能测试工具&#xff0c;使用Jmeter进行分布式测试时&#xff0c;也需要注意一些细节和问题&#xff0c;否则可能会影响测试结果的准确性和可靠性。 Jmeter分布式测试时需要特别注意的几个方面 1. 参数化文件的位置和内容 如果使用csv文件进行参数化&…

人工智能基础_机器学习030_ElasticNet弹性网络_弹性回归的使用---人工智能工作笔记0070

然后我们再来看elastic-net弹性网络,之所以叫弹性是因为,他融合了L1和L2正则,可以看到 他的公式 公式中有L1正则和L2正则两个都在这个公式中 可以看到弹性网络,在很多特征互相联系的时候,非常有用,比如, 相关性,如果数学好,那么物理也好,如果语文好,那么英语也好 这种联系 正…

[论文分享] Never Mind the Malware, Here’s the Stegomalware

Never Mind the Malware, Here’s the Stegomalware [IEEE Security & Privacy 2022] Luca Caviglione | National Research Council of Italy Wojciech Mazurczyk | Warsaw University of Technology and FernUniversitt in Hagen 近年来&#xff0c;隐写技术已逐渐被观…

处理本地DNS劫持,导致域名解析失败

回顾情形 在公司内网&#xff0c;有同事反馈appstoreconnect.apple.com网站需要通过代理才能正常访问。 向我这边询问&#xff0c;否修改过路由策略&#xff1b; 检测域名 通过域名ping检测网址&#xff0c;https://ping.chinaz.com/astrill.com&#xff0c;来ping域名apps…

「实用场景教程」如何用日程控件DHTMLX Scheduler制作酒店预订日历?(一)

dhtmlxScheduler是一个类似于Google日历的JavaScript日程安排控件&#xff0c;日历事件通过Ajax动态加载&#xff0c;支持通过拖放功能调整事件日期和时间&#xff0c;事件可以按天&#xff0c;周&#xff0c;月三个种视图显示。 DHTMLX Scheduler正式版下载 在本教程中&…

Git | Git的基本操作以及原理介绍

文章目录 基本操作创建git仓库配置name和email .git目录的结构git add & git commit.git目录结构的变化 git追踪管理的数据git的版本回退回退的原理回退的三种情况 版本库中文件的删除git分支管理分支的删除合并分支时的冲突分支的合并模式分支策略git stash不要在master分…

reactive和effect,依赖收集触发依赖

通过上一篇文章已经初始化项目&#xff0c;集成了ts和jest。本篇实现Vue3中响应式模块里的reactive方法。 前置知识要求 如果你熟练掌握Map, Set, Proxy, Reflect&#xff0c;可直接跳过这部分。 Map Map是一种用于存储键值对的集合&#xff0c;并且能够记住键的原始插入顺…

谈谈一个IT杂家的职业生涯规划,你的护城河被AI 攻破了么

文章大纲 没有顶会的从业者&#xff1a;成为深度学习老中医AIGC 还未能克服的难点&#xff1a;忽然的惊喜 -- 大模型的智能涌现未来还能做点什么&#xff0c;从计算机视觉的发展走向看T 字型人才与护城河成为更加熟练使用人工智能的人 参考文献与学习路径 我的职业生涯将近十年…

JVM实战-JVM之类加载时机

目录 JVM实战-JVM之类加载时机1 主动引用2 被动引用 JVM实战-JVM之类加载时机 Java虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验、转换解析和初始化&#xff0c;最终形成可以被虚拟机直接使用的Java类型&#xff0c;这个过程被称作虚拟机的类加载机…

第一篇 《随机点名答题系统》简介及设计流程图(类抽奖系统、在线答题系统、线上答题系统、在线点名系统、线上点名系统、在线考试系统、线上考试系统)

专栏目录 第一篇 《随机点名答题系统》简介及设计流程图&#xff08;类抽奖系统、在线答题系统、线上答题系统、在线点名系统、线上点名系统、在线考试系统、线上考试系统&#xff09;-CSDN博客 第二篇 《随机点名答题系统》——题库管理详解&#xff08;类抽奖系统、在线答题…

【luckfox】0、开发环境搭建

前言 本章简单介绍如何搭建luckfox的开发环境。 一、抓取luckfox源码 需要提前准备好ubuntu环境。 git clone https://github.com/LuckfoxTECH/luckfox-pico.git二、编译 youkaiubuntu:/home/luckfox/luckfox-pico$ ./build.sh lunchyoukaiubuntu:/home/luckfox/luckfox-p…

SoftwareTest6 - 用 Selenium 怎么点点点

用 Selenium 来点点点 一 . 什么是自动化 ?1.1 自动化测试的分类接口自动化测试UI 自动化测试 (界面测试) 1.2 实现自动化测试的工具 : selenium环境部署驱动 二 . selenium 的使用2.1 一个简单的示例 : 让谷歌浏览器在百度首页搜索蔡徐坤准备工作编写代码 2.2 打开谷歌浏览器…

C++内存分区 代码区 全局区 栈区 堆区

一.内存四区 1.1 代码区&#xff1a; 存放函数体的二进制代码&#xff0c;由操作系统进行管理。1.2 全局区&#xff1a; 存放全局变量&#xff0c;静态变量以及常量。1.3 栈区&#xff1a; 由编译器自动分配释放&#xff0c;存放函数的参数值&#xff0c;局部变量等。1.4 堆…

JVM虚拟机:垃圾回收器之G1

本文重点 在前面的课程中我们介绍了六个垃圾回收器,分别是新生代的三个以及老年代的三个,本文我们将介绍一个垃圾回收器,它既可以用于新生代又可以用于老年代,这个垃圾回收器就是G1。 G1垃圾回收器的特点 G1是一种服务器端的并发收集垃圾回收器,应用在多处理器和大容量…

大文件分片上传、断点续传、秒传

小文件上传 后端&#xff1a;SpringBootJDK17 前端&#xff1a;JavaScriptsparkmd5.min.js 一、依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.2</ve…

python数据处理作业4:使用numpy数组对象,随机创建4*4的矩阵,并提取其对角元素

每日小语 真理诚然是一个崇高的字眼&#xff0c;然而更是一桩崇高的业绩。如果人的心灵与情感依然健康&#xff0c;则其心潮必将为之激荡不已。——黑格尔 难点&#xff1a;如何创建&#xff1f;取对角元素的函数是什么&#xff1f; gpt代码学习 import numpy as np# 随机创…

【数据结构】树与二叉树(十六):二叉树的基础操作:插入结点(算法Insert)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…