springsecurity---使用流程、加密機制、自定義密碼匹配器、token字符串生成

目錄

權限控制

相關框架

SpringSecurity

springsecurity使用流程

1、搭建環境實現默認用戶名和密碼登錄

2、使用數據庫表中定義好的用戶名和密碼訪問實現等值密碼匹配

1)sql文件

2)搭建jdbc或者mybatis或者mybatis-plus環境

3)配置mybatis-plus環境

4)使用mybatisX 生成基本的service和mapper

5)創建一個類實現UserDetailsService接口 ,重寫方法(根據用戶名到數據庫中查找用戶對象)

6)創建一個LoginUser實現UserDetails接口,封裝用戶信息

3、加密機制 自定義密碼匹配器

1)創建加密對象

2)使用測試類,生成臨時密碼,測試匹配方法

4、自定義登錄接口

5、token字符串的生成


權限控制

一、認證:是否登錄成功。

二、授權:權限控制,授予權限、校驗權限。

相關框架

一、shiro

Shiro 是 apache權限框架,較之 JAAS 和 Spring Security,Shiro 在保持強大功能的同時,還在簡單性和靈活性方面擁有巨大優勢。 Shiro 是一個強大而靈活的開源安全框架,能夠非常清晰的處理認證授權管理會話以及密碼加密

二、springsecurity

Spring Security 是 Spring家族中的一個安全管理框架。相比與另外一個安全框架Shiro,它提供了更豐

富的功能,社區資源也比Shiro豐富。

一般來說中大型的項目都是使用SpringSecurity來做安全框架。

小項目用Shiro的比較多,因為相比與SpringSecurity,Shiro的上手更加的簡單。

SpringSecurity

springsecurity 和 其他組件的簡單交互

前后端分離場景下,登錄校驗流程的核心思路:token。 Token是服務端生成的一串字符串,以作客戶端進行請求的一個令牌,當第一次登錄后,服務器生 成一個Token便將此Token返回給客戶端,以后客戶端只需帶上這個Token前來請求數據即可,無 需再次帶上用戶名和密碼。

使用token機制的身份驗證方法,在服務器端不需要存儲用戶的登錄記錄。

JWT:JWT全面解讀、詳細使用步驟 - 簡書

springsecurity使用流程

1、搭建環境實現默認用戶名和密碼登錄

springboot環境+springweb+springsecurity權限jar包

訪問目標方法時,自動跳轉到/login接口,輸入用戶名user和默認密碼,登錄成功后,自動跳轉到目標方法。

localhost:8080/login

2、使用數據庫表中定義好的用戶名和密碼訪問實現等值密碼匹配

1)sql文件
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` ?(`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',`user_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'NULL' COMMENT '用戶名',`nick_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'NULL' COMMENT '昵稱',`password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'NULL' COMMENT '密碼',`status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '賬號狀態(0正常 1停用)',`email` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '郵箱',`phonenumber` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手機號',`sex` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用戶性別(0男,1女,2未知)',`avatar` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '頭像',`user_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '用戶類型(0管理員,1普通用戶)',`create_by` bigint(20) NULL DEFAULT NULL COMMENT '創建人的用戶id',`create_time` datetime NULL DEFAULT NULL COMMENT '創建時間',`update_by` bigint(20) NULL DEFAULT NULL COMMENT '更新人',`update_time` datetime NULL DEFAULT NULL COMMENT '更新時間',`del_flag` int(11) NULL DEFAULT 0 COMMENT '刪除標志(0代表未刪除,1代表已刪除)',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用戶表' ROW_FORMAT = Dynamic;
?INSERT INTO `sys_user` VALUES (1, '張三', '張三', '{noop}1234', '0', NULL, NULL, NULL, NULL, '1', NULL, NULL, NULL, NULL, 0);
2)搭建jdbc或者mybatis或者mybatis-plus環境
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3</version>
</dependency>
3)配置mybatis-plus環境
server:port: 8080
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/springsecurityusername: rootpassword: 123456
mybatis-plus:configuration:map-underscore-to-camel-case: truetype-aliases-package: com.hl.springsecurity01.domainmapper-locations: classpath:/mapper/*.xml
4)使用mybatisX 生成基本的service和mapper

?

5)創建一個類實現UserDetailsService接口 ,重寫方法(根據用戶名到數據庫中查找用戶對象)
package com.hl.springsecurity01.security;
?
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hl.springsecurity01.domain.SysUser;
import com.hl.springsecurity01.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
?
import java.util.List;
?
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate SysUserService sysUserService;/*根據用戶名查找用戶對象*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//根據用戶名,到數據庫表中,查找用戶對象QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("user_name", username);List<SysUser> list = sysUserService.list(queryWrapper);//判斷用戶是否存在LoginUser user = null;if(list != null && list.size() > 0){SysUser sysUser = list.get(0);//封裝數據到UserDetails接口實現類對象中user = new LoginUser(sysUser);}return user;}
}
6)創建一個LoginUser實現UserDetails接口,封裝用戶信息
package com.hl.springsecurity01.security;
?
import com.hl.springsecurity01.domain.SysUser;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
?
import java.util.Collection;
import java.util.Collections;
/*
創建類實現UsersDetail接口,存儲當前登錄成功的用戶信息*/
@Data
public class LoginUser implements UserDetails {
?private SysUser sysUser;
?public LoginUser() {}public LoginUser(SysUser sysUser) {this.sysUser = sysUser;}
?//返回用戶權限信息,返回權限列表@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return Collections.emptyList();}
?@Overridepublic String getPassword() {return sysUser.getPassword();}
?@Overridepublic String getUsername() {return sysUser.getUserName();}
?@Overridepublic boolean isAccountNonExpired() {return true;}
?@Overridepublic boolean isAccountNonLocked() {return true;}
?@Overridepublic boolean isCredentialsNonExpired() {return true;}
?@Overridepublic boolean isEnabled() {return true;}
}

3、加密機制 自定義密碼匹配器

1)創建加密對象
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {/*創建加密對象(密碼匹配器對象)*/@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
}
2)使用測試類,生成臨時密碼,測試匹配方法
@SpringBootTest
class Springsecurity01ApplicationTests {@Autowiredprivate PasswordEncoder passwordEncoder;
?@Testvoid contextLoads() {String pwd = passwordEncoder.encode("1234");System.out.println(pwd);//$2a$10$DpNgEn0fiYStJJ/EoYxf7uhBOMnuqK/UdBKmexX5KrEVPLuGQ0LsS//$2a$10$sLUel1CyTVY1kDWM5BwlNu1WMLMqlys00NIir0SiEgR0A5ItM1Vda//比對密碼boolean flag1 = passwordEncoder.matches("1234", "$2a$10$DpNgEn0fiYStJJ/EoYxf7uhBOMnuqK/UdBKmexX5KrEVPLuGQ0LsS");boolean flag2 = passwordEncoder.matches("1234", "$2a$10$sLUel1CyTVY1kDWM5BwlNu1WMLMqlys00NIir0SiEgR0A5ItM1Vda");System.out.println(flag1);System.out.println(flag2);}
?
}
$2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
├─┬─┼──┬─┼──────────────┼───────────────────────────────────│ │  │  │ ? ?  │ ? ? ? ? ? ? ? ? ? ? │ │  │  │ ? ?  └─ 哈希值(31字節)│ │  │  └─ 鹽值(22字符,16字節)│ │  └─ cost參數(12 → 2^12=4096輪迭代)│ └─ 算法版本(2a)└─ 固定前綴
$<算法版本>$<cost>$<salt><hash>

4、自定義登錄接口

@RestController
public class LoginController {@Autowiredprivate LoginService loginService;@RequestMapping("/login")public R login(String username, String password) throws AuthenticationException {//調用servicereturn loginService.login(username, password);}
}
public interface LoginService {public R login(String username, String password) throws AuthenticationException;
}
@Service
public class LoginServiceImpl implements LoginService {@Autowiredprivate AuthenticationManager authenticationManager;@Overridepublic R login(String username, String password) throws AuthenticationException {UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username, password);//調用認證提供器的認證方法,進行用戶名,密碼認證Authentication authentication = authenticationManager.authenticate(token);//根據返回值判斷是否認證成功if(authentication == null){//認證失敗throw ?new AuthenticationException("用戶名或者密碼錯誤");}if(authentication.isAuthenticated()){//認證成功//返回 code ,msg,tokenreturn R.ok("token.............","認證成功");}return null;}
}
package com.hl.springsecurity01.security;
?
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {/*創建加密對象(密碼匹配器對象)*/@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// 對于登錄接口 允許匿名訪問.antMatchers("/login").anonymous()// 除上面外的所有請求全部需要鑒權認證.anyRequest().authenticated();}@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}

?將數據庫密碼字段換成生成的加密字段$2a$10$DpNgEn0fiYStJJ/EoYxf7uhBOMnuqK/UdBKmexX5KrEVPLuGQ0LsS

登錄成功,看到json返回,失敗,沒有任何提示。

5、token字符串的生成

<!--生成token-->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>

JwtUtil工具類

package com.hl.springsecurity01.util;
?
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
?
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
?
/*** JWT工具類*/
public class JwtUtil {//有效期為public static final Long JWT_TTL = 60 * 60 *1000L;// 60 * 60 *1000  一個小時//設置秘鑰明文public static final String JWT_KEY = "test";
?public static String getUUID(){String token = UUID.randomUUID().toString().replaceAll("-", "");return token;}
?/*** 生成jtw字符串* @param subject token中要存放的數據(json格式)* @return*/public static String createJWT(String subject) {JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 設置過期時間return builder.compact();}
?/*** 生成jtw字符串* @param subject token中要存放的數據(json格式)* @param ttlMillis token超時時間* @return*/public static String createJWT(String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 設置過期時間return builder.compact();}
?private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;SecretKey secretKey = generalKey();long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);if(ttlMillis==null){ttlMillis=JwtUtil.JWT_TTL;}long expMillis = nowMillis + ttlMillis;Date expDate = new Date(expMillis);return Jwts.builder().setId(uuid) ? ? ? ? ? ? ?//唯一的ID.setSubject(subject) ? // 主題  可以是JSON數據.setIssuer("sg") ? ? // 簽發者.setIssuedAt(now) ? ? ?// 簽發時間.signWith(signatureAlgorithm, secretKey) //使用HS256對稱加密算法簽名, 第二個參數為秘鑰.setExpiration(expDate);}
?/*** 創建token* @param id* @param subject* @param ttlMillis* @return*/public static String createJWT(String id, String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 設置過期時間return builder.compact();}
?
?/*** 生成加密后的秘鑰 secretKey* @return*/public static SecretKey generalKey() {byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}
?/*** 解析jwt** @param jwt* @return* @throws Exception*/public static Claims parseJWT(String jwt) throws Exception {SecretKey secretKey = generalKey();return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}
?/*** ? 用于測試*/public static void main(String[] args) throws Exception {
// ? ? ?  String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjYWM2ZDVhZi1mNjVlLTQ0MDAtYjcxMi0zYWEwOGIyOTIwYjQiLCJzdWIiOiJzZyIsImlzcyI6InNnIiwiaWF0IjoxNjM4MTA2NzEyLCJleHAiOjE2MzgxMTAzMTJ9.JVsSbkP94wuczb4QryQbAke3ysBDIL5ou8fWsbt_ebg";
// ? ? ?  Claims claims = parseJWT(token);
// ? ? ?  System.out.println(claims);String token = createJWT("1");String token1 = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJlM2UzMGE0ZjhhMGE0OTQ1ODNjMzZlZmNjMWQ3YzQ4YiIsInN1YiI6IjEiLCJpc3MiOiJzZyIsImlhdCI6MTc1MTUzMjI0MiwiZXhwIjoxNzUxNTM1ODQyfQ.ALfU833lUe1bCRlsAwcDd_mwD5j3sCtFCO3Ue1E-WWw";System.out.println(token);Claims claims = parseJWT(token1);System.out.println(claims);}
?
}
package com.hl.springsecurity01.service.impl;
?
import com.hl.springsecurity01.domain.R;
import com.hl.springsecurity01.security.LoginUser;
import com.hl.springsecurity01.service.LoginService;
import com.hl.springsecurity01.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
?
import javax.security.sasl.AuthenticationException;
?
@Service
public class LoginServiceImpl implements LoginService {@Autowiredprivate AuthenticationManager authenticationManager;@Overridepublic R login(String username, String password) throws AuthenticationException {UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username, password);//調用認證提供器的認證方法,進行用戶名,密碼認證Authentication authentication = authenticationManager.authenticate(token);//根據返回值判斷是否認證成功if(authentication == null){//認證失敗throw ?new AuthenticationException("用戶名或者密碼錯誤");}if(authentication.isAuthenticated()){//認證成功//獲取用戶身份 LoginUserLoginUser user = (LoginUser) authentication.getPrincipal();//獲取用戶idLong id = user.getSysUser().getId();//根據用戶id,生成tokenString token2 = JwtUtil.createJWT(id+"");//返回 code ,msg,tokenreturn R.ok(token2,"認證成功");}return null;}
}

?

 

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

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

相關文章

在 Ubuntu 22.04 上使用 Minikube 部署 Go 應用到 Kubernetes

文章目錄 環境說明目標步驟與問題解決1. 構建 Go 應用和 Docker 鏡像問題 1&#xff1a;Go 依賴下載卡住問題 2&#xff1a;Docker 鏡像拉取失敗 2. 設置 Minikube 集群安裝 Minikube問題 3&#xff1a;Minikube 啟動失敗問題 4&#xff1a;Minikube 鏡像拉取失敗 3. 部署 Kube…

Android Studio-Git的使用指南

一、git的基本使用流程 git clone 克隆遠程資源到本地目錄&#xff0c;作為工作目錄&#xff1b;然后在本地的克隆目錄上添加或修改文件&#xff1b;如果遠程修改了&#xff0c;需要同步遠程的內容&#xff0c;直接git pull就可以更新本地的文件&#xff1b;本地在修改之后&…

【github】想fork的項目變為私有副本

在 GitHub 上&#xff0c;所有的 fork 都會繼承其上游倉庫&#xff08;upstream&#xff09;的可見性&#xff08;visibility&#xff09;設置&#xff1a; 可見性繼承 如果你 fork 的原倉庫是 public&#xff0c;那么你的 fork 也必須是 public。如果原倉庫是 private&#xf…

微軟發布新一代存儲優化型虛擬機:Azure Laosv4、Lasv4 和 Lsv4 系列

微軟宣布&#xff0c;全新一代存儲優化型虛擬機——Azure Laosv4、Lasv4 和 Lsv4 系列已正式面世。 與前一代虛擬機系列相比&#xff0c;全新的 L 系列虛擬機實現了重大突破。它支持高達 23TB 的本地 NVMe SSD&#xff0c;在 CPU、網絡以及遠程存儲性能方面均有顯著提升。該系…

python調用pybind11導出的pyd,出現UnicodeDecodeError

python調用pybind11導出的pyd&#xff0c;出現UnicodeDecodeError 1. 問題描述 舉個例子&#xff0c;當有以下C代碼以及Pybind11的綁定代碼時&#xff0c;在python訪問包含中文的Name和Value會有UnicodeDecodeError的異常&#xff01; class VxUserProp{public:VxUserProp();…

MySQL別名在GROUP BY中的使用規則

-- 設置變量&#xff1a;SET earliest_date ... 用于定義并賦值一個用戶變量 earliest_date。 -- 用戶定義的變量必須以 符號開頭&#xff0c;例如 earliest_date。 -- 符號是MySQL中用戶變量的標識符&#xff0c;用于區分系統變量和用戶變量。 SET earliest_date (SELECT …

2025.7.4總結

感恩環節:感謝今日工作順利度過&#xff0c;明天終于能美美的睡個懶覺了。感謝這周有個美好的雙休。今日去實驗室參觀設備&#xff0c;感謝我的一個同事解答了我關于硬件設備與所做軟件業務之間的關系&#xff0c;通過控制器控制網元等相關設備&#xff0c;同時&#xff0c;雖然…

Prompt 精通之路(五)- 構建你的“AI 指令系統”:超越簡單提問的 CRISPE 與 APE 框架

&#x1f680; Prompt 精通之路&#xff1a;系列文章導航 第一篇&#xff1a;[本文] AI 時代的新語言&#xff1a;到底什么是 Prompt&#xff1f;為什么它如此重要&#xff1f;第二篇&#xff1a;告別廢話&#xff01;掌握這 4 個黃金法則&#xff0c;讓你的 Prompt 精準有效第…

#NFT藝術品哈希值唯一性與《民法典》“網絡虛擬財產”認定的沖突

首席數據官高鵬律師數字經濟團隊創作&#xff0c;AI輔助 一、當區塊鏈的「絕對唯一」遇上法律的「彈性空間」 每個NFT藝術品背后的哈希值&#xff0c;都像用數學密碼刻在區塊鏈上的指紋——世界上沒有任何兩個完全相同的編碼。這種由0和1構筑的「數字DNA」&#xff0c;被技術信…

【arXiv2025】計算機視覺|即插即用|LBMamba:革新視覺模型效率,性能炸裂

論文地址&#xff1a;https://arxiv.org/pdf/2506.15976 代碼地址&#xff1a;https://github.com/CiaoHe/bi-mamba 關注UP CV縫合怪&#xff0c;分享最計算機視覺新即插即用模塊&#xff0c;并提供配套的論文資料與代碼。 https://space.bilibili.com/473764881 摘要 Mamba…

【狂飆AGI】第7課:AGI-行業大模型(系列1)

目錄 &#xff08;一&#xff09;服裝史的GPT時刻&#xff08;二&#xff09;AI多學科診療系統&#xff08;三&#xff09;醫療大模型&#xff08;四&#xff09;生物醫藥大模型&#xff08;五&#xff09;教育大模型&#xff08;六&#xff09;心理大模型&#xff08;七&#…

(LeetCode 每日一題) 3307. 找出第 K 個字符 II (位運算、數學)

題目&#xff1a;3307. 找出第 K 個字符 II 思路&#xff1a;位運算&#xff0c;時間復雜度0(logk)。 當2^(i-1) <k 且 2^i>k &#xff0c;說明k在K2^i的右半段 &#xff0c;k和其前半段的某個字符有關系 即當k>K時&#xff0c;k是由k-K位置上的字符變化而來&#xf…

國產MCU學習Day4——CW32F030C8T6:獨立看門狗功能全解析

CW32F030C8T6 看門狗功能概述 CW32F030C8T6 是芯源半導體&#xff08;WCH&#xff09;推出的 Cortex-M0 內核微控制器&#xff0c;內置獨立看門狗&#xff08;IWDG&#xff09;和窗口看門狗&#xff08;WWDG&#xff09;&#xff0c;用于檢測和恢復系統異常狀態。 一.獨立看門…

SAP升級過程中如何確保數據安全?

目錄 升級過程中可能遇到的數據風險 升級前的準備工作 升級過程中的保護措施 升級后的驗證工作 在數字化轉型浪潮中&#xff0c;SAP系統作為企業核心業務運營的系統&#xff0c;其升級過程不僅關乎技術架構的革新&#xff0c;更直接關系到企業最寶貴的資產——數據安全。一…

Vue 3 + Element Plus 常見開發問題與解決方案手冊

&#x1f31f;Vue 3 Element Plus 常見開發問題與解決方案手冊 &#x1f9e0; 本文整理了常見但容易混淆的幾個 Vue 3 前端開發問題&#xff0c;包括插槽、原型鏈、響應式數據處理、v-model 報錯、樣式陰影控制等&#xff0c;建議收藏學習&#xff01; &#x1f4cc;一、動態插…

Spring Boot + 本地部署大模型實現:安全性與可靠性保障

在將大語言模型集成到 Spring Boot 應用中時&#xff0c;安全性和可靠性是兩個關鍵因素。本地部署的大模型雖然提供了強大的功能&#xff0c;但也可能帶來一些安全風險&#xff0c;如數據泄露、模型被惡意利用等。本文將介紹如何在 Spring Boot 應用中保障本地部署大模型的安全…

Zookeeper 客戶端 .net訪問框架 ZookeeperNetEx項目開發編譯

一、項目簡介 ZooKeeperNetEx 項目是一個針對.NET開發的異步客戶端庫&#xff0c;旨在為開發者提供高效且可靠的分布式協調服務。? 該項目完全基于任務異步編程&#xff0c;兼容.NET 4.61及以上版本&#xff0c;包括.NET Core。ZooKeeperNetEx嚴格遵循官方Java客戶端的邏輯&am…

【學習筆記】因果推理導論第2課

因果推理導論第2課 因果推斷假設 前言一、假設1、 Ignorability / Exchangeability2、條件可交換 二、估計 前言 第一節課通過一些例子說明了為什么要做因果推斷,以及通過控制混雜因素計算因果效應;這一節課將圍繞為何控制混雜因素計算因果效應這一方法成立,講述其涉及到的一些…

VASP 教程:VASP 機器學習力場微調

機器學習力場&#xff08;Machine-Learned Force Fields, MLFFs&#xff09;作為一種新興的計算方法&#xff0c;已在第一性原理分子動力學&#xff08;Ab Initio Molecular Dynamics, AIMD&#xff09;模擬中展現出獨特優勢&#xff08;參見 VASP Wiki&#xff1a;Category:Ma…