SpringSecurity中文文檔(Servlet Password Storage)

存儲機制(Storage Mechanisms)

每種支持的讀取用戶名和密碼的機制都可以使用任何支持的存儲機制:

  • Simple Storage with In-Memory Authentication
  • Relational Databases with JDBC Authentication
  • Custom data stores with UserDetailsService
  • LDAP storage with LDAP Authentication

In-Memory Authentication

Spring Security 的 InMemoryUserDetailsManager實現了 UserDetailsService,以支持存儲在內存中的基于用戶名/密碼的身份驗證。InmemyUserDetailsManager 通過實現 UserDetailsManager 接口提供對 UserDetails 的管理。當 SpringSecurity 配置為接受用戶名和密碼進行身份驗證時,將使用基于 UserDetails 的身份驗證。

在下面的示例中,我們使用 Spring Boot CLI 對密碼的密碼值進行編碼,并得到{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW

InMemoryUserDetailsManager Java Configuration

@Bean
public UserDetailsService users() {UserDetails user = User.builder().username("user").password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW").roles("USER").build();UserDetails admin = User.builder().username("admin").password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW").roles("USER", "ADMIN").build();return new InMemoryUserDetailsManager(user, admin);
}

前面的示例以安全的格式存儲密碼,但在初始體驗方面還有很多不足之處。

在下面的示例中,我們使用 User.withDefaultPasswordEncoder 來確保存儲在內存中的密碼受到保護。但是,它不能通過反編譯源代碼來防止獲取密碼。因此,User.withDefaultPasswordEncoder 只能用于“入門”,而不能用于生產。

InMemoryUserDetailsManager with User.withDefaultPasswordEncoder

@Bean
public UserDetailsService users() {// The builder will ensure the passwords are encoded before saving in memoryUserBuilder users = User.withDefaultPasswordEncoder();UserDetails user = users.username("user").password("password").roles("USER").build();UserDetails admin = users.username("admin").password("password").roles("USER", "ADMIN").build();return new InMemoryUserDetailsManager(user, admin);
}

在基于 XML 的配置中使用 User.withDefaultPasswordEncoder 沒有簡單的方法。對于演示或剛開始,您可以選擇以{ noop }作為密碼的前綴來表示不應該使用編碼:

<user-service><user name="user"password="{noop}password"authorities="ROLE_USER" /><user name="admin"password="{noop}password"authorities="ROLE_USER,ROLE_ADMIN" />
</user-service>

JDBC Authentication

Spring Security 的 JdbcDaImpl 實現了 UserDetailsService,以支持使用 JDBC 檢索的基于用戶名和密碼的身份驗證。JdbcUserDetailsManager 擴展了 JdbcDaImpl,通過 UserDetailsManager 接口提供對 UserDetails 的管理。Spring Security 將基于 UserDetails 的身份驗證配置為接受用戶名/密碼進行身份驗證時,將使用該身份驗證。

在下面的章節中,我們將討論:

  • Spring Security JDBC Authentication使用的默認架構
  • 設置數據源
  • JdbcUserDetailsManager Bean

默認架構(Default Schema)

SpringSecurity 為基于 JDBC 的身份驗證提供默認查詢。本節提供與默認查詢一起使用的相應默認架構。您需要調整模式,使其與所使用的查詢和本地數據庫的任何定制相匹配。

用戶架構(User Schema)

JdbcDaImpl 需要表來加載用戶的密碼、帳戶狀態(啟用或禁用)和權限(角色)列表。默認模式也公開為一個名為 org/springFramework/security/core/userDetails/jdbc/users.ddl 的類路徑資源。

Default User Schema

create table users(username varchar_ignorecase(50) not null primary key,password varchar_ignorecase(500) not null,enabled boolean not null
);create table authorities (username varchar_ignorecase(50) not null,authority varchar_ignorecase(50) not null,constraint fk_authorities_users foreign key(username) references users(username)
);
create unique index ix_auth_username on authorities (username,authority);

Oracle 是一種流行的數據庫選擇,但需要一種略有不同的模式:

Default User Schema for Oracle Databases

CREATE TABLE USERS (USERNAME NVARCHAR2(128) PRIMARY KEY,PASSWORD NVARCHAR2(128) NOT NULL,ENABLED CHAR(1) CHECK (ENABLED IN ('Y','N') ) NOT NULL
);CREATE TABLE AUTHORITIES (USERNAME NVARCHAR2(128) NOT NULL,AUTHORITY NVARCHAR2(128) NOT NULL
);
ALTER TABLE AUTHORITIES ADD CONSTRAINT AUTHORITIES_UNIQUE UNIQUE (USERNAME, AUTHORITY);
ALTER TABLE AUTHORITIES ADD CONSTRAINT AUTHORITIES_FK1 FOREIGN KEY (USERNAME) REFERENCES USERS (USERNAME) ENABLE;

組結構(Group Schema)

如果應用程序使用組,則需要提供組架構:

Default Group Schema

create table groups (id bigint generated by default as identity(start with 0) primary key,group_name varchar_ignorecase(50) not null
);create table group_authorities (group_id bigint not null,authority varchar(50) not null,constraint fk_group_authorities_group foreign key(group_id) references groups(id)
);create table group_members (id bigint generated by default as identity(start with 0) primary key,username varchar(50) not null,group_id bigint not null,constraint fk_group_members_group foreign key(group_id) references groups(id)
);

設置數據源(Setting up a DataSource)

在配置 JdbcUserDetailsManager 之前,必須創建一個 DataSource。在我們的示例中,我們設置了一個用默認用戶架構初始化的嵌入式 DataSource。

@Bean
DataSource dataSource() {return new EmbeddedDatabaseBuilder().setType(H2).addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION).build();
}

JdbcUserDetailsManager Bean

在這個示例中,我們使用 Spring Boot CLI 對密碼的密碼值進行編碼,并獲得{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW 的編碼密碼。有關如何存儲密碼的詳細信息,請參閱 PasswordEncoder 部分。

JdbcUserDetailsManager

@Bean
UserDetailsManager users(DataSource dataSource) {UserDetails user = User.builder().username("user").password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW").roles("USER").build();UserDetails admin = User.builder().username("admin").password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW").roles("USER", "ADMIN").build();JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);users.createUser(user);users.createUser(admin);return users;
}

UserDetails

UserDetails 由 UserDetailsService 返回。DauAuthenticationProvider 驗證 UserDetails,然后返回一個 Authentication,其主體是由配置的 UserDetailsService 返回的 UserDetails。

UserDetailsService

DataAuthenticationProvider 使用 UserDetailsService 檢索用戶名、密碼和其他屬性,以便使用用戶名和密碼進行身份驗證。Spring Security 提供了 UserDetailsService 的內存、 JDBC 和緩存實現。

可以通過將自定義 UserDetailsService 公開為 bean 來定義自定義身份驗證。例如,下面的清單假設 CustomUserDetailsService 實現 UserDetailsService,從而自定義身份驗證:

只有在沒有填充 AuthenticationManagerBuilder 且沒有定義 AuthenticationProviderBean 的情況下才會使用。

Custom UserDetailsService Bean

@Bean
CustomUserDetailsService customUserDetailsService() {return new CustomUserDetailsService();
}

PasswordEncoder

SpringSecurity 的 servlet 支持包括通過集成 PasswordEncoder 來安全地存儲密碼。您可以通過公開 PasswordEncoderBean 來自定義 Spring Security 使用的 PasswordEncoder 實現。

DaoAuthenticationProvider

DauAuthenticationProvider 是一個 AuthenticationProvider 實現,它使用 UserDetailsService 和 PasswordEncoder 對用戶名和密碼進行身份驗證。

本節研究 DauAuthenticationProvider 如何在 SpringSecurity 中工作。下圖以“閱讀用戶名和密碼”部分中的數字解釋了 AuthenticationManager 的工作原理。

daoauthenticationprovider

  1. Reading the Username & Password 部分中的身份驗證篩選器將 UsernamePasswordAuthenticationToken 傳遞給 AuthenticationManager,后者由 ProviderManager 實現。
  2. ProviderManager 配置為使用類型為 DauAuthenticationProvider 的 AuthenticationProvider。
  3. DauAuthenticationProvider 從 UserDetailsService 查找 UserDetails。
  4. DauAuthenticationProvider 使用 PasswordEncoder 驗證在上一步中返回的 UserDetails 上的密碼。
  5. 身份驗證成功后,返回的身份驗證類型為 UsernamePasswordAuthenticationToken,其主體是由配置的 UserDetailsService 返回的 UserDetails。最終,身份驗證篩選器將在 SecurityContextHolder 上設置返回的 UsernamePasswordAuthenticationToken。

LDAP Authentication

LDAP (輕型目錄訪問協議)經常被組織用作用戶信息的中央存儲庫和身份驗證服務。它還可用于存儲應用程序用戶的角色信息。

Spring Security 的基于 LDAP 的身份驗證在配置為接受用戶名/密碼進行身份驗證時使用。然而,盡管使用用戶名和密碼進行身份驗證,它并不使用 UserDetailsService,因為在綁定身份驗證中,LDAP 服務器不會返回密碼,因此應用程序無法進行密碼驗證。

對于如何配置 LDAP 服務器,有許多不同的場景,因此 Spring Security 的 LDAP 提供程序是完全可配置的。它使用單獨的策略接口進行身份驗證和角色檢索,并提供默認實現,可以將其配置為處理各種情況。

Required Dependencies

Spring Security LDAP Dependencies

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-ldap</artifactId>
</dependency>

Prerequisites

在嘗試將 LDAP 與 SpringSecurity 一起使用之前,您應該熟悉 LDAP。以下連結提供有關概念的簡介,以及使用免費 LDAP 伺服器(OpenLDAP)建立目錄的指引: www.zytrax.com/books/LDAP/。熟悉用于從 Java 訪問 LDAP 的 JNDI API 也很有用。我們在 LDAP 提供商中不使用任何第三方 LDAP 庫(Mozilla、 JLDAP 或其他) ,而是大量使用的是 Spring LDAP,所以如果您計劃添加自己的定制,對該項目有一些了解可能會有用。

在使用 LDAP 身份驗證時,應確保正確配置 LDAP 連接池。如果您不熟悉如何這樣做,請參閱 JavaLDAP 文檔。

設置嵌入式 LDAP 服務器(Setting up an Embedded LDAP Server)

您需要做的第一件事情是確保您有一個 LDAP 服務器來指向您的配置。

您需要做的第一件事情是確保您有一個 LDAP 服務器來指向您的配置。為了簡單起見,最好從嵌入式 LDAP 服務器開始。Spring Security 支持使用以下兩種方式:

  • Embedded UnboundID Server
  • Embedded ApacheDS Server

在下面的示例中,我們將 users.ldif 作為類路徑資源公開,以使用兩個用戶(user 和 admin)初始化嵌入式 LDAP 服務器,這兩個用戶都有密碼:

users.ldif

dn: ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: groupsdn: ou=people,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: peopledn: uid=admin,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Rod Johnson
sn: Johnson
uid: admin
userPassword: passworddn: uid=user,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Dianne Emu
sn: Emu
uid: user
userPassword: passworddn: cn=user,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: user
member: uid=admin,ou=people,dc=springframework,dc=org
member: uid=user,ou=people,dc=springframework,dc=orgdn: cn=admin,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: admin
member: uid=admin,ou=people,dc=springframework,dc=org

Embedded UnboundID Server

如果希望使用 Unbound ID,請指定以下依賴項:

UnboundID Dependencies

<dependency><groupId>com.unboundid</groupId><artifactId>unboundid-ldapsdk</artifactId><version>6.0.11</version><scope>runtime</scope>
</dependency>

然后可以使用 EmbeddedLdapServerContextSourceFactoryBean 配置嵌入式 LDAP 服務器。這將指示 Spring Security 啟動內存中的 LDAP 服務器:

Embedded LDAP Server Configuration

@Bean
public EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {return EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();
}

或者,可以手動配置嵌入式 LDAP 服務器。如果選擇這種方法,您將負責管理嵌入式 LDAP 服務器的生命周期。

Explicit Embedded LDAP Server Configuration

@Bean
UnboundIdContainer ldapContainer() {return new UnboundIdContainer("dc=springframework,dc=org","classpath:users.ldif");
}

Embedded ApacheDS Server

Spring Security 使用 ApacheDS 1.x,不再進行維護。不幸的是,ApacheDS 2.x 只發布了里程碑版本,沒有穩定的版本。一旦 ApacheDS 2.x 的穩定版本可用,我們將考慮更新。

如果您希望使用 Apache DS,請指定以下依賴項:

ApacheDS Dependencies

<dependency><groupId>org.apache.directory.server</groupId><artifactId>apacheds-core</artifactId><version>1.5.5</version><scope>runtime</scope>
</dependency>
<dependency><groupId>org.apache.directory.server</groupId><artifactId>apacheds-server-jndi</artifactId><version>1.5.5</version><scope>runtime</scope>
</dependency>

然后可以配置嵌入式 LDAP 服務器:

@Bean
ApacheDSContainer ldapContainer() {return new ApacheDSContainer("dc=springframework,dc=org","classpath:users.ldif");
}

LDAP ContextSource

一旦有了指向配置的 LDAP 服務器,就需要將 Spring Security 配置為指向應該用于身份驗證用戶的 LDAP 服務器。為此,創建一個 LDAP ContextSource (相當于 JDBC DataSource)。如果已經配置了 EmbeddedLdapServerContextSourceFactoryBean,Spring Security 將創建指向嵌入式 LDAP 服務器的 LDAP ContextSource。

LDAP Context Source with Embedded LDAP Server

@Bean
public EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean =EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();contextSourceFactoryBean.setPort(0);return contextSourceFactoryBean;
}

或者,可以顯式配置 LDAP ContextSource 以連接到提供的 LDAP 服務器:

LDAP Context Source

ContextSource contextSource(UnboundIdContainer container) {return new DefaultSpringSecurityContextSource("ldap://localhost:53389/dc=springframework,dc=org");
}

Authentication

Spring Security 的 LDAP 支持不使用 UserDetailsService,因為 LDAP 綁定身份驗證不允許客戶端讀取密碼,甚至不允許密碼的散列版本。這意味著沒有辦法讀取密碼,然后由 SpringSecurity 進行身份驗證。

因此,LDAP 支持是通過 LdapAuthenticator 接口實現的。LdapAuthenticator 接口還負責檢索任何必需的用戶屬性。這是因為對屬性的權限可能取決于所使用的身份驗證類型。例如,如果綁定為用戶,則可能需要使用用戶自己的權限讀取屬性。

Spring Security 提供了兩個 LdapAuthenticator 實現:

  • Using Bind Authentication
  • Using Password Authentication

Using Bind Authentication

綁定身份驗證是使用 LDAP 對用戶進行身份驗證的最常用機制。在綁定身份驗證中,用戶的憑據(用戶名和密碼)被提交給 LDAP 服務器,LDAP 服務器對它們進行身份驗證。使用綁定身份驗證的優點是不需要向客戶機公開用戶的秘密(密碼) ,這有助于保護它們不被泄露。

下面的示例演示綁定身份驗證配置:

Bind Authentication

@Bean
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);factory.setUserDnPatterns("uid={0},ou=people");return factory.createAuthenticationManager();
}

前面的簡單示例將通過在提供的模式中替換用戶登錄名并嘗試將該用戶與登錄密碼綁定來獲取該用戶的 DN。如果所有用戶都存儲在目錄中的單個節點下,則可以這樣做。如果希望配置 LDAP 搜索篩選器來定位用戶,可以使用以下方法:

Bind Authentication with Search Filter

@Bean
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);factory.setUserSearchFilter("(uid={0})");factory.setUserSearchBase("ou=people");return factory.createAuthenticationManager();
}

如果與前面顯示的 ContextSource 定義一起使用,這將使用(uid = {0})作為過濾器在 DN ou = people,dc = springFramework,dc = org 下執行搜索。同樣,用戶登錄名替代了篩選器名稱中的參數,因此它搜索的條目的 uid 屬性與用戶名相等。如果未提供用戶搜索基,則從根目錄執行搜索。

Using Password Authentication

密碼比較是將用戶提供的密碼與存儲庫中存儲的密碼進行比較。這可以通過檢索 password 屬性的值并在本地進行檢查來完成,也可以通過執行 LDAP 的“比較”操作來完成,其中提供的密碼被傳遞給服務器進行比較,并且永遠不會檢索到真正的密碼值。如果密碼使用隨機的 salt 進行了正確的散列,則無法進行 LDAP 比較。

Minimal Password Compare Configuration

@Bean
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {LdapPasswordComparisonAuthenticationManagerFactory factory = new LdapPasswordComparisonAuthenticationManagerFactory(contextSource, NoOpPasswordEncoder.getInstance());factory.setUserDnPatterns("uid={0},ou=people");return factory.createAuthenticationManager();
}

下面的示例顯示了一個更高級的配置,其中包含一些自定義項:

Password Compare Configuration

@Bean
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {LdapPasswordComparisonAuthenticationManagerFactory factory = new LdapPasswordComparisonAuthenticationManagerFactory(contextSource, new BCryptPasswordEncoder());factory.setUserDnPatterns("uid={0},ou=people");factory.setPasswordAttribute("pwd");return factory.createAuthenticationManager();
}
  • 將 password 屬性指定為 pwd。

LdapAuthoritiesPopulator

SpringSecurity 的 LdapAuthoritiesPopator 用于確定為用戶返回哪些權限。下面的示例顯示如何配置 LdapAuthoritiesPopator:

LdapAuthoritiesPopulator Configuration

@Bean
LdapAuthoritiesPopulator authorities(BaseLdapPathContextSource contextSource) {String groupSearchBase = "";DefaultLdapAuthoritiesPopulator authorities =new DefaultLdapAuthoritiesPopulator(contextSource, groupSearchBase);authorities.setGroupSearchFilter("member={0}");return authorities;
}@Bean
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource, LdapAuthoritiesPopulator authorities) {LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);factory.setUserDnPatterns("uid={0},ou=people");factory.setLdapAuthoritiesPopulator(authorities);return factory.createAuthenticationManager();
}

Active Directory

ActiveDirectory 支持自己的非標準身份驗證選項,正常的使用模式與標準的 LdapAuthenticationProvider 不太匹配。通常,身份驗證是通過使用域用戶名(以 user@domain 的形式)執行的,而不是使用 LDAP 專有名稱。為了簡化這一點,SpringSecurity 有一個身份驗證提供程序,該程序是為典型的 ActiveDirectory 設置定制的。

配置 ActiveDirectoryLdapAuthenticationProvider 非常簡單。您只需提供域名和提供服務器地址的 LDAP URL。

也可以通過 DNS 查找獲得服務器的 IP 地址。目前還不支持,但希望在將來的版本中會支持。

下面的示例配置 ActiveDirectory:

Example Active Directory Configuration

@Bean
ActiveDirectoryLdapAuthenticationProvider authenticationProvider() {return new ActiveDirectoryLdapAuthenticationProvider("example.com", "ldap://company.example.com/");
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/40043.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/40043.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/40043.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Cube大小與性能的博弈:Kylin查詢性能優化指南

Cube大小與性能的博弈&#xff1a;Kylin查詢性能優化指南 在Apache Kylin的多維數據分析世界中&#xff0c;Cube是核心組件&#xff0c;它直接影響查詢性能和系統資源的使用。理解Cube大小與查詢性能之間的關系對于構建高效的數據分析平臺至關重要。本文將深入探討Kylin中Cube…

FW SystemUI Keyguard解析(二)

文章目錄 CTS之Keyguard Menu事件處理 CTS之Keyguard Menu事件處理 事件觸發點: NotificationShadeWindowViewController.dispatchKeyEvent 設置setInteractionEventHandler回調之后通過NotificationShadeWindowView 觸發 調用到return mService.onMenuPressed(); public cla…

31-Pandas index操作索引

Pandas index操作索引 索引&#xff08;index&#xff09;是 Pandas 的重要工具&#xff0c;通過索引可以從 DataFame 中選擇特定的行數和列數&#xff0c;這種選擇數據的方式稱為“子集選擇”。 在 Pandas 中&#xff0c;索引值也被稱為標簽&#xff08;label&#xff09;&a…

簡單的text/html無法解析解決記錄

簡單的text/html無法解析解決記錄 1. bug發現 我們所有的服務都是微服務&#xff0c;服務間調用都是使用feign接口進行調用&#xff0c;正常調用都沒有問題&#xff0c;但是某一天發現部分從esb服務調用過來到我們本地的服務&#xff0c;本地服務再使用feign接口調用其他微服…

DPO算法推導

DPO 核心思想&#xff1a;直接使用偏好數據進行策略優化&#xff0c;省去 reward 模型策略優化。 技術背景知識&#xff1a; 首先給定prompt x&#xff0c;生成兩個答案 ( y 1 , y 2 ) Π S F T ( y ∣ x ) (y_1,y_2)~\Pi^{SFT}(y|x) (y1?,y2?) ΠSFT(y∣x) &#xff0c;并通…

2. Python+Playwright playwright的API

Playwright支持同步和異步兩種API&#xff0c;使用異步API需要導入asyncio庫&#xff0c;它是一個可以用來實現Python協程的庫&#xff0c;更詳細介紹可參考Python協程 。我們可以根據自己的偏好選擇適合的模式。 同步與異步模式原理 同步操作方式&#xff1a;在代碼執行時&am…

c++的const

const在C中是一個非常重要的關鍵字&#xff0c;用于定義不可變的變量、函數參數、成員函數等。它可以提高代碼的可讀性、安全性&#xff0c;并幫助編譯器進行優化。 定義常量 使用const定義不可變的變量&#xff1a; const int MAX_SIZE 100;常量指針 指向常量的指針和常量…

【ARMv8/v9 GIC 系列 5 -- GIC GICD_CTRL 使用詳細介紹】

文章目錄 GICD_CTRLGICD_CTLR 寄存器結構RWP&#xff08;Register Write Pending&#xff09;E1NWF&#xff08;Enable 1 of N Wakeup Functionality&#xff09;DS&#xff08;Disable Security&#xff09; 親和性路由&#xff08;Affinity Routing&#xff09;ARE_NSARE_S 中…

【java計算機畢設】服裝生產管理系統java MySQL springboot vue html maven項目設計源代碼+萬字文檔

目錄 1項目功能 2項目介紹 3項目地址 1項目功能 【java計算機畢設】服裝生產管理系統java MySQL springboot vue html maven項目代碼文檔 2項目介紹 系統功能&#xff1a; 服裝生產管理系統包括管理員、用戶兩種角色。 管理員功能包括個人中心模塊用于修改個人信息和密碼&a…

【UE5.3】筆記6-創建可自由控制Pawn類

搭建場景 搭建一個場景&#xff1a;包含地板、圍墻。可以根據喜好加一些自發光的效果。 增加食物 創建食物藍圖類&#xff0c;在場景里放置一些食物以供我們player去吃掉獲取分值。 創建可控制的layer 我們先右鍵創建一個藍圖繼承自pawn類&#xff0c;起名BP_Player&#xf…

Python-算法編程100例-二分法(入門級)-業務負載分配

題目&#xff1a; 現有一個服務器集群&#xff08;服務器數量為 serverNum&#xff09;&#xff0c;和一批不同類型的任務&#xff08;用數組 tasks 表示&#xff0c;下標表示任務類型&#xff0c;值為任務數量&#xff09;。 現需要把這批任務都分配到集群的服務器上&#x…

2024年在WordPress中創建銷售活動的專家級優惠券方法

2024年在WordPress中創建銷售活動的專家級優惠券方法 今天我想和大家分享一些關于如何在WordPress網站上使用專家級優惠券工具來創建銷售活動的經驗。對于已經在電商領域有一定經驗的店主&#xff0c;利用專家級優惠券不僅能吸引顧客&#xff0c;還能顯著增加銷量。在這篇文章…

【Linux】線程封裝與互斥(萬字)

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 目錄 文章目錄 前言 C多線程的用法 對原生線程進行一次封裝 理解pthread線程 Linux線程互斥 進程線程間的互斥相關背景概念 互斥量mutex 操作共享變量會有問題的售票…

[go-zero] goctl 生成api和rpc

文章目錄 1.goctl 概述2.go-zero 需要安裝的組件3.生成 api4.生成 rpc 1.goctl 概述 goctl支持多種rpc&#xff0c;較為流行的是google開源的grpc&#xff0c;這里主要介紹goctl rpc protoc的代碼生成與使用。protoc是grpc的命令&#xff0c;作用是將proto buffer文件轉化為相…

探討命令模式及其應用

目錄 命令模式命令模式結構命令模式適用場景命令模式優缺點練手題目題目描述輸入描述輸出描述題解 命令模式 命令模式是一種行為設計模式&#xff0c; 它可將請求轉換為一個包含與請求相關的所有信息的獨立對象。 該轉換讓你能根據不同的請求將方法參數化、 延遲請求執行或將其…

《亞馬遜搬運亞馬遜產品》配合跟賣采集爬取跟賣店鋪高質量

亞馬遜高質量產品如何搬運&#xff1f;亞馬遜采集亞馬遜。 哈嘍大家好&#xff0c;大家講一下做亞馬遜是發貨、鋪貨這塊的功能。目前這款軟件做跟賣大家都知道&#xff0c;同時也支持做鋪貨。鋪貨可以采集國內的1688、淘寶、京東都可以采&#xff0c;采完之后也可以采速賣通&a…

周周星分享7.3—基于氣象大數據的自動站實況聯合預測

賽題 2024中國高校計算機大賽 — 大數據挑戰賽 經驗分享 大家好&#xff0c;我是掃地僧團隊的隊長&#xff0c;以前參加這樣打榜的比賽比較少&#xff0c;了解的打榜技巧不是太多&#xff0c;所以想從科研的角度給大家一點分享。 這次比賽主要從以下五個步驟進行&#xff1a…

Linux Doxygen快速生成文檔

此前寫過一篇編寫Doxygen格式的注釋以用于生成文檔,點擊以查閱, Doxygen常用語法與字段記錄,但是當時用的windows桌面版的doxygen,最近使用ubuntu編寫代碼想直接使用doxygen生成,故寫下此博客 Doxygen Doxygen是一個用于生成軟件文檔的工具&#xff0c;它可以從代碼中提取注釋…

(四)opengl函數加載和錯誤處理

#include <glad/glad.h>//glad必須在glfw頭文件之前包含 #include <GLFW/glfw3.h> #include <iostream>void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height) {glViewport(0, 0, width, height);std::cout << width << &qu…

PHP多線程爬蟲:高效解析電商網頁內容

如何使用php多線程編寫高效的網頁爬蟲 隨著互聯網的發展和數據的不斷增長&#xff0c;網頁爬蟲成為了一種非常重要的工具。通過網頁爬蟲&#xff0c;我們可以自動地從各種網站上獲取大量的數據&#xff0c;并進行進一步的處理和分析。而PHP作為一種廣泛使用的編程語言&#xf…