亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

Spring Boot系統(tǒng)屬性解密:屬性源優(yōu)先級(jí)與解密層實(shí)踐

Spring Boot系統(tǒng)屬性解密:屬性源優(yōu)先級(jí)與解密層實(shí)踐 寫(xiě)在最前面系統(tǒng)屬性這層?xùn)|西平時(shí)誰(shuí)都不會(huì)特意去看它可一旦里面塞了加密值問(wèn)題就會(huì)變得很別扭——配置文件里寫(xiě)明文的那套經(jīng)驗(yàn)全失效了。前段時(shí)間我接手一個(gè)項(xiàng)目運(yùn)維在啟動(dòng)腳本里用-D傳了一串加密后的數(shù)據(jù)庫(kù)口令結(jié)果 Spring 容器起來(lái)之后拿到的還是密文連接池直接報(bào)認(rèn)證失敗。后來(lái)折騰了大半天才把整條鏈路捋順?biāo)餍园堰^(guò)程整理一下從屬性源的優(yōu)先級(jí)、解密層的插入位置到幾個(gè)幾乎必踩的坑一次說(shuō)清楚。這篇內(nèi)容適合已經(jīng)寫(xiě)過(guò) Spring Boot、但沒(méi)系統(tǒng)研究過(guò)屬性加載鏈路的朋友也適合正在給老項(xiàng)目補(bǔ)安全加固的同學(xué)照著做。1. 系統(tǒng)屬性在 Spring Boot 屬性鏈路里的真實(shí)位置1.1 一次 setProperty 之后值究竟被誰(shuí)讀走了System.setProperty(key, value)寫(xiě)進(jìn)去的東西本質(zhì)上是 JVM 全局的一張Properties表底層是Hashtable進(jìn)程內(nèi)所有線程共享生命周期跟 JVM 一致。Spring Boot 在啟動(dòng)早期會(huì)把這張表包裝成一個(gè)PropertySource名字固定叫systemProperties塞進(jìn)MutablePropertySources里。你后面寫(xiě)的Value(${xxx})、ConfigurationProperties、environment.getProperty(xxx)最終都會(huì)順著這條鏈一路找下來(lái)。關(guān)鍵在于包裝這兩個(gè)字。Spring 拿到的不是你原始那張Properties而是一個(gè)只讀視圖getProperty每次調(diào)用都會(huì)實(shí)時(shí)去問(wèn) JVM。也就是說(shuō)你在容器啟動(dòng)之后調(diào)System.setPropertyenvironment.getProperty是能立刻讀到新值的。但已經(jīng)完成綁定的 Bean、已經(jīng)解析完的占位符不會(huì)自動(dòng)刷新這一點(diǎn)后面會(huì)專(zhuān)門(mén)講。理解這一層很重要。很多人以為系統(tǒng)屬性就是環(huán)境變量的小名其實(shí)兩者在 Spring Boot 里是兩個(gè)獨(dú)立的屬性源名字分別是systemProperties和systemEnvironment優(yōu)先級(jí)也不一樣系統(tǒng)屬性排在環(huán)境變量前面。這個(gè)順序直接決定了你的加密值會(huì)不會(huì)被別的配置蓋掉。1.2 屬性源優(yōu)先級(jí)決定了你的加密值會(huì)被誰(shuí)覆蓋Spring Boot 的屬性源是有明確順序的靠前的優(yōu)先。下面這張表是我實(shí)際排查時(shí)整理的只列了日常最常撞上的幾層優(yōu)先級(jí)屬性源典型來(lái)源1命令行參數(shù)--app.secret.xxx...2SPRING_APPLICATION_JSON環(huán)境變量里的 JSON3Servlet 相關(guān)參數(shù)少見(jiàn)4JNDI少見(jiàn)5systemProperties-Dkeyvalue、System.setProperty6systemEnvironment操作系統(tǒng)環(huán)境變量7random.*隨機(jī)值8外部配置文件jar 同級(jí)的application.yml9jar 內(nèi)配置文件classpath:/application.yml10PropertySource代碼里聲明的11默認(rèn)值SpringApplication.setDefaultProperties從這個(gè)順序能看出來(lái)兩件事。第一系統(tǒng)屬性天然壓過(guò)application.yml你在配置文件里寫(xiě)同名 key 是蓋不住它的這是好事方便運(yùn)維用啟動(dòng)參數(shù)覆蓋。第二命令行參數(shù)又壓過(guò)系統(tǒng)屬性所以如果有人用--app.secret.xxx明文啟動(dòng)你的加密邏輯就白做了——這一點(diǎn)在做兜底校驗(yàn)時(shí)值得加一條判斷。還有個(gè)容易忽略的細(xì)節(jié)Profile 相關(guān)的配置文件application-prod.yml排在同名非 Profile 文件前面但它們整體都排在系統(tǒng)屬性之后。所以只要 key 對(duì)得上系統(tǒng)屬性永遠(yuǎn)贏。這也解釋了為什么有些團(tuán)隊(duì)喜歡把所有敏感配置都通過(guò)-D注入而不是寫(xiě)進(jìn)配置文件。1.3 三個(gè)必須提前想清楚的時(shí)間點(diǎn)做加解密之前有三個(gè)時(shí)間點(diǎn)必須先確認(rèn)否則代碼寫(xiě)得再漂亮也不生效。設(shè)置時(shí)間點(diǎn)System.setProperty是在SpringApplication.run()之前、之中還是之后調(diào)的之前最穩(wěn)Spring 能完整讀到之中取決于具體階段之后只能保證environment.getProperty讀到已經(jīng)綁定的 Bean 拿不到。解密層插入時(shí)間點(diǎn)解密邏輯必須插在所有讀取動(dòng)作之前。Spring Boot 提供了EnvironmentPostProcessor、ApplicationContextInitializer、BeanFactoryPostProcessor三個(gè)常見(jiàn)鉤子它們的執(zhí)行階段完全不同選錯(cuò)了就會(huì)出現(xiàn)配置文件里的能解密、系統(tǒng)屬性里的不能這種詭異現(xiàn)象。占位符解析時(shí)間點(diǎn)Value的占位符由PropertySourcesPlaceholderConfigurer在 Bean 實(shí)例化階段解析晚于環(huán)境準(zhǔn)備。所以只要在環(huán)境準(zhǔn)備階段把屬性源包一層Value就能拿到解密值。我見(jiàn)過(guò)最典型的翻車(chē)方式是在某個(gè)PostConstruct方法里調(diào)System.setProperty塞密鑰然后指望Value能讀到。結(jié)果 Bean 初始化順序稍微一變讀到的就是 null。這類(lèi)問(wèn)題排查起來(lái)極其費(fèi)勁因?yàn)椴粓?bào)錯(cuò)只是值不對(duì)。2. 方案選型三種落地路徑的邊界與取舍2.1 路徑一在設(shè)置源頭就地解密最直接的做法是在main方法里、SpringApplication.run之前把系統(tǒng)屬性里的加密值解密后重新setProperty回去。代碼大概長(zhǎng)這樣public static void main(String[] args) { decryptSystemProperties(); SpringApplication.run(DemoApplication.class, args); } private static void decryptSystemProperties() { Properties props System.getProperties(); for (String name : props.stringPropertyNames()) { String raw props.getProperty(name); if (raw ! null raw.startsWith(enc:v1:)) { System.setProperty(name, AesGcmCipher.decrypt(raw)); } } }這段代碼的優(yōu)勢(shì)是簡(jiǎn)單、無(wú)框架依賴(lài)、執(zhí)行時(shí)機(jī)絕對(duì)早。缺點(diǎn)是它會(huì)把解密后的明文回寫(xiě)到 JVM 系統(tǒng)屬性里任何能讀System.getProperties()的代碼包括某些診斷工具都能看到明文。另外它只處理系統(tǒng)屬性配置文件里的加密值管不著如果你的項(xiàng)目?jī)煞N來(lái)源都有就得維護(hù)兩套邏輯。這條路徑適合什么場(chǎng)景我總結(jié)下來(lái)是項(xiàng)目規(guī)模小、敏感配置全部走啟動(dòng)參數(shù)、團(tuán)隊(duì)不想引入額外依賴(lài)。反過(guò)來(lái)說(shuō)如果配置文件里也有加密值或者需要按環(huán)境切換密鑰版本就別選它了后期會(huì)很難受。2.2 路徑二用 Jasypt 兜住所有屬性源Jasypt 的 Spring Boot Starter 是這類(lèi)需求里出場(chǎng)率最高的方案。它的思路是提供一個(gè)EncryptablePropertySourceConverter在容器 refresh 之前把所有PropertySource逐個(gè)包一層讀取時(shí)遇到ENC(...)包裹的值就解密。配置成本很低加個(gè)依賴(lài)、配個(gè)密鑰就行。它對(duì)系統(tǒng)屬性同樣有效因?yàn)閟ystemProperties也在被包裝的名單里。我實(shí)測(cè)過(guò)-Dapp.secret.db-passwordENC(xxx)這種寫(xiě)法Spring 讀出來(lái)是解密后的值。具體流程是EnableEncryptablePropertiesBeanFactoryPostProcessor在BeanFactory后置處理階段觸發(fā)屬性源轉(zhuǎn)換此時(shí)Environment已經(jīng)準(zhǔn)備好了所以Value和ConfigurationProperties都能拿到明文。但 Jasypt 有幾個(gè)需要提前知道的邊界。它的密鑰本身要通過(guò)jasypt.encryptor.password配置這個(gè)值如果也從系統(tǒng)屬性來(lái)就得保證包裝之前已經(jīng)就位它的默認(rèn)算法是PBEWITHHMACSHA512ANDAES_256需要 BouncyCastle 支持JDK 版本低的項(xiàng)目要額外引依賴(lài)它對(duì)值的前綴匹配是ENC(開(kāi)頭、)結(jié)尾如果你的密文里恰好包含這個(gè)模式會(huì)被二次解密產(chǎn)生莫名其妙的錯(cuò)誤。還有一個(gè)隱蔽的問(wèn)題Jasypt 的包裝發(fā)生在BeanFactory后置處理階段比EnvironmentPostProcessor晚。如果某個(gè)EnvironmentPostProcessor在更早的階段就要讀加密屬性比如決定加載哪個(gè)配置文件那時(shí)候還是密文。這種情況雖然少見(jiàn)但一旦碰上就很難定位。2.3 路徑三自己包裝 PropertySource第三種是自己寫(xiě)一個(gè)EnvironmentPostProcessor在環(huán)境準(zhǔn)備階段遍歷所有屬性源把需要處理的那幾個(gè)替換成解密包裝器。這種做法可控性最高能精確控制包裝哪些源、能自定義密文前綴、能支持密鑰版本、能在解密失敗時(shí)給出明確日志。代價(jià)是要自己寫(xiě)代碼大概一百多行包括一個(gè)加解密工具類(lèi)、一個(gè)PropertySource包裝器、一個(gè)EnvironmentPostProcessor實(shí)現(xiàn)和注冊(cè)文件。聽(tīng)著多其實(shí)拆開(kāi)看每一塊都不復(fù)雜后面第三章會(huì)給出完整實(shí)現(xiàn)。這條路徑適合對(duì)安全有明確要求、或者需要和現(xiàn)有密鑰管理流程對(duì)接的項(xiàng)目。比如你的密鑰來(lái)自某個(gè)配置中心需要在啟動(dòng)時(shí)拉取那用自定義處理器就比 Jasypt 靈活得多。2.4 三條路徑的橫向?qū)Ρ染S度源頭就地解密Jasypt Starter自定義 PropertySource實(shí)現(xiàn)成本極低低中覆蓋配置文件否是是覆蓋系統(tǒng)屬性是是是密鑰版本支持需自己實(shí)現(xiàn)弱強(qiáng)明文殘留會(huì)回寫(xiě)系統(tǒng)屬性不回寫(xiě)不回寫(xiě)執(zhí)行時(shí)機(jī)最早較晚可調(diào)排查難度低中中選型上我的建議是新項(xiàng)目、配置來(lái)源統(tǒng)一走啟動(dòng)參數(shù)的選路徑一夠用且省事已經(jīng)在用 Spring Boot 且只想快速補(bǔ)上的選 Jasypt對(duì)密鑰輪換、審計(jì)日志有要求的老老實(shí)實(shí)寫(xiě)自定義處理器。三條路徑也可以混用比如配置文件走 Jasypt、系統(tǒng)屬性走源頭解密但混用會(huì)讓排查變復(fù)雜不建議。3. 手寫(xiě)一個(gè)能識(shí)別系統(tǒng)屬性的解密層3.1 先寫(xiě)一個(gè)靠譜的 AES-GCM 工具類(lèi)算法選擇上我不推薦再用PBEWithMD5AndDES這個(gè)在 Jasypt 老版本里是默認(rèn)值強(qiáng)度已經(jīng)不夠看了。直接上AES/GCM/NoPadding帶認(rèn)證標(biāo)簽?zāi)芡瑫r(shí)防篡改。public final class AesGcmCipher { private static final String TRANSFORMATION AES/GCM/NoPadding; private static final int IV_LENGTH 12; private static final int TAG_LENGTH_BIT 128; private static final String PREFIX enc:v1:; private static final SecureRandom RANDOM new SecureRandom(); private AesGcmCipher() { } public static String encrypt(String plain, SecretKey key) throws Exception { byte[] iv new byte[IV_LENGTH]; RANDOM.nextBytes(iv); Cipher cipher Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(TAG_LENGTH_BIT, iv)); byte[] cipherText cipher.doFinal(plain.getBytes(StandardCharsets.UTF_8)); ByteBuffer buffer ByteBuffer.allocate(iv.length cipherText.length); buffer.put(iv).put(cipherText); return PREFIX Base64.getUrlEncoder().withoutPadding() .encodeToString(buffer.array()); } public static String decrypt(String encoded, SecretKey key) throws Exception { if (encoded null || !encoded.startsWith(PREFIX)) { return encoded; } byte[] all Base64.getUrlDecoder() .decode(encoded.substring(PREFIX.length())); ByteBuffer buffer ByteBuffer.wrap(all); byte[] iv new byte[IV_LENGTH]; buffer.get(iv); byte[] cipherText new byte[buffer.remaining()]; buffer.get(cipherText); Cipher cipher Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(TAG_LENGTH_BIT, iv)); return new String(cipher.doFinal(cipherText), StandardCharsets.UTF_8); } }幾個(gè)點(diǎn)值得說(shuō)明。Base64.getUrlEncoder()用的是 URL 安全字符集把和/換成了-和_這樣密文丟進(jìn)啟動(dòng)腳本、環(huán)境變量、URL 查詢(xún)串都不會(huì)被轉(zhuǎn)義。我就吃過(guò)這個(gè)虧標(biāo)準(zhǔn) Base64 里的在某個(gè) CI 平臺(tái)的變量傳遞環(huán)節(jié)被轉(zhuǎn)成了空格解密直接報(bào)填充異常查了兩小時(shí)。前綴enc:v1:有兩個(gè)作用一是避免誤傷普通值二是為密鑰輪換預(yù)留版本號(hào)。以后換密鑰就上enc:v2:解密時(shí)按版本選對(duì)應(yīng)密鑰老數(shù)據(jù)不用一次性全刷。IV 長(zhǎng)度選 12 字節(jié)是 GCM 的推薦值性能最好。認(rèn)證標(biāo)簽 128 位是標(biāo)準(zhǔn)配置別為了省幾個(gè)字節(jié)改成 96 位收益微乎其微。3.2 包裝屬性源時(shí)的關(guān)鍵選擇Enumerable 不能丟寫(xiě)包裝器的時(shí)候有個(gè)坑必須提前避開(kāi)如果你把一個(gè)EnumerablePropertySource包裝成普通的PropertySourcegetPropertyNames()就返回不了了。后果是ConfigurationProperties的寬松綁定失效、Environment.getProperty的下標(biāo)查找失效、actuator 的/env端點(diǎn)看不到這些屬性。所以包裝類(lèi)要按源的類(lèi)型分兩種實(shí)現(xiàn)或者直接寫(xiě)一個(gè)繼承EnumerablePropertySource的版本public class DecryptingPropertySource extends EnumerablePropertySourcePropertySource? { private final SecretResolver resolver; private final PredicateString keyFilter; public DecryptingPropertySource(String name, PropertySource? source, SecretResolver resolver, PredicateString keyFilter) { super(name, source); this.resolver resolver; this.keyFilter keyFilter; } Override public Object getProperty(String name) { Object value source.getProperty(name); if (value instanceof String str keyFilter.test(name)) { return resolver.resolve(str); } return value; } Override public String[] getPropertyNames() { if (source instanceof EnumerablePropertySource? enumerable) { return enumerable.getPropertyNames(); } return new String[0]; } Override public boolean containsProperty(String name) { return source.containsProperty(name); } }SecretResolver負(fù)責(zé)真正的解密內(nèi)部加一層ConcurrentHashMap緩存同一個(gè)密文只解一次。啟動(dòng)階段屬性可能被讀幾百次緩存能省下不少開(kāi)銷(xiāo)。public class SecretResolver { private final MapString, SecretKey keys; private final MapString, String cache new ConcurrentHashMap(); public SecretResolver(MapString, SecretKey keys) { this.keys keys; } public String resolve(String raw) { if (raw null || !raw.startsWith(enc:)) { return raw; } return cache.computeIfAbsent(raw, this::doResolve); } private String doResolve(String raw) { String version raw.substring(4, raw.indexOf(:, 4)); SecretKey key keys.get(version); if (key null) { throw new IllegalStateException(未找到密鑰版本: version); } try { return AesGcmCipher.decrypt(raw, key); } catch (Exception e) { throw new IllegalStateException(屬性解密失敗請(qǐng)檢查密鑰與密文是否匹配, e); } } }注意異常信息里不要帶明文也不要帶完整密文。帶上密鑰版本號(hào)就夠了生產(chǎn)日志里泄露密文等于泄露了一半信息。3.3 EnvironmentPostProcessor 的注冊(cè)和生效時(shí)機(jī)處理器本身很簡(jiǎn)單核心是遍歷屬性源、替換、保持順序public class DecryptingEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { SecretResolver resolver SecretKeyLoader.load(environment); MutablePropertySources sources environment.getPropertySources(); ListString names new ArrayList(); for (PropertySource? ps : sources) { names.add(ps.getName()); } PredicateString filter name - name.startsWith(app.secret.) || name.startsWith(spring.datasource.); for (String name : names) { PropertySource? original sources.get(name); if (original null || original instanceof DecryptingPropertySource) { continue; } sources.replace(name, new DecryptingPropertySource(name, original, resolver, filter)); } } Override public int getOrder() { return Ordered.LOWEST_PRECEDENCE; } }getOrder()返回LOWEST_PRECEDENCE是有講究的。Spring Boot 2.4 之后配置文件通過(guò)ConfigDataEnvironmentPostProcessor加載它的 order 很靠前。如果你的處理器 order 太小執(zhí)行時(shí)application.yml還沒(méi)進(jìn)屬性源列表就漏掉了。設(shè)成最低優(yōu)先級(jí)能保證所有配置文件都加載完之后再統(tǒng)一包裝。迭代時(shí)要先收集名字快照不能在遍歷MutablePropertySources的同時(shí)調(diào)用replace會(huì)拋ConcurrentModificationException。這個(gè)坑我在第一次寫(xiě)的時(shí)候踩過(guò)啟動(dòng)直接掛掉。SecretKeyLoader負(fù)責(zé)從環(huán)境變量或外部密鑰文件讀取主密鑰。這里要強(qiáng)調(diào)一點(diǎn)密鑰絕不能和密文放在同一個(gè)屬性源里。密文在啟動(dòng)參數(shù)、密鑰在環(huán)境變量這是最低要求再好一點(diǎn)是密鑰從掛載的 secret 文件讀只有特定用戶(hù)可讀。3.4 Spring Boot 3.x 的注冊(cè)差異與兼容寫(xiě)法Spring Boot 2.x 的注冊(cè)文件是META-INF/spring.factoriesorg.springframework.boot.env.EnvironmentPostProcessor\ com.example.config.DecryptingEnvironmentPostProcessorSpring Boot 3.x 改成了META-INF/spring/org.springframework.boot.env.EnvironmentPostProcessor.imports內(nèi)容直接寫(xiě)類(lèi)名一行一個(gè)com.example.config.DecryptingEnvironmentPostProcessor如果項(xiàng)目要同時(shí)兼容 2.x 和 3.x兩個(gè)文件都放內(nèi)容各寫(xiě)各的格式。Spring Boot 3 會(huì)優(yōu)先讀 imports 文件找不到再回退到spring.factories放兩份不會(huì)沖突。另外 3.x 對(duì)spring.factories的很多擴(kuò)展點(diǎn)都做了遷移如果你還依賴(lài)其他擴(kuò)展點(diǎn)建議一次性檢查一遍別只改了這一處。3.5 讓 Value、ConfigurationProperties、Environment 三條讀取路徑都走通包裝完之后要驗(yàn)證三條路徑是不是都拿到明文。Value走的是PropertySourcesPlaceholderConfigurer它讀的是Environment的propertySources包裝后的源直接生效沒(méi)問(wèn)題。ConfigurationProperties走的是ConfigurationPropertySources這是一個(gè)在環(huán)境準(zhǔn)備末尾 attach 上去的視圖。因?yàn)樗?attach 時(shí)持有的是MutablePropertySources的引用遍歷是動(dòng)態(tài)的所以后包裝也生效。但要注意 attach 的時(shí)機(jī)在你的處理器之后——Ordered.LOWEST_PRECEDENCE恰好能保證這一點(diǎn)。environment.getProperty(key)直接遍歷propertySources同樣生效。有一個(gè)例外是PropertySource注解引入的屬性源。它的加載時(shí)機(jī)在ConfigurationClassPostProcessor階段晚于EnvironmentPostProcessor所以不會(huì)被包裝到。如果這個(gè)源里也有加密值需要單獨(dú)處理比如在BeanFactoryPostProcessor里再包一次或者干脆把加密值挪到application.yml里。4. 從加密一個(gè)值到項(xiàng)目跑起來(lái)的完整實(shí)操4.1 生成 256 位密鑰并加密目標(biāo)值密鑰生成用 KeyGenerator 就行別自己拼字節(jié)數(shù)組KeyGenerator generator KeyGenerator.getInstance(AES); generator.init(256, new SecureRandom()); SecretKey key generator.generateKey(); String base64Key Base64.getEncoder().encodeToString(key.getEncoded()); System.out.println(主密鑰: base64Key);256 位 AES 在 JDK 8u161 之后默認(rèn)就支持不需要額外裝策略文件。如果你的運(yùn)行環(huán)境是很老的 JDK 8 小版本跑的時(shí)候會(huì)拋InvalidKeyException: Illegal key size那就得升級(jí) JDK 或者裝無(wú)限強(qiáng)度策略文件。這個(gè)報(bào)錯(cuò)信息很明確一看就知道原因。拿到密鑰之后加密目標(biāo)值SecretKey key new SecretKeySpec(Base64.getDecoder().decode(base64Key), AES); String encrypted AesGcmCipher.encrypt(Pssw0rd-2024, key); System.out.println(encrypted);輸出大概長(zhǎng)這樣enc:v1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx長(zhǎng)度 60 到 80 個(gè)字符之間具體取決于明文長(zhǎng)度。4.2 啟動(dòng)腳本里注入系統(tǒng)屬性的幾種寫(xiě)法Linux 下用-D傳參java -Dapp.secret.db-passwordenc:v1:xxxxx \ -Dspring.profiles.activeprod \ -jar demo.jar注意值里的特殊字符。雖然用了 URL 安全 Base64理論上只有字母數(shù)字和-_但前綴里有個(gè)冒號(hào)在 YAML 或某些腳本里冒號(hào)后面跟空格會(huì)被當(dāng)成分隔符。所以建議整個(gè)值用單引號(hào)包起來(lái)別圖省事。容器環(huán)境里更推薦用環(huán)境變量避免命令行參數(shù)被ps看到env: - name: APP_SECRET_DB_PASSWORD valueFrom: secretKeyRef: name: app-secret key: db-password環(huán)境變量名APP_SECRET_DB_PASSWORD會(huì)被 Spring Boot 的寬松綁定映射成app.secret.db-password所以你的代碼里照常寫(xiě)Value(${app.secret.db-password})就行。這個(gè)映射規(guī)則是全大寫(xiě)、下劃線轉(zhuǎn)點(diǎn)、點(diǎn)轉(zhuǎn)短橫線。搞清楚這條規(guī)則很多環(huán)境變量明明設(shè)了卻讀不到的問(wèn)題就迎刃而解了。如果值里必須帶加密前綴環(huán)境變量這種方式反而更安全因?yàn)椴恍枰?jīng)過(guò) shell 解析。4.3 寫(xiě)個(gè)測(cè)試驗(yàn)證解密鏈路真的生效測(cè)試這塊有個(gè)坑SpringBootTest會(huì)緩存ApplicationContext如果第一個(gè)測(cè)試類(lèi)啟動(dòng)時(shí)系統(tǒng)屬性還沒(méi)設(shè)后面再設(shè)也不會(huì)重新加載。所以要么用DirtiesContext要么在BeforeAll里設(shè)置并確保測(cè)試類(lèi)順序。SpringBootTest DirtiesContext(classMode DirtiesContext.ClassMode.AFTER_CLASS) class SecretPropertyTest { static final String KEY 測(cè)試用密鑰的Base64; BeforeAll static void setUp() throws Exception { SecretKey key new SecretKeySpec(Base64.getDecoder().decode(KEY), AES); System.setProperty(app.secret.db-password, AesGcmCipher.encrypt(Pssw0rd-2024, key)); System.setProperty(APP_SECRET_KEY, KEY); } AfterAll static void tearDown() { System.clearProperty(app.secret.db-password); System.clearProperty(APP_SECRET_KEY); } Value(${app.secret.db-password}) String dbPassword; Autowired Environment environment; Test void 系統(tǒng)屬性應(yīng)被解密讀取() { assertThat(dbPassword).isEqualTo(Pssw0rd-2024); assertThat(environment.getProperty(app.secret.db-password)) .isEqualTo(Pssw0rd-2024); } }AfterAll里清理系統(tǒng)屬性這一步別省。系統(tǒng)屬性是 JVM 級(jí)別的測(cè)試跑完不清理會(huì)影響同一個(gè) JVM 里的其他測(cè)試類(lèi)癥狀是單跑通過(guò)、全跑失敗特別難查。4.4 長(zhǎng)度、性能與緩存的實(shí)際測(cè)算密文長(zhǎng)度可以精確算出來(lái)。明文n字節(jié)GCM 加密后是n 16字節(jié)認(rèn)證標(biāo)簽加上 12 字節(jié) IV總共n 28字節(jié)。Base64 URL 無(wú)填充編碼后的長(zhǎng)度是ceil((n 28) * 4 / 3)再減去填充再加上 7 個(gè)字符的前綴。拿一個(gè) 12 字符的口令舉例12 28 40字節(jié)Base64 后約 54 字符加前綴總共 61 字符。這個(gè)長(zhǎng)度對(duì)啟動(dòng)參數(shù)和環(huán)境變量來(lái)說(shuō)毫無(wú)壓力。性能方面AES-GCM 在現(xiàn)代 CPU 上有硬件加速指令單次加解密在微秒級(jí)。真正影響啟動(dòng)時(shí)間的是屬性被讀取的次數(shù)——一個(gè)中等規(guī)模的應(yīng)用啟動(dòng)時(shí)屬性讀取可能上萬(wàn)次。所以緩存是必須的用ConcurrentHashMap以密文為 key 緩存明文命中率接近 100%。我實(shí)測(cè)過(guò)一個(gè)有 8 個(gè)加密屬性的項(xiàng)目加了緩存之后解密耗時(shí)從 40 毫秒降到 3 毫秒以?xún)?nèi)。要提醒一句緩存里存的是明文內(nèi)存 dump 能看到。如果對(duì)內(nèi)存安全有極高要求可以考慮用char[]并在用完后清零但這會(huì)把代碼復(fù)雜度拉高不少一般業(yè)務(wù)系統(tǒng)不必做到這個(gè)程度。5. 踩坑實(shí)錄那些配置看著對(duì)但就是不生效的情況5.1 值被配置文件覆蓋的排查順序最常見(jiàn)的問(wèn)題是系統(tǒng)屬性設(shè)了但讀出來(lái)還是配置文件里的值。排查順序我一般是這樣的第一步看 key 是否完全一致。系統(tǒng)屬性里的點(diǎn)號(hào)、短橫線、大小寫(xiě)都有講究。app.secret.dbPassword和app.secret.db-password在寬松綁定下是同一個(gè)但在environment.getProperty里是兩個(gè)不同的 key。用Value時(shí)尤其容易搞混。第二步看屬性源順序有沒(méi)有被人為改過(guò)。有些項(xiàng)目啟動(dòng)時(shí)會(huì)調(diào)用environment.getPropertySources().addFirst(...)塞自定義源把系統(tǒng)屬性擠下去了。這種情況在引入了某些配置中心客戶(hù)端的項(xiàng)目里很常見(jiàn)。第三步看是不是加密前綴沒(méi)匹配上。比如你的密文是ENC(xxx)格式但處理器只認(rèn)enc:v1:那就原樣返回了原始字符串看著像沒(méi)解密。第四步看處理器有沒(méi)有真的被注冊(cè)。spring.factories里類(lèi)名寫(xiě)錯(cuò)一個(gè)字母就靜默不加載不報(bào)任何錯(cuò)??梢栽谔幚砥骼锎蛞恍?info 日志啟動(dòng)時(shí)確認(rèn)一下。5.2 解密異常與亂碼的定位方法解密報(bào)錯(cuò)無(wú)非幾類(lèi)。AEADBadTagException說(shuō)明密鑰不對(duì)或者密文被改過(guò)這是 GCM 的認(rèn)證失敗屬于最明確的一類(lèi)。IllegalBlockSizeException通常是密文被截?cái)啾热鐐鬏斶^(guò)程中丟了字符。IllegalArgumentException: Illegal base64 character說(shuō)明 Base64 解碼失敗基本可以斷定是特殊字符被轉(zhuǎn)義了。亂碼問(wèn)題多數(shù)出在編碼上。加密時(shí)用 UTF-8 取字節(jié)解密時(shí)也必須用 UTF-8 還原中間任何一步用了平臺(tái)默認(rèn)編碼都可能出問(wèn)題。特別是在 Windows 上開(kāi)發(fā)、Linux 上部署的場(chǎng)景默認(rèn)編碼不一樣很容易踩。還有一種隱蔽情況屬性值本身就是空字符串。System.setProperty(key, )設(shè)進(jìn)去之后environment.getProperty返回的是空串而不是 null某些框架會(huì)把空串當(dāng)成未配置處理走了默認(rèn)值分支。如果加密后的值恰好解出空串行為會(huì)很怪。建議在解密之后加一句判空把空串轉(zhuǎn)成 null 或者直接拋異常。5.3 常見(jiàn)問(wèn)題速查表現(xiàn)象可能原因處理方式讀到的是密文原文處理器未注冊(cè)或 order 太靠前檢查注冊(cè)文件order 設(shè) LOWEST_PRECEDENCE讀到的是配置文件的值屬性源被 addFirst 覆蓋檢查是否有自定義源插到最前面啟動(dòng)報(bào) InvalidKeyExceptionJDK 版本低不支持 256 位升級(jí) JDK 或裝無(wú)限強(qiáng)度策略報(bào) AEADBadTagException密鑰不匹配或密文損壞核對(duì)密鑰版本檢查傳輸過(guò)程報(bào) Illegal base64 character密文中特殊字符被轉(zhuǎn)義改用 URL 安全 Base64ConfigurationProperties 綁不上包裝時(shí)丟了 Enumerable包裝類(lèi)繼承 EnumerablePropertySource測(cè)試單跑通過(guò)全跑失敗系統(tǒng)屬性污染AfterAll 里清理系統(tǒng)屬性環(huán)境變量設(shè)了但讀不到命名映射規(guī)則不匹配全大寫(xiě)、下劃線分詞5.4 密鑰管理和日志里的安全紅線有幾個(gè)紅線是必須守住的。密鑰不能出現(xiàn)在代碼倉(cāng)庫(kù)里包括測(cè)試代碼。測(cè)試用的密鑰要單獨(dú)生成只用于測(cè)試環(huán)境而且要明確標(biāo)注僅測(cè)試使用。密鑰不能和密文在同一個(gè)屬性源。如果兩部分都在application.yml里那加密等于沒(méi)做任何一個(gè)能看配置文件的人都能解密。日志里不能打印解密后的值。很多框架在 debug 級(jí)別會(huì)打印屬性綁定的過(guò)程如果你的屬性名比較敏感比如帶password要確認(rèn)這些日志不會(huì)上線。異常堆棧里不能帶明文。Cipher.doFinal拋異常時(shí)不會(huì)帶明文但如果你自己包裝異常時(shí)把原值拼進(jìn) message那就漏了。前面給的SecretResolver里我只帶了密鑰版本就是這個(gè)考慮。還有一點(diǎn)容易被忽略actuator 的/env和/configprops端點(diǎn)默認(rèn)會(huì)做脫敏脫敏規(guī)則是匹配password、secret、key、token這類(lèi)關(guān)鍵詞。如果你的屬性名叫app.datasource.credential不在這份名單里就會(huì)被原樣展示。這個(gè)名單可以自定義但更穩(wěn)妥的做法是直接限制這些端點(diǎn)的訪問(wèn)權(quán)限。6. 上線前的加固清單6.1 actuator 端點(diǎn)的脫敏處理Spring Boot 的脫敏靠SanitizingFunction實(shí)現(xiàn)2.6 之后可以自定義。默認(rèn)規(guī)則只覆蓋常見(jiàn)關(guān)鍵詞業(yè)務(wù)自定義的屬性名很容易漏。Bean public SanitizingFunction customSanitizer() { return property - { String name property.getName().toLowerCase(); if (name.contains(credential) || name.contains(passwd) || name.contains(private)) { return property.withValue(******); } return property; }; }這段代碼注冊(cè)到容器后/env端點(diǎn)里匹配到的值都會(huì)顯示成星號(hào)。注意這只是展示層面的保護(hù)屬性值在內(nèi)存里仍然是明文別把它當(dāng)成加密手段。更徹底的做法是把 actuator 端點(diǎn)限制在內(nèi)網(wǎng)訪問(wèn)或者干脆在生產(chǎn)環(huán)境只暴露health和info。配置項(xiàng)management.endpoints.web.exposure.include設(shè)成health,info就夠用了。6.2 密鑰輪換與多版本密鑰的共存設(shè)計(jì)密鑰輪換是安全實(shí)踐里的常規(guī)操作但在配置加密這個(gè)場(chǎng)景下很容易做砸。核心思路是解密時(shí)支持多個(gè)版本加密時(shí)只用最新版本。前面給的enc:v1:前綴就是為此設(shè)計(jì)的。輪換時(shí)先生成 v2 密鑰把SecretResolver的 keys 映射表里同時(shí)放 v1 和 v2重新加密所有敏感值并替換成enc:v2:前綴確認(rèn)沒(méi)有 v1 的密文殘留之后再把 v1 從映射表里移除。這個(gè)過(guò)程可以分多次發(fā)布完成不需要一次性切換。第一版發(fā)布只加 v2 密鑰的支持密文還是 v1第二版發(fā)布把密文換成 v2第三版發(fā)布移除 v1 密鑰。每次發(fā)布都可回滾風(fēng)險(xiǎn)可控。要注意的是如果密鑰來(lái)自外部服務(wù)輪換時(shí)要考慮服務(wù)的可用性。密鑰服務(wù)掛了會(huì)導(dǎo)致應(yīng)用完全起不來(lái)所以本地最好有一份降級(jí)密鑰或者把密鑰緩存到本地文件。6.3 測(cè)試環(huán)境與生產(chǎn)環(huán)境的隔離測(cè)試環(huán)境的密鑰和生產(chǎn)環(huán)境必須完全不同這是基本要求。但實(shí)際項(xiàng)目里經(jīng)常出現(xiàn)測(cè)試密鑰硬編碼在代碼里、生產(chǎn)環(huán)境復(fù)用的情況。我的做法是把密鑰來(lái)源做成可配置的通過(guò)app.secret.key-source指定可選值是env、file、vault。測(cè)試環(huán)境用env配合 CI 的變量注入生產(chǎn)環(huán)境用file掛載只讀的密鑰文件。這樣同一份代碼在不同環(huán)境走不同路徑不需要改代碼。同時(shí)要在啟動(dòng)時(shí)加一條校驗(yàn)如果檢測(cè)到當(dāng)前是生產(chǎn) Profile 但密鑰來(lái)源是env且密鑰長(zhǎng)度不足直接啟動(dòng)失敗。寧可起不來(lái)也別帶著弱密鑰跑起來(lái)。另外測(cè)試環(huán)境的數(shù)據(jù)最好也是脫敏的。有些團(tuán)隊(duì)為了圖省事把生產(chǎn)數(shù)據(jù)導(dǎo)到測(cè)試庫(kù)密碼還是同一套這種時(shí)候加密配置就形同虛設(shè)了。我個(gè)人在實(shí)際操作中的體會(huì)是配置加密這件事真正的難點(diǎn)不在算法而在讓所有人都按同一套規(guī)則來(lái)。代碼里寫(xiě)得再完善運(yùn)維在啟動(dòng)腳本里直接寫(xiě)明文整條鏈路就破了。所以落地的時(shí)候除了技術(shù)方案最好再配一條啟動(dòng)校驗(yàn)檢測(cè)到關(guān)鍵屬性沒(méi)有加密前綴時(shí)打一條 WARN 日志慢慢把習(xí)慣糾正過(guò)來(lái)。踩過(guò)幾次坑之后我發(fā)現(xiàn)日志比文檔管用得多。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
18禁中文字幕| 青娱乐休闲视频在线观看| 久久久久久久亚洲Av无码| 麻豆天美在线喷水AV| 成人在线日韩| 377p欧洲日本亚洲大胆| 久久久啊啊啊| 97精品国产精品免费观看| 亚洲制服aⅴ中文字幕| yazhouzaixian| 麻豆黄四叶草网站| 亚洲日韩精品在线播放| 欧美激情内射| 果冻传媒A片麻豆熟妇人妻| 色香阁在线| 欧洲熟妇xxXx欧美老妇裸体 | 亚洲国产成人福利在线观看| 欧美激情综合网| 60秒免费小视频| 大伊香蕉在线视频免费| 久久久久国产精品片区无码直播| 好吊色青靑草| 日本 情色 1区| 日本男人插女人的逼黄色| 蜜桃久久综合视频| 色9999日韩国产| 强奸乱伦AV网站| 亚洲网站一区二区在线| 97在线视频免费看| 中文字幕第9页萱萱影音先锋| 亚洲黄色网址| 中文字幕第7页| 天天日美女的B| 青青草啪啪网| 精品十三区| 麻豆黄色五月天| 欧美人妻精品一区二区| 国产少妇肉丝在线观看| 日韩中文字幕二区| 99九九精品| 亚洲精美粉嫩嫩泬在线观看 | 色色国产| 国产精品一二三区福利| 九九综合久久| 久久婷婷国产一区二区色| 激情五月天综合网| 99热成人| 白丝1区2区3区| 性老妇一区二区三区| 按摩中文字幕| 国产乱婷婷精品二区三区| 六九九九| 台湾大香蕉99热| 久久久成人精品| 97精品视频在线| 亚洲亚洲亚洲天堂天堂| 国产精品久久久无码aV去| 黄片www视频免费| 视频一区二区免费在线| 国产一进一出视频网站| 日本熟妇人妻中出视频| 99自拍视频在线观看| 色5月婷婷| 九九夜精品九九在线| 69人妻精品丰满熟女区| 97欧美色综合| 久久尹人大香焦视| 久久午夜鲁丝片| 18禁无码永久免费无限制| 人人操人人舒服| 26uuu性| 免费日韩黄片| 亚洲操人| 精品人人| 国产第11页| 国产精品97超碰| 青青草大香蕉视频| 三级特黄60分钟播放| 国产福利小视频高清在线观看| 探花一区在线| 香一区二区三区| 欧美亚洲涩涩| 91精片| 日韩黄色av中文字幕| 亚洲天堂99| 97超碰69| 乱操9999| AV和黑人在线播放| 夜夜嗨一区二区| 超碰天天久久79| 亚欧美无遮挡| 成人av影院在线观看| 成人免费不卡在线视频| 99国产精品人妻人伦| 日韩综合97P| 91操熟女| www.av在线观看| 射 色综合| 欧美激情精品久久久| 色香天天| 综合色播| 九久久精品| 国产成人超碰在线| 9l视频自拍9l九色成人| 性性欧美| 亚洲欧洲av影音| 9久精品| 综合网~91综合网| 中文字幕国产| 韩国三级理论在线| 天天肏美女| 欧美特大黄一级片片免费| 97chaopengongkai| 三四中文字幕| 亚洲91网| 又大又大又大又粗爽高潮观看| 超碰在线综合97| 操淫穴亚洲五月丁香 | 熟女一区二区三区| 91撸色网 玖玖网 欧美| 欧美色图亚洲特色| 精品一久久久| 色色综合97| 国产黄色动态精品| 欧美大香蕉97| av线电影| 青青草导航在线视频| 麻豆色约约| 啊啊啊啊好多水| 2017天天插| 啊啊啊好舒服视频| 午夜小电影在线插入淫高潮| 亚洲一区日韩精品| 第四色奇米影视777| 成人av在线播放| 日韩Va亚洲va欧美Ⅴa久久| 国产av波波国产精品| 日韩欧美成人性爱在线| 99日韩| 九九99久久| 翘臀vidoes| 熟啊v色欧美热| 亚洲国产剧情少妇激情| 九九九网页| 在线 制服丝袜中出 人妻| 91狠狠色丁香婷婷综合久久精品| 性欧美另类高清| 久久9视频| 东北黄色电影| 97av,com| 国产精品不卡一区二区三区av| 九九热久久99精品re| 国产成人bd在线观看| 色婷婷99| 色综合20p| 九九九九九精品视频| 啊啊啊好想要| 亚洲少妇喷视频看| 日本精品九九九| 国产精品农村妇女精品| 91欧美大片| 日本性爱欧美性爱| 97精品视频免费| 后入式999| 东北少妇高潮zzzz| 激情五月天丁香社区| 五月婷婷综合在线| 久久精品免费| 春色综合免费| 99re热有精品视频国产| 人妻啊啊人妻啊啊| 东北操逼| 屁股久久久久久| 波多野结衣一级视频| 日本一级一级一级一级| 四虎精品一区| 新久久AV| 97在线欧洲| 丝袜综合网| 成人无遮挡毛片免费看| 五月丁香综合| 死我十八禁| 午夜超爽| 青青草视频导航官网| 亚洲图片欧美偷拍| 人人透人人操| 亚洲s色图| 国产亚洲福利第一页丝袜| 人人考人人摸人人干| 800zy一区二区| 日本布卡一区二三区| 亚洲乱色熟女一区| 亚洲精品骚逼| 激情五月综合开心五月| 亚洲中文制服诱惑| 四虎影视欧美| 婷婷五月天影院| 神马久久免费电影观看| 中文自拍欧美影视| 五月天亚洲色图| 五月丁香六月婷| 98福利在线视频| 黄色大片免费在线| 欧美国产一区二区三区麻豆传媒| 老鸭窝成人免费毛片视频 | AV有码在线| 精品国产人成在线| 欧美亚洲厕所精品偷拍91 | 日日夜夜草草草| 84YTCOM性无码| 九色97| 欧美色图91| 婷婷综合激情| 亚洲丝袜综合| 亚洲不卡AV在线| 水滴偷拍| 91大神电影天堂| 屁股久久久久久| 91色综| 久久中文字幕女同性恋一区| 国产一区二区av综合| 免费99精品国产自在在线| 婷婷超| 美骚妇av高清在线| 凹凸视频在线观看伊人| 精品熟妇视频一区二区| 久久乐| 国产一区二区二区按摩精品啪视频| 少妇 综合| 97爱综合| 欧美情色男人的天堂| 99在线免费公开视频| 久久只有精品一区二区三区| 日韩亚洲国产视频| 天天影视91看看| 国产成人资源| 欧美日韩国产黄色片| 欧美大色交| 国产懂色精品国产av| 91欧| 黑人娇小av在线播放| 久久天天摸| 国产欧美在线观看免费观看| 啊啊啊啊好疼视频| 狼人综合婷婷激情四射| 人人操人人uiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii | 中文字幕av亚洲精品| 九九精品美女高溯喷水| 欧美成人一级免费电影| 欧美在线第五页| 伊人久久88国产女| 国产精品毛片?v一区二区三区| 校园春色亚洲无码| 人人摸人人干| 蜜乳AV网址| 亚洲人久久久久日| 亚洲高清在线se| 97精品一二区| 国产91久久九九免费精品无码| juliaann欧美丝袜办公室| 超碰碰97| 欧美一级三级| 自拍大香蕉乱插| 九九九九热| 欧洲亚洲天堂精品| 美女人妻色网站| 尤物视频一区| 玖玖综合网| 噜噜噜久久亚洲精品色情| 亚洲成人久久美女| 亚洲啪AⅤ永久无码| 国产精品伦理| 男人的天堂日本东京热| 欧美色图亚洲特色| 亚洲色图久久成人| www.91久久| 国产AAAAAABBBBB| 好吊色青靑草| 精品无人区麻豆乱码1区2区图片| 日韩精品熟妇| 小草三级久久观看| 婷婷综合在线| 一区二区视频在线播放| 97欧美| 天堂av最新电影网| 91激情综合| 干b在线性社区| 午夜一区| 91社操逼| 国产一级高跟丝袜| 国产一区二区在线播放量| 免费操逼91| 国产久久天堂资源| 五十路熟女人妻一区二区在线观看| 日韩三级av片| 日日不卡av| 欧美日韩亚洲天堂| 日韩兔费看黄片| 丝袜足交视频| 午夜爽爽爽在线观看永久入口姬片| 97在线免费| 久久精品操| 日韩大香蕉AV影片| 啪啪啪精品| 操婢日韩| 99精品成人免费看| 亚洲熟妇图片| 国产精品suv一区| 啊啊啊啊啊啊啊啊啊啊在线观看| 亚洲中亚日激情视频| 久久是精品| 青青操日韩| 青青草原av| 色香av| 欧州一区二区三区四区| 黄页视频网站野外| 99操逼| 欧洲综合视频| 国产精品丝袜久久亚洲不卡| 骚鸭AV| 欧美亚洲高清| 思思热久久成人| 欧美日韩性爱操大逼| 激情五月天综合网| 免费看污网址| 国产综合久| 91肉丝| 视频在线观看免费一区二区三区| 日韩性爱播放| 不卡九肏| 亚洲色棕合| 欧美国产婷婷久久| 人干人人人操人人摸| 高清无码网址| 亚洲人91| 欧美精品三级黄片| 中文字幕在线免费观看视频| 成 人 影视 一区 二区 三区 四区| 青青草字幕AV| 亚洲精品一区二区日本| 天天天天天干夜夜夜夜夜操| 高树玛利亚无码流出| 国产天天噜一噜久久久| 日本国产欧美一区三区二区 | 亚洲资源站| 99久久精品无码一区二区毛片免费| 1024人妻熟女一区二区三区| 亚洲熟妇乱女区二区三区| 亚洲天堂电影网| 亚洲九九九| 免费综合亚洲中文| 国产欧美后入| 操逼逼一区视频| 色色激情| 日韩av情韩国爱禁区av一区二区| 亚洲阿v天堂在线| 亚洲一区日韩| 91美女視頻| 99人妻碰碰碰久久久久禁片| 五月丁香六月婷| 伊人久久亚洲色欲综合网站 | 久久熟女人| 亚洲偷拍欧美激情| 欧美精品成人在线播放| 麻豆一区在线| 少妇一级无码精品| 天美国产三级传媒| 欧美综合色,www| 亚洲美女自拍偷拍视频| 天天舔天天日天天射| 97干97色| 日本欧美韩国日产片片在线看免| 中文字幕第7页| a天堂视频| 97在线无精品| 中国大陆国产高清AⅤ毛片| www.一本大99| 亚洲国产精品成人综合| 爆乳免费黄网站| 综合网 欧美| 天天干天天做| 好爽视频在线观看视频| 99精品在线| 97久操| 大香蕉丝袜一级片| 色欲久久99精品久久| 人人摸人人干人人拍97| 美女丝袜激情小说| 囯产操逼片| 天欧美在线| 国产中文字幕曰本毛片| 夜夜夜夜爽| 亚洲免费人妻在| 热久久无毒不卡| 激情久久久| 成人AV在线网站| 国产高潮AA片免费看| 国内毛片四区| 国产精品天美传媒| 国产精品第一区第一页| 加勒比五月天| 国产精品视频精品一二| 国产久久天堂资源| 高清不卡视频| 亚洲暴力强奸AV| 插B在线观看| 久久五月婷| 亚洲97在线观看| 不卡超碰护士AV在线免费播放| 亚洲精品一区二区日本| 久久6热精品99视频| 欧美日韩国内不卡| 超碰九区| 操曰本熟女| 色婷婷色99国产综合精品| 久久爱97| 好看的91视频| 天天干天天干天天干| 国产91影院| 少妇三P| 国产成人www免费人成看片| 国产91美女视频| 欧美有码亚洲中文字幕一区二区三区四区| 黄色电影在线播放综合网站| 欧美偷| 无码欧美有限公司| 中文字幕aⅴ在线视频| 91久久婷婷| 欧美日韩精品久久| 啊灬啊灬啊灬好深灬快高潮了动漫-国产字幕国产在线观看-B049AV | 亚洲91色在线| 手机看av网站在线看| 粉嫩av在线| 蜜臀av网址| 大香蕉碰碰| 国产白嫩漂亮KTV在线| 国产深喉视频一区二区| 性欧美精| 伊人成人情色综合| 偷拍 精品另类 凸凹了四区| 不卡一区二区日本视频| 欧美日韩97| 亚洲久久东京热一二三四五区视频| 女优免费一区二区永久| 一级黄色性爱A级片| 97日韩欧美| 俺也射| 黑人中出21连凳花野真衣| 欧美性爱另类综合| 亚洲欧洲综合av在线| 91n欧美| 天天天堂影视日韩亚洲91| 国产乱婷婷精品二区三区| 色情五月综合婷婷| 久久国内| 国产一级不卡在线观看| 日产操逼| …亚洲黄色厕厕女女在线播…| 91伊人久久在线| 精久久久91| 91女神在线视频| 狠狠狠狠狠干| 无套内射性感少妇视频| 唐山老熟妇露脸啪啪叫| 逼操网站| 国产一区二区三区久久久精品| 碰碰97| 777超碰| 久久久一区二区三区麻豆| 1.igao73.com 加入收藏 免费专区 国产精品 中文字幕 日韩精品 欧美精品 精彩 | 三级日本一区二区三区| 好爽视频在线观看视频 | 国产精品69久久久久久久| 久久色一区二区| 台湾大香蕉99热| 国产精品制服丝袜中文字幕日韩一区二区三区| 色婷婷综合久久久久中文国产精品一区中文字幕,国产福利电影一区二区三区 | 99re视频这里只有精品| 国产白丝网站| 欧美性性性| 男同专区一区二区三区在线| 婷婷激情丁香| 后入国产| 夜夜爽夜夜爽| 亚洲欧洲成人在线电影| 亚洲天堂在线怕怕视频| 日韩免费簧片| 亚洲中文一区二区三区| 欧美亚洲| 国产亚洲精品自在线亚洲情侣| 日韩免费性爱视频在线观看| 大香蕉黄色一区| 色综合久| 国产丝袜美女诱惑| 综合网久久| 好舒服视频| 青久久| 殴美色网| 无码精品久久久久久亚洲| 人人操人人干xxx| 日韩av不卡在线看| 亚洲天堂 视频你懂的| 丁香啪啪| 99国产在线绯色一区| 亚洲欧洲色情高清| 美女天天干| 久久人妻| 自拍偷拍 高清无码| 国产精品青草综合久久| 国产精品久久9| 欧美色图人妻| 蜜臀久久99精品久久久久久婷婷 | 日本久久女同性恋视频| 日韩卡一卡二卡三在线| 色婷婷网| 精品人妻一区二区三区视频| 尤物AV免费网站| 日日超碰亚洲| 人人干人人操人人..com| 丁香五月久久| 2019AV天堂| 夜夜春夜夜操| 色屁屁影院www国产| 日韩激情中文字幕有码| 国产不卡精品91| 中文字幕伊人| 男人的天堂 在线一区| 亚洲欧洲日韩天堂av| 9l视频自拍9l九色成人| 精彩国产视频播放1区2区| 97综合久第一页| 国产精品福利资源在线尤物| 日韩午夜啪啪视频| 91网站视频在线观看| 精品日日人妻| 日本一区二区三区四区免费观看| 国内精品999| 超碰综合97在线| 三级日韩一区二区三区| 99热在线播放| 综合网亚洲1| 欧美性爱精品七区| 91黑丝在线播放| 日韩中文字幕宗合在线| 天天视频网站黄| 欧美成人精品一区二区男人蜜臀| www.91视频网| 亚洲区 欧美区| 乱伦一区二区三区‘| 日本三级中国三级99人妇网站| 超碰天天操你比| 色噜噜狠狠色综无码久久合欧美| 香蕉人人操tv| 亚洲区限制级| 亚洲国产精品V?在线播放| 99热久| 欧美玖玖爱免费玖玖| 国产拍偷精品网站| 综合日本女人伊人| 天天操天天舔| · —级AA伦aa坐爱午夜极速ⅴA一区天天噪天天噪天天噪 | 亚洲视频,小说| 大色综合| 亚洲18禁| 蜜臀久久99精品久久久久| 91精品黄在线观看| chaopen97久久| 日韩久久.一级黄色片| 熟女一区二区| 欧美的性爱网站免费| 男人天堂.AB| 亚洲av噜噜噜噜噜噜| 蜜臀av在线播放一区二区三区| 欧美色图99| 97干在线视频| 色爱亚洲| 亚洲 欧美都市激情| 欧美亚洲今日在线| 又大又黄国产| 1769一区| 久久爽爽精品| 亚洲av淫乱| 欧美亚洲韩国视频十五区 | 日本一级二级三级网站| 91在线国产后入风骚翘臀美女素人| 亚洲精美粉嫩嫩泬在线观看| 少妇丝袜在线观看AV| 无色无码| 中文字幕一区二区无码成人| 久久极品一区二区| 97超碰欧美| 亚州色站 日韩电影| 久久久久久久九九九九九九| 亚洲日韩熟女人妻高清在线| 亚洲午夜福利视频| 一区二区三区看视频| 熟女人妻av在线资源,黄色的资源| 欧美性暴力| 亚洲精品欧美专业| 亚洲熟女性高潮久久久| 久久久久96| 日韩/97| 色婷婷激一区二区三区| 天天综合~91| 天天肏美女| 偷拍三区| 精品少妇高潮久久| 欧美专利1区2区3区4区5区免费| 波多野结衣之双飞调教在线播放 | 激情综合网五月婷婷| 蜜臀99久久精品久久久久| 丝袜喷水在线| 大色综合网| 国产精品96| 北京美女一区二区| 五月婷在线| 蜜乳视频网站| 久久大香蕉97| 欧美激情片一区二区| 亚洲成人性爱在线观看| 欧美在线播放| 亚洲天堂久| 亚洲中文字幕乱码无码一区二区| 网页导航五月天免费一二三区 | 欧美小说区视频区| 久久天天躁日日躁狠狠躁 | 波多野结衣被操50分钟免费视频 | 天天爽入口| 亚洲伊人久久精品狠狠在线| 亚洲精品a人片在线观看视| 九九热AV| 亚洲色图片区| 成人一区二区三区四区| 国产九月婷婷| 成年人性爱日韩| 国产精品一区二区a| 中文字幕一二三av| 超碰97最新人妻| 又黄又爽在线观看视频| 99久久精品无码一区二区| 欧美91精品国产自产| 国产女主播视频在线观看| 成人熟女视频一区二区三区| 激情综合五月天| 日韩探花精品在线视频| 中文字幕天堂在线| 美女91| 99精品综合久久久久五月天| 91久久堂| 日本999精品视频| 无码免费一区二区三区啪啪| 中国亚洲呦女专区| 黄片com.| 亚洲免费成人在线高清无码视频 | 日本操逼无码| 超碰97护士| 欧美亚洲在线| 草B在线| 国产九九九九九九| 亚洲超碰综合网| 超碰天天操| 99热精品国产| av午夜玫瑰| 中文字幕乱碼在线| 欧美色图中文字幕| 亚洲欧美爆| 蜜臀av中字字幕网站| 男人的天堂2019AV| 亚洲天堂电影精品一区| 99性爱| 日本欧美成人片AAAA| 欧美日韩99| 色爱综合网| 丁香五月成人| 920日本午夜免费| 深夜啪啪啪视频免费| 激情第四色| 久久免费精彩视频| 欧美拳交在线播放| 91网站18在线观看| 亚洲乱色视频一区、二区在线| 91久热这里只有精品| 少妇蜜汁| 加勒比日本在线| 97一本大道亚洲一区| 亚精品无码毛片一区二区三区| 狠狠图片青青草| 亚洲精品蜜桃久久久久久久| 91国内外在线| 玖色av| 国产99999| 国产在线综合网| 操www| 亚洲国产一级精品毛一级精品看免费视频| 果冻国产精品麻豆成人av| 一区二区三区激情在线观看| 五月天激情视频| 少妇高潮99p| 中文字幕制服欧美久久一区| 国产精品久久久久久久久久久久久久久久 | 亚洲欧美国产日本一区二区三区| 色99视频| 台湾大香蕉99热| 日本三级韩国三级美三级91| 性欧美999| 日本操逼视频在线| 粉嫩粉嫩一区性色AV片| 91久久久久久久| 精品一区二区三区最新| 91黑丝美女| 后入综合久久| 国产高清午夜成人在线观看| 金莲网址| 亚洲情色91| 2026国产精品视频| 这里只有精品97| 天天躁日日躁成人字幕aⅴ| 亚洲日韩国产欧美综合v| 日韩精品一二三四| B049AV在线播放| 超碰色老头| 久久久久久电影| 狠狠干,狠狠操| 久久久久网站-538在线视频-欧美永久乱码 | av强奸乱轮| 色五月亚洲| 国产精品suv一区| 久久亚洲一区女同性恋中文字幕| 国产精品白丝在线播放| 亚洲AV永久无码一区仙野| 91在线综合网| 天天综合91入口| 国内毛片无遮挡国产| 久久久国产三级黄色片| 97超碰热线| 欧美劲爆第一页| 亚洲国产精品成人无码久久久 | 亚洲av无码成人精品国产| 国产精品久久久蜜臀| 亚洲日韩狠狠撸视频| 欧美偷拍区| 校园春色综合| 精品免费成人久久| 色婷婷视频| 欧美少妇一区二区三区| 久久9精品| h无码动漫在线观看| 中文字幕在在线观看网站| 久9爱精品| 亚洲精品影视老司机| 99久久无色码| 欧美亚洲手机在线| 亚欧韩av| 亚洲偷拍欧美激情| 日日夜夜精品| 美女主播色欲91抠b在线播放| 啊v在线观看视频| 九九性爱网| 久久 久久国内精品亚洲| 中国AAAAAA黄色片| 超碰久久性爱| 久久精品熟妇丰满人妻99| 黄色性爱网网| 日本免费一区二区不卡| 日韩精品在线观看观看| 久久九九一区二区三区成人| 夫妻天天操岛国视频| 欧美久热| 久久久555| 2024人人操人人摸| 91精品国产91久久久久久久久久久久| 激情综合网五月婷婷五月天| 精品乱码久久久久| 人人艹亚洲| 久久久禁| 一级久久久久久久久久久| 亚欧美综合网。| yellow网站免费观看日韩高清无码| 上床不卡网站| 中文字幕奈奈美被公侵犯| 国产精品久久久久久久久久久久久久久久久久| 成人性爱免费播放| 九九热超碰97亚洲最新香蕉| 亚洲国产成人7777| 老汉网| 亚洲免费在线探花| 啊灬啊灬啊灬啊灬高潮奶出了免费视 | 成人日本精品九区| 久久亚洲中文字幕视频| 日韩精品人妻系列无码天堂| 人人贴人人摸| 韩日自拍| 99re在线观看| 久久9久| 69精品人人人人| 国产高清免费不卡av| 色五月激情AV在线| 成人短视频在线观看| 99av| 老师充足的奶水小说| 国产日韩欧美中文在线播放| 啊啊啊啊啊好舒服视频| 国产成人网站在线观看| 99re免费| 精品一国2| 桃花色涩综合影院| 男人天堂网站| 91天射| 一区二区三区机械有限公司| 超碰97网站| 欧美在线55555| 你懂得91| 91P0RNY大屁股人妻| 欧美熟妇精品黑人巨大91| 久久人妻办公室视频| 久久国产AⅤ| 久久国产999| 99这里只有精品| 人人做,人人操,人人摸| 亚洲天天精品| 丝袜内射| 亚洲第一成人影院色播| 欧美91精品国产自产| 蜜臀一二三| 欧美|91色综合| 美国aaaaa一级黄片| 亚洲综合在线第一页| 日韩欧美被操黄免费观看| 秋霞视频一区二区| 亚洲一卡二卡在线免费| 老鸭窝在线视频播放| 亚洲另类色图片| 自拍鲍鱼一区在线高清观看免费| 日日干天天干夜夜爽| 综合情欲网| 屌妞视频久久久久久久久久久久| 久热伊人| 日韩欧美aⅴ综合网站发布| 夜夜爽夜夜操| 九九九九九九九| 有码免费观看| 丁香五月激情啪啪| 无码日韩人妻av一| av网站免费看| 91制服丝袜| 97视频在线视频| 操国产高清| 中文字幕在线免费观看视频| 中文字幕一区二区三区人妻不卡| 97色色视频| 中文字幕一区二区视频在线观看| 久久大香蕉手机高清视频| 欧美在线电影| 91麻豆天美国产| 爽爽歪在线视频| 啊视频在线| 日本一本道A级黄色毛片试看60分钟| 日本中文熟女视频| 96精品久久| 999国产精品999久久久久久| 青青草久草AV| SUV一区二区在线看| 99国产在线绯色一区| 日韩草久视频| 日韩久久三区| www.99热| 色啪网| 三级片网站在线播放| 国产高清免费不卡av| 日B操| 极品销魂美女一区二区| 91w欧美| 精品国产乱码久久久久久网站入口| 中文精品少妇天堂| 日韩亚洲97| 天天干夜夜肏| 五十路熟女,国产欧美精品区一区二区三区 | 美女被啪到深处抽搐视频| 玖玖久久久| 欧美天天综合在线| 狠日欧美| 人妻夜夜爽天天爽三区麻豆AV网站| 最新AV在线| 97超碰9| 男人的天堂一区| 91成人无码| 放黄片放3级黄片没穿衣服| 熟女人妻一区二区三区免费看| 搡老女人老91二区| 97色碰| a男人的天堂久久一级A毛片 | 精品日韩产品在线,日韩在线不卡视频,欧美日韩免费专区/久, | 中文字幕国产精品1区| 日本成人电影资源网| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 精品人妻视频入口| 黄视频免费| 超碰在线观看av不卡| 免费簧片在线观看| 久精品无码av一区二免费国产在线观看| 久久精品国产亚洲AV高级北京| 99久久久er直播网址| 女人双腿搬开让男人桶| 色婷网| 日韩97超碰中文字幕| 国产免费大片| 久久夜夜夜| 噜噜噜亚洲精| 白丝一区| 中文字幕国产| 综合一区中亚洲国产成人综合精品| 五月天综合网| 夜夜操av亚洲一区二区| 老女人老91妇女老热女| 日夜尻逼网| 日本综合色图| heyZO天然素人无码AⅤ专区| 美中日韩无码| 91 刺激在线| 狠狠操一区二区| 欧美黑人91| 九九碰九九爱97超| 日韩伦理视频| 亚州色国| 亚洲 日本 不卡| 欧美传媒| 秋霞视频一区二区| 欧美久久毛片基地| 欧美爱国产综合、| 国产91影院| 后入式999| 国产夫妻一区二区| GVH-003 母子姦 青木玲-麻豆视频,麻豆视传媒短视频网站入口,麻豆视传媒官网直 | 国产不良强奸视频免费看| 女人双腿搬开让男人桶| 亚洲不卡不卡中文字幕不卡| 亚洲性综合| 在线视频97| 日韩激情中文字幕有码| 十八禁网站在线| 天堂av最新电影网| 波多野结衣AV无码一区| 日本中文字幕在线视频| 国产大片精久久久久久| 亚洲天堂一二| 久久久久久电影| 啊啊啊啊一区| 色97综合中文字幕| 自拍偷拍 日韩欧美| 无码国产精品午夜不卡(| 啊啊好多水| 亚州性色| 亚洲最大网站av| 91成人国产综合久久精品蜜月| 久久香蕉国产线看观看亚洲女人| 国产野战露脸在线播放| 国产成人资源| 91青青在线| 岛国大片在线观看网站入口| 成 人 影视 一区 二区 三区 四区| 亚洲素人综合| 日韩精品一区二区日韩| www.欧精品| 中文字幕AV中出| 欧美日韩国产色图在线| 日韩啪啪啪视频| 曰韩人妻中文字幕在线| 日本99热| 懂色AV网| 国人欧美精品一区二区| 日韩精品99久久久久久中文字幕 | 亚洲美女AV无码| 婷婷五月激情综合| 精久久久| 美女天天干| 超碰 欧美| 亚洲欧美国产中文视频| wwwcaobibi| 中文字幕加勒比海高清无码免费视频| 国产精品在线一区二区| 97免费在线观看| 日韩欧美综合激情| 欧美美女自慰一区二区三区| 日日骚精品视频| 午夜操一操| 亚洲精品一区二区三区在线播放| 性爱动态120秒| 乱色视频中文字幕| 欧美,日韩,中文,另类| 天天躁日日躁AAA片李宗瑞| 久久视频,这里只有精品| www.91逼逼.com| 91欧美性| 夜夜影视四色| 好爽要喷了| 久久这里只精品99re66图 | 天天摸天天碰天天添青青| 免费视频在线一区二区不卡| 婷婷综合在线观看| 99精品国产户外露出| 色婷婷成人综合| 伊人久久综合影院精品久久久 | 久久久久9999| 国产精品久久久久久久久久久久久久吹 | 欧美性爱伊人| 欧美另类丝袜熟女| 婷婷在线播放| 色色毛片| 99蜜桃臀亚洲成人在线观看| 911av网站免费观看| 九九九九97| 国产精品久久久三级无码| 亚洲第一页色网| 日本天天吊| 国内偷自视频区视频综合| 丝袜美女诱惑 91 视频| 国产亚洲精品第一最新| 天天射天天色成人| 最新加勒比丝袜在线| 欧美一级美片在线观看免费| 亚洲欧美日韩国产丝袜自拍中文| 日本一级性爱| 91天天综合日韩欧美| 青青草视频爽一爽| 国产中文精品一区二区在线观看| 亚洲好色人妻| 精品少妇后入一区二区三区四区人妻巨乳 | 中文高清一区二区的| 夜草网站| 久草久日| 久久久一级| 影音先锋新男人| 国产后入式在线观看| 亚洲天堂女优在线| AV不卡在线| 久久婷婷影院| 在线观看啊啊啊啊啊| 91GD.COM| 日本东京热加勒比久久| 密臀AV在线| 曰韩操B| www. 男人天堂成人在线| 综合五月婷婷亚洲一区| 柠檬AV导航| 狠狠爱夜夜| 97在线青| 日本熟妇一区二区三区| 日韩精品国产一区二区| 少妇的嫩逼图片| 手机久操欧美综合色码| 色色婷婷丁香| 福利社区午夜一区二区| 伊香蕉综合久久久久久久噜噜噜| 成人五月天色网| 精品区9| 亚洲成人美女无吗| 亚洲无码电影久久久| 成人开心网在线视频| 综合网~91综合网| 九九99久久| 顶级丝袜熟女一区二区三区| 91精品国产91久久青草| 乱操9999| 国产成人主播| 中文字幕av色| 婷婷视频网| 26uuu国产日韩综合在线观看| 亚洲欧洲激情卡通另类文学四射小说网站 | 五月天激情四射| 思思热久久成人| 美女天天干| 97网色| 亚欧操逼片在线观看 | 亚洲精品天天影视综合网 | 日本亚洲熟女视频| 少妇人妻好深太紧了vr91| 欧美日韩97| 日韩99999| 超碰社区97| 激情人妻另类| 蜜臀99999| 中文字幕 一区二区 亚洲无码| 婷婷伊人綜合中文字幕小说| 欧美日本国产日韩激情视频| 亚洲日本激情| AV乱伦专区| 日韩二级| 91在线视频观看国产| rion磁力链接| 97丝袜亚洲在线播放| 亚洲av夫妻操穴网| 五月丁香拍拍激情综合三级| 99999亚洲| 涩涩久久精品| 91是天天| 2024人人操人人摸| 成人性爱av| 好属操| av日韩中文字幕| 色欲人妻一区二区在线| 色色婷| 蜜桃久久一区二区| 日韩人妻丝袜中文字幕| 91亚洲网站| 久久系列| 97天天摸天天爽| 久久大| 国内毛片热久久思思热| 乱操乱伦AV| 欧美A片中文字幕| 7777奇米影视久久| 乱伦a片视频| 色色香蕉| 18禁超污无遮挡无码免费网| 亚洲最新a在线观看| 国产 日韩 另类 视频一区爱| 婷婷五月天激情网| 91超级碰| 欧美|91色综合| 在线人妻熟女一区二区三区四区五区| 久久9亚洲| 嗯嗯啊啊视频一区二区三区| 中文字幕人妻色偷偷久久皮| surenchaopeng| 久久久久久久久国产| 国产精品对白自产拍| 欧美姓爱综合网| 可免费观看的av毛片中日美韩| 天天看夜夜看日日干| 日本性爱欧美性爱| 屁屁影院一区二区三区国产| 岛国成人av在线播放网址| 丰满人妻一区二区三区| 色婷婷aV一区二区三区麻豆综合 | 国产成人+综合亚洲+天堂| 午夜精品久久久久久久男人的天堂| 亚洲精品97在线| 成人在线视频一区| 成人精品水蜜桃久久久久久久| 无码二级三级| 国产亚洲色婷婷久久99精品91 - 百度| 可以免费看黄片的视频| 干日本人少妇午夜寂寞影院| av一区二区三区 中文| 丰满欧美少妇| 久久伦理视频久久大香蕉视频| 欧洲自拍第一页| 欧美99999| 成人三一级一片aaa| 大香蕉婷婷| 婷婷色网| 人妻激情视频| 午夜福利国产欧美日韩夜夜| 黄片免费视频2019| 素颜老阿姨乱情色| 91蜜桃传媒精品久久久一区二区| 日本媚薬中文字幕在线| 亚熟hd视频在线| 97超碰国产精品| 欧美一二三区四五区|