Spring Boot实战:SSO和OAuth2.0

SSO和OAuth2.0

SSO(单点登录)和OAuth 2.0 是两个在认证和授权场景中常用的技术概念。它们的应用场景、目标和工作机制不同,但在一些方面也有联系。以下是它们的区别和联系的详细分析。

一、SSO(Single Sign-On)

1.1 定义

SSO(单点登录)是一种认证机制,它允许用户只需登录一次即可访问多个独立的应用系统,而不需要在每个系统上重复登录。SSO的核心是用户身份认证,即确定用户是谁,并在多个应用系统之间共享这一登录状态。

1.2 工作机制

SSO通常的工作流程如下:

  1. 用户访问一个需要认证的系统。
  2. 如果用户未登录,系统将用户重定向到SSO认证中心。
  3. 用户在认证中心登录,认证通过后,SSO认证中心生成一个令牌并返回给系统。
  4. 系统验证该令牌,用户成功登录并获得访问权限。
  5. 当用户访问其他系统时,系统使用同样的令牌或共享会话信息进行认证,允许用户无缝访问。
1.3 应用场景
  • 企业内部多个系统的统一登录。
  • 门户网站中多个子系统共享同一登录入口。
  • 需要在不同应用之间频繁切换的场景。
1.4 核心目标
  • 用户身份认证:主要目标是解决用户的单点登录问题,即多个系统共享用户的登录状态。

二、OAuth 2.0

2.1 定义

OAuth 2.0 是一种授权协议,允许第三方应用在不暴露用户凭据的情况下,安全地访问用户的资源。OAuth 2.0 的核心是授权,即用户授权第三方应用访问其资源的权限,而不是直接进行用户认证。

2.2 工作机制

OAuth 2.0的典型授权流程如下:

  1. 客户端(第三方应用)请求用户授权。
  2. 用户被引导到授权服务器,在登录并同意授权后,授权服务器会返回一个授权码给客户端。
  3. 客户端使用授权码向授权服务器请求访问令牌。
  4. 授权服务器颁发access_token,客户端使用该令牌访问资源服务器上的受保护资源。
2.3 应用场景
  • 第三方应用希望访问用户的数据或服务(如社交媒体API、支付系统)。
  • 用户授权应用访问其云存储文件、社交平台上的照片等场景。
  • 应用间的API授权和集成。
2.4 核心目标
  • 授权:主要解决第三方应用访问用户资源的问题,让用户能够控制第三方应用访问的权限和范围。

三、SSO与OAuth 2.0的区别

特性SSO(单点登录)OAuth 2.0(授权)
核心概念用户身份认证,解决多系统共享登录状态授权,允许第三方应用代表用户访问资源
重点认证,确定用户身份授权,控制第三方应用对资源的访问
典型场景用户在多个应用之间切换时无需重复登录第三方应用请求访问用户资源(API、数据)
主要角色用户、SSO认证中心、多个应用系统资源拥有者、客户端(应用)、授权服务器、资源服务器
令牌使用方式会话、Cookie 或 SSO令牌用于标识用户身份通过access_tokenrefresh_token 授权访问资源
授权范围不涉及资源授权,主要是身份认证用户可以细化对第三方应用的授权范围
安全目标提供用户统一的登录体验,减少多次登录风险控制第三方应用对用户数据的访问权限
实现复杂度相对简单,主要关注登录状态共享较高,涉及授权、令牌管理、授权范围和安全性

四、SSO与OAuth 2.0的联系

尽管SSO和OAuth 2.0在概念上有所不同,但它们在某些情况下可以结合使用,尤其是在现代的分布式系统和开放平台中。

4.1 SSO和OAuth 2.0的结合使用
  • OAuth 2.0 作为 SSO 的实现手段:OAuth 2.0通过授权服务器认证用户,并生成授权码或访问令牌(access token),允许用户使用相同的令牌在多个系统间访问资源,实现类似SSO的效果。例如,用户在一个门户网站(SSO认证中心)登录后,可以使用OAuth 2.0生成的令牌访问其他子系统,而不需要每次都重新登录。
  • OpenID Connect (OIDC):OIDC是基于OAuth 2.0的认证层协议,结合了OAuth 2.0的授权和SSO的认证功能。OIDC在OAuth 2.0的基础上,添加了用户身份信息,允许用户通过OAuth 2.0协议认证并共享登录状态。因此,OpenID Connect可以被视为一种结合了SSO和OAuth 2.0的协议,是一种标准的SSO解决方案。
4.2 SSO与OAuth 2.0的配合场景
  • 门户系统:在一些复杂的系统中,用户可以通过SSO实现单点登录进入门户网站,之后门户网站使用OAuth 2.0的授权机制授予用户对不同子系统的访问权限。
  • 微服务架构:在微服务架构中,可以结合SSO和OAuth 2.0。用户通过SSO登录系统后,系统使用OAuth 2.0生成访问令牌,用户携带该令牌在不同的微服务间访问受保护的资源。每个微服务可以验证令牌的有效性,从而保证访问的安全性和便捷性。
  • 跨组织系统:在跨组织系统中,用户可以通过SSO登录主系统,然后通过OAuth 2.0授权机制访问其他组织的系统或资源。例如,一个企业用户可以在企业门户上登录(SSO),然后通过OAuth 2.0授权机制访问其他合作伙伴的API资源。

五、总结

  • SSO主要解决用户认证问题,让用户在多个系统之间可以使用单一的登录状态,实现“登录一次,访问多处”的效果。
  • OAuth 2.0主要解决授权问题,让第三方应用在不获取用户凭据的情况下,可以安全地访问用户的资源。
  • SSO和OAuth 2.0在某些场景下可以结合使用。OAuth 2.0可以充当SSO的实现方式,通过授权服务器生成的令牌可以实现单点登录效果,而OpenID Connect(基于OAuth 2.0的认证协议)就是一个将SSO和OAuth 2.0结合的标准。
  • 在实际应用中,OAuth 2.0适合用于API访问、授权控制,而SSO适合用于统一的用户登录体验。结合SSO和OAuth 2.0可以构建一个完整的认证和授权解决方案,尤其适合分布式系统和微服务架构。

Spring Boot实现SSO

在Spring Boot项目中实现单点登录(SSO)功能,允许第三方系统通过SSO登录你的系统,可以通过OAuth 2.0协议和JWT(JSON Web Token)来实现。SSO的目标是让用户只需在SSO认证中心登录一次,即可访问多个系统而无需重复登录。下面将详细介绍如何实现这种方案。

一、SSO(单点登录)的基本原理

SSO的工作原理是多个系统共享用户的登录状态,通过集中式认证和授权服务器来统一管理登录。具体流程如下:

  1. 用户访问第三方系统:用户访问第三方系统A,但未登录。
  2. 重定向到SSO认证中心:第三方系统将用户重定向到SSO认证中心(授权服务器)。
  3. 用户登录并认证:用户在SSO认证中心登录并完成认证。
  4. 生成令牌并返回:SSO认证中心生成授权码或访问令牌,返回给第三方系统。
  5. 第三方系统验证令牌:第三方系统使用该令牌访问你的系统或资源服务器,以验证用户身份。
  6. 跨系统共享认证状态:当用户再次访问其他系统(如系统B),无需再次登录。

二、技术选型

在Spring Boot中,可以使用以下技术来实现SSO:

  • Spring Security OAuth2:提供OAuth 2.0的授权和认证支持。
  • JWT:使用JWT作为令牌,保存用户的认证信息,使系统能够基于令牌验证用户的身份。
  • Spring Security:用于管理用户的认证和授权。

三、实现步骤

3.1 添加依赖

首先,在pom.xml中添加Spring Security、OAuth2和JWT的依赖。

<dependencies><!-- Spring Security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- OAuth2 依赖 --><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId></dependency><!-- JWT 支持 --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
</dependencies>
3.2 配置授权服务器(Authorization Server)

授权服务器是整个SSO的核心,它负责用户的认证和生成访问令牌。在Spring Boot中可以通过配置OAuth 2.0来实现。

1. 创建AuthorizationServerConfig

在Spring Boot项目中,创建一个AuthorizationServerConfig类来配置授权服务器。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("third-party-client-id").secret("{noop}third-party-client-secret").authorizedGrantTypes("authorization_code", "refresh_token").scopes("read", "write").redirectUris("http://localhost:8081/callback");  // 回调地址}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(new JwtTokenStore(accessTokenConverter())).accessTokenConverter(accessTokenConverter());}@Beanpublic JwtAccessTokenConverter accessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey("mySecretKey");  // 设置JWT的签名密钥return converter;}
}

此配置实现了OAuth 2.0的授权模式,并且通过JWT生成访问令牌,第三方系统可以使用授权码获取令牌,并使用它来访问受保护的资源。

3.3 配置资源服务器(Resource Server)

资源服务器托管你的受保护资源,并通过验证令牌的合法性来控制资源的访问。

1. 创建ResourceServerConfig
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/public/**").permitAll()  // 公共资源.antMatchers("/private/**").authenticated();  // 受保护资源}
}
2. 创建受保护资源的控制器

定义一个受保护资源的控制器,用于测试SSO的访问控制。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ResourceController {@GetMapping("/private/data")public String getPrivateData() {return "This is a protected resource!";}@GetMapping("/public/data")public String getPublicData() {return "This is a public resource!";}
}
3.4 配置第三方系统(客户端应用)

第三方系统作为客户端应用,需要向授权服务器请求授权,并使用获取到的令牌访问受保护资源。

1. 在application.yml中配置OAuth 2.0客户端信息
spring:security:oauth2:client:registration:sso-client:client-id: third-party-client-idclient-secret: third-party-client-secretscope: read,writeauthorization-grant-type: authorization_coderedirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"provider:authserver:authorization-uri: http://localhost:8080/oauth/authorizetoken-uri: http://localhost:8080/oauth/tokenuser-info-uri: http://localhost:8080/userinfo
2. 使用Spring Security OAuth2登录

SecurityConfig类中启用OAuth2登录。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll().anyRequest().authenticated().and().oauth2Login();  // 启用OAuth2登录}
}

四、SSO工作流程

  1. 第三方系统请求授权码:用户访问第三方系统的受保护资源,系统检测到用户未登录,将用户重定向到SSO认证中心(授权服务器)。

  2. SSO认证中心处理认证请求:用户在SSO认证中心登录并通过认证后,授权服务器生成授权码并重定向回第三方系统的回调地址。

  3. 第三方系统获取访问令牌:第三方系统使用授权码向授权服务器请求访问令牌,授权服务器返回访问令牌给第三方系统。

  4. 访问受保护资源:第三方系统携带访问令牌访问资源服务器,资源服务器验证令牌的合法性后返回受保护资源。

  5. 其他系统共享登录状态:如果用户再次访问其他系统,这些系统可以使用同样的认证流程共享用户的登录状态,无需用户再次登录。

五、常见问题及建议

  1. 令牌的安全性:在生产环境中,建议使用HTTPS加密传输,防止令牌被拦截,JWT签名密钥也应妥善保管。
  2. 令牌的过期与刷新:访问令牌通常设置较短的有效期,可以使用刷新令牌机制延长会话,避免用户频繁登录。
  3. SSO登出与会话管理:在SSO环境下,登出操作需要清除各个系统的会话信息,可以通过分布式Session或集中式会话管理。
  4. 日志和监控:对登录、授权和资源访问等操作进行日志记录,方便后期审计和问题排查。

六、总结

通过以上配置,可以在Spring Boot项目中实现一个OAuth 2.0 SSO的认证授权系统,让第三方系统通过SSO登录你的系统。授权服务器集中管理用户认证,生成和验证JWT令牌,资源服务器通过验证令牌控制资源访问,客户端应用通过OAuth2流程安全地访问受保护资源。这种实现方式不仅提供了SSO功能,还具备了灵活的授权控制,非常适合在分布式架构中使用。

Spring Boot实现OAuth2.0授权

在Spring Boot中实现OAuth 2.0授权,允许第三方系统访问你的系统资源,通常包括搭建授权服务器、资源服务器,并通过OAuth 2.0协议来进行认证和授权。这种实现能够确保第三方系统安全地访问受保护的资源,而无需直接提供用户的凭据。

以下是实现OAuth 2.0授权的详细步骤,用于让第三方系统访问你的系统。

一、OAuth 2.0授权的基本工作原理

OAuth 2.0的授权流程主要包含以下几个步骤:

  1. 授权请求:第三方系统通过OAuth 2.0协议向授权服务器发起授权请求。用户被重定向到授权服务器,并在此进行登录。
  2. 用户同意授权:用户登录并同意授权后,授权服务器生成授权码并返回给第三方系统。
  3. 获取访问令牌:第三方系统使用授权码向授权服务器请求访问令牌(access_token)。
  4. 访问受保护资源:第三方系统使用access_token访问资源服务器上的受保护资源。

二、项目结构

OAuth 2.0授权在Spring Boot项目中通常需要三个主要组件:

  1. 授权服务器(Authorization Server):负责处理用户认证和授权请求,并生成访问令牌。
  2. 资源服务器(Resource Server):托管受保护资源,验证令牌的合法性。
  3. 客户端应用(Client Application):第三方系统,通过OAuth 2.0协议获取访问令牌并使用它来访问资源。

三、实现步骤

3.1 添加依赖

在Spring Boot项目的pom.xml文件中,添加Spring Security和OAuth 2.0相关依赖:

<dependencies><!-- Spring Security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- OAuth2 Authorization Server 和 Resource Server 支持 --><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.4.0</version></dependency><!-- JWT 支持 --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
</dependencies>
3.2 配置授权服务器(Authorization Server)

授权服务器负责生成和管理令牌,并处理用户的授权流程。我们可以使用Spring Security OAuth 2.0来配置授权服务器。

1. 创建AuthorizationServerConfig类

在Spring Boot项目中创建一个AuthorizationServerConfig类,继承AuthorizationServerConfigurerAdapter,配置授权服务器。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("client-id")  // 第三方系统的客户端ID.secret("{noop}client-secret")  // 客户端密钥.authorizedGrantTypes("authorization_code", "refresh_token")  // 支持的授权模式.scopes("read", "write")  // 授权范围.redirectUris("http://localhost:8081/callback");  // 回调地址}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {// 通过JWT生成令牌endpoints.tokenStore(new JwtTokenStore(jwtAccessTokenConverter())).accessTokenConverter(jwtAccessTokenConverter());}@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey("mySecretKey"); // 设置签名密钥return converter;}
}
3.3 配置资源服务器(Resource Server)

资源服务器托管受保护资源,并验证令牌的有效性。资源服务器可以通过JWT验证令牌,确保只有持有有效access_token的请求才能访问资源。

1. 创建ResourceServerConfig类

在Spring Boot项目中创建一个ResourceServerConfig类,继承ResourceServerConfigurerAdapter,配置资源服务器行为。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/api/public").permitAll()  // 公共接口.antMatchers("/api/private").authenticated();  // 受保护资源}
}

2. 受保护资源的控制器

在资源服务器中创建一个控制器,定义受保护的资源。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ResourceController {@GetMapping("/api/private")public String getPrivateData() {return "This is a protected resource!";}@GetMapping("/api/public")public String getPublicData() {return "This is a public resource!";}
}
3.4 配置客户端应用(Client Application)

客户端应用(即第三方系统)需要通过OAuth 2.0协议获取访问令牌,并使用令牌访问受保护资源。

1. 配置客户端信息

在第三方系统的application.yml中,配置OAuth 2.0客户端信息。

spring:security:oauth2:client:registration:myclient:client-id: client-idclient-secret: client-secretscope: read,writeauthorization-grant-type: authorization_coderedirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"provider:authserver:authorization-uri: http://localhost:8080/oauth/authorizetoken-uri: http://localhost:8080/oauth/tokenuser-info-uri: http://localhost:8080/userinfojwk-set-uri: http://localhost:8080/oauth/jwks

2. 使用Spring Security OAuth2登录

在客户端应用的SecurityConfig类中启用OAuth2登录,并配置安全策略。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll().anyRequest().authenticated().and().oauth2Login();  // 启用OAuth2登录}
}
3.5 授权流程演示
  1. 授权请求:第三方系统(客户端)发起授权请求,用户将被重定向到授权服务器进行登录和授权。典型的授权请求URL如下:

    http://localhost:8080/oauth/authorize?response_type=code&client_id=client-id&redirect_uri=http://localhost:8081/callback
    
  2. 用户登录和授权:用户在授权服务器上登录,并同意授权第三方系统访问其资源。

  3. 获取授权码:授权服务器生成授权码,并通过重定向将其返回给第三方系统的回调地址。

  4. 获取访问令牌:第三方系统使用授权码向授权服务器请求访问令牌。

    POST http://localhost:8080/oauth/token
    Content-Type: application/x-www-form-urlencodedgrant_type=authorization_code
    code=AUTHORIZATION_CODE
    redirect_uri=http://localhost:8081/callback
    client_id=client-id
    client_secret=client-secret
    
  5. 访问受保护资源:第三方系统使用获得的access_token来访问资源服务器上的受保护资源。

    GET /api/private
    Authorization: Bearer access_token
    

资源服务器验证令牌的合法性后,返回受保护的数据。

四、常见问题及建议

  1. 令牌存储与安全性:在生产环境中,建议使用JWT作为令牌存储,并通过HTTPS加密通信,防止令牌泄露。
  2. 令牌过期管理:可以通过刷新令牌(refresh_token)机制来延长会话,避免用户频繁登录。
  3. 客户端凭证管理:客户端密钥(client-secret)需要妥善保护,不要泄露给未授权的用户或系统。
  4. 授权范围的控制:OAuth 2.0的授权范围可以控制第三方应用的访问权限,确保第三方只能访问必要的数据。

五、总结

通过以上步骤,可以在Spring Boot中实现OAuth 2.0授权机制,允许第三方系统在获得用户授权后,安全地访问受保护的资源。授权服务器负责用户的认证和令牌生成,资源服务器负责资源的保护,客户端应用使用令牌访问资源。通过这种方式,可以实现一个标准的OAuth 2.0授权流程,确保数据的安全和用户的访问控制。

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

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

相关文章

AUTOSAR COM 与 LargeDataCOM 模块解析及 C++ 实现示例

AUTOSAR COM 和 LargeDataCOM 模块在功能和使用场景上有一些显著的区别。以下是它们的主要区别及具体的应用示例,最后用 C++ 源代码来解析说明。 AUTOSAR COM 模块 • 功能:主要用于处理标准大小的信号和 I-PDU(协议数据单元),提供了信号打包、解包、数据传输和接收等功能…

JavaWeb复习

在网络应用程序中有两种基本的结构&#xff0c;即C/S和B/S&#xff0c;对于c/s程序分为客户机和服务器两层&#xff0c;把应用软件按照在客户机端(通常由客户端维护困难)&#xff0c;通过网络与服务器进行相互通信。B/S结构却不用通知客户端安装某个软件&#xff0c;内容修改了…

qt获取本机IP和定位

前言&#xff1a; 在写一个天气预报模块时&#xff0c;需要一个定位功能&#xff0c;在网上翻来翻去才找着&#xff0c;放在这里留着回顾下&#xff0c;也帮下有需要的人 正文&#xff1a; 一开始我想着直接调用百度地图的API来定位&#xff0c; 然后我就想先获取本机IP的方…

python爬取旅游攻略(1)

参考网址&#xff1a; https://blog.csdn.net/m0_61981943/article/details/131262987 导入相关库&#xff0c;用get请求方式请求网页方式&#xff1a; import requests import parsel import csv import time import random url fhttps://travel.qunar.com/travelbook/list.…

Oracle OCP认证考试考点详解082系列12

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 56. 第56题&#xff1a; 题目 解析及答案&#xff1a; 关于企业管理器&#xff08;EM&#xff09;Express&#xff0c;以下哪两个陈述是…

Postgresql源码(137)执行器参数传递与使用

参考 《Postgresql源码&#xff08;127&#xff09;投影ExecProject的表达式执行分析》 0 总结速查 prepare p_04(int,int) as select b from tbl_01 where a $1 and b $2为例。 custom计划中&#xff0c;在表达式计算中使用参数的值&#xff0c;因为custom计划会带参数值&…

SPI通信详解-学习笔记

参考原文地址 SPI&#xff1a;高速、全双工&#xff0c;同步、通信总线 SPI主从模式 SPI分为主、从两种模式&#xff0c;一个SPI通讯系统需要包含一个&#xff08;且只能是一个&#xff09;主设备&#xff0c;一个或多个从设备。提供时钟的为主设备&#xff08;Master&#xff…

Day102漏洞发现-漏扫项目篇Poc开发Yaml语法插件一键生成匹配结果交互提取

知识点&#xff1a; 1、Nuclei-Poc开发-环境配置&编写流程 2、Nuclei-Poc开发-Yaml语法&匹配提取 3、Nuclei-Poc开发-BurpSuite一键生成插件 Nuclei-Poc开发-环境配置&编写流程 1、开发环境&#xff1a;VscodeYaml插件 Visual Studio Code - Code Editing. R…

Node.js 入门指南:从零开始构建全栈应用

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;node.js篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来node.js篇专栏内容:node.js-入门指南&#xff1a;从零开始构建全栈应用 前言 大家好&#xff0c;我是青山。作…

WordPress网站添加嵌入B站视频,自适应屏幕大小,取消自动播放

结合bv号 改成以下嵌入式代码&#xff08;自适应屏幕大小,取消自动播放&#xff09; <iframe style"width: 100%; aspect-ratio: 16/9;" src"//player.bilibili.com/player.html?isOutsidetrue&bvidBV13CSVYREpr&p1&autoplay0" scrolling…

大模型应用系列:Query 变换的示例浅析

【引】NLP中的经典组件在大模型应用中还有效么&#xff1f;大模型对自然语言处理中的典型任务有什么影响么&#xff1f; RAG应用通过分割文档、嵌入向量化并检索高语义相似性的块来响应用户问题&#xff0c;但面临文档块不相关、用户用词不当及结构化查询需求等问题。若RAG无法…

【Oracle】空格单字符通配符查询匹配失败

问题 在进行模糊查询的时候&#xff0c;通过全局任意字符串匹配出含有两个字刘姓的人&#xff0c;但是通过刘_不能匹配出结果。 解决 检查后发现&#xff0c;姓名中包含空格 SELECT * FROM student WHERE TRIM(sname) LIKE 刘_;第一种解决方案就是查询的时候进行去空格处理&a…

讲讲⾼并发的原则?

大家好&#xff0c;我是锋哥。今天分享关于【讲讲⾼并发的原则&#xff1f;】面试题。希望对大家有帮助&#xff1b; 讲讲⾼并发的原则&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 高并发是指系统在同一时间内能够处理大量请求的能力。要有效地管理…

鸿蒙进阶-AlphabetIndexer组件

大家好&#xff0c;这里是鸿蒙开天组&#xff0c;今天我们来学习AlphabetIndexer组件&#xff0c;喜欢就点点关注吧&#xff01; 通过 AlphabetIndexer 组件可以与容器组件结合&#xff0c;实现导航联动&#xff0c;以及快速定位的效果 核心用法 AlphabetIndexer不是容器组件…

ubuntu交叉编译expat库给arm平台使用

1.下载expat库源码: https://github.com/libexpat/libexpat/release?page=2 wget https://github.com/libexpat/libexpat/release/download/R_2_3_0/expat-2.3.0.tar.bz2 下载成功: 2.解压expat库,并进入解压后的目录: tar xjf expat-2.3.0.tar.bz2 cd expat-2.3.0 <…

【系统面试篇】进程和线程类(1)(笔记)——区别、通讯方式、同步、互斥、锁分类

目录 一、问题综述 1. 进程和线程的区别&#xff1f; 2. 进程的状态有哪些&#xff1f; 3. 进程之间的通信方式? &#xff08;1&#xff09;管道 &#xff08;2&#xff09;消息队列 &#xff08;3&#xff09;共享内存 &#xff08;4&#xff09;信号量 &#xff08…

nginx(四):如何在 Nginx 中配置以保留真实 IP 地址

如何在 Nginx 中配置以保留真实 IP 地址 1、概述2、nginx配置示例2.1、配置说明2.2、客户端获取真实IP2.2.1、代码说明 3、插曲4、总结 大家好&#xff0c;我是欧阳方超&#xff0c;可以我的公众号“欧阳方超”&#xff0c;后续内容将在公众号首发。 1、概述 当使用nginx作为…

C++《list的模拟实现》

在上一篇C《list》专题当中我们了解了STL当中list类当中的各个成员函数该如何使用&#xff0c;接下来在本篇当中我们将试着模拟实现list&#xff0c;在本篇当中我们将通过模拟实现list过程中深入理解list迭代器和之前学习的vector和string迭代器的不同&#xff0c;接下来就开始…

本篇万字,博客最细,oled多级菜单代码解析,与实现教程,指针实现(含源码)!!!

目录 教程前言 多级菜单基本知识 驱动文件创建 ​编辑 ​编辑 ​编辑 定义菜单数据类型代码解析 按键代码解析 菜单数据赋值代码解析 菜单按键切换显示代码解析 项目工程移植地址 教程前言 前言&#xff1a;编写不易&#xf…

华为HarmonyOS打造开放、合规的广告生态 - 贴片广告

场景介绍 贴片广告是一种在视频播放前、视频播放中或视频播放结束后插入的视频或图片广告。 接口说明 接口名 描述 loadAd(adParam: AdRequestParams, adOptions: AdOptions, listener: AdLoadListener): void 请求单广告位广告&#xff0c;通过AdRequestParams、AdOptions…