Java中的安全加密

上一次我寫關于密碼學的文章時 ,我概述了Apache Shiro加密API,并展示了如何使用其兩個對稱密碼。 我還寫道:“您不需要在應用程序中對敏感數據進行加密和解密。”

我了解了更多有關密碼的知識,發現您需要了解更多信息。 我寫的內容在一定程度上是正確的,但是除非您小心謹慎,否則敏感數據可能并非對所有攻擊者都是安全的。

開箱即用Shiro提供了Blowfish-CBC和AES-CBC加密方法,我建議使用它們。 兩者都旨在防止被動竊聽攻擊者并且擅長于此。 不幸的是,真正的攻擊者更加復雜,可能會破壞基于他們的系統。

注意“可能”。 攻擊者只有在被攻擊系統至少與他配合時才能成功。 如果要使用這些密碼,則必須知道如何安全地編寫系統。 當然,另一種選擇是使用更強的密碼并完全避免該問題。

第一章中很少解釋所需的理論術語和概念 。 第二章介紹了如何以更安全的方式加密數據。 然后,我們描述了Blowfish-CBC和AES-CBC的工作方式,并展示了對它們的兩種可能的攻擊 。 最后,該帖子的末尾包含對其他資源的引用

理論

我們從一些理論概念開始。 如果您不想閱讀它,請直接轉到解決方案的章節。

首先要描述的重要事情是被動攻擊者和主動攻擊者之間的區別。 然后,我們解釋什么是分組密碼以及什么是經過身份驗證的加密。 最后兩個子章節列出了選定的易受攻擊的密碼和選定的安全密碼。

主動與被動攻擊者

僅竊聽攻擊者通常是被動的。 他能夠讀取加密的通信,但無法對其進行修改或將新的密文發送給通信應用程序。 他無法影響交流,他只會聽。 他的被動性只有一個例外:攻擊者能夠將未加密的信息提供給通信方之一,并獲得具有該確切信息的密文。

現實世界中的攻擊者通常更活躍。 他們編寫自己的消息,并將其發送到通信應用程序。 然后,該應用程序假定這些消息已加密,因此它將嘗試對其進行解密。 攻擊者觀察其反應(返回的錯誤代碼,需要的響應時間等),并進一步了解密碼。

如果幸運的話,他可能會使用獲得的知識來破解密碼或植入虛假信息。

分組密碼

分組密碼只能加密短消息。 例如,AES只能加密16個字節長的消息,而Blowfish只能加密8個字節長的消息。

較長的消息分為多個塊。 每個塊與先前加密的塊組合,然后傳遞到塊密碼。 塊組合被稱為操作模式,并且有多種安全方式來實現。

本文討論的兩種主動攻擊是對CBC操作模式的攻擊。 分組密碼本身是安全的。

認證加密

經過身份驗證的加密將任何修改后的密文視為無效。 無法獲取加密的數據,對其進行修改并以有效的密文結尾。 此屬性也稱為密文完整性。

密碼首先檢查完整性,然后以相同方式拒絕所有已修改的消息。 由于攻擊者無法通過完整性檢查,因此他從向應用程序發送新消息中得不到任何好處。

身份驗證和密文完整性通常(但不總是)由操作模式提供。

弱勢密碼

任何不提供密文完整性或未經過身份驗證的加密的密碼都可能會受到一些主動攻擊。 使用哪個加密庫都沒有關系。 加密算法是在標準中定義的,并且與所使用的庫無關,其含義相同。

換句話說,如果可以在不知道秘密密鑰的情況下創建有效的密文,那么即使不知道,也可能存在一些主動攻擊。

這篇文章描述了兩種攻擊CBC的操作模式。 一旦了解了這些攻擊以及被動和主動攻擊者之間的區別,您就應該能夠對CFB,CTR,OFB或其他未經身份驗證的密碼模式提出類似的攻擊。

安全密碼

經過身份驗證的加密可以防止主動攻擊者的攻擊。 還提供身份驗證的最常見操作模式是:

  • GCM
  • EAX
  • CCM

用這些模式之一(例如AES-EAX)替換CBC,您將擁有一個針對活動攻擊者的安全密碼。

當然,針對主動攻擊者的安全并不意味著該密碼沒有其他實際限制。 例如,大多數密碼只有在用戶加密了太多數據后才更改密鑰時才是安全的。 如果您認真對待數據加密,則應該研究并了解這些限制。

使用Shiro進行身份驗證的加密

本章介紹如何在Java中使用經過身份驗證的加密。 對于那些不了解該理論的人 ,認證加密可以防止數據篡改。 沒有密鑰的任何人都不能修改加密的消息,并且不可能對這種密碼進行主動攻擊。

Apache Shiro沒有實現自己的加密算法。 它將所有工作委托給Java密碼學擴展(JCE),每個Java運行時中都可用。 Shiro“僅”提供易于使用的API和安全的默認值。

因此,我們必須做兩件事:

  • 將經過身份驗證的操作模式安裝到Java密碼擴展中,
  • 將Shiro與新的經過驗證的操作模式集成。

安裝經過身份驗證的操作模式

Java密碼術擴展是一個可擴展的API。 所有類和算法都是由提供程序創建的,新提供程序可以隨時安裝到系統中。 提供者可以是:

  • 安裝到Java運行時中,并且可用于所有Java應用程序,
  • 與應用程序一起分發和初始化。

我們將展示如何將Bouncy Castle添加到項目中。 Bouncy Castle是根據MIT許可分發的提供商,并且包含EAX和GCM操作模式。

Bouncy Castle分發了多個jar文件,每個文件針對不同的Java版本進行了優化。 由于我們的演示項目使用Java 6,因此我們必須使用bcprov-jdk16庫。 將maven依賴項添加到pom.xml中:

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk16</artifactId><version>1.46</version>
</dependency>

庫存在后,您必須將其提供程序安裝到java安全系統中。 在應用程序啟動時運行以下方法:

private BouncyCastleProvider installBouncyCastle() {BouncyCastleProvider provider = new BouncyCastleProvider();Security.addProvider(provider);return provider;
}

現在已安裝Bouncy Castle,并且兩種驗證操作模式都可用。

與Shiro集成

Shiro加密軟件包基本上是JCE上易于使用的外觀。 它將JCE對象配置為使用安全默認值,并為其添加線程安全性。

擴展DefaultBlockCipherService類以利用這些功能。 大多數配置都由該類完成,但是我們仍然必須指定三件事:

  • 分組密碼名稱和參數,
  • 操作模式,
  • 填充。

塊密碼名稱在構造函數參數中指定。 我們將使用AES,因為它不需要其他配置。 GCM和CCM都不需要填充,因此我們必須指定填充NONE

新密碼服務:

class GCMCipherService extends DefaultBlockCipherService {private static final String ALGORITHM_NAME = "AES";public GCMCipherService() {super(ALGORITHM_NAME);setMode(OperationMode.GCM);setPaddingScheme(PaddingScheme.NONE);}}

這就對了。 您可以將新的身份驗證密碼用作任何其他Shiro密碼服務 。

測試用例

我們創建了一個簡單的測試用例,以證明完整性檢查有效。 它加密消息并更改其密文的第三個字節。 如果密碼提供了身份驗證,則嘗試解密修改后的密文將導致運行時異常:

@Test
public void testGCMAuthentication() {String message = "secret message";GCMCipherService gcmCipher = new GCMCipherService();assertIngetrityCheck(message, gcmCipher);
}private void assertIngetrityCheck(String message, DefaultBlockCipherService cipher) {byte[] key = cipher.generateNewKey().getEncoded();byte[] messageBytes = CodecSupport.toBytes(message);ByteSource encrypt = cipher.encrypt(messageBytes, key);// change the ciphertextencrypt.getBytes()[3] = 0;try {// it should be impossible to decrypt changed ciphertextcipher.decrypt(encrypt.getBytes(), key).getBytes();} catch (Exception ex) {return;}fail("It should not be possible to decrypt changed ciphertext.");
}

關于Java 7的注意事項

根據文檔 ,Java 7支持兩種經過身份驗證的操作模式:CCM和GCM。 從理論上講,您不需要第三方加密提供程序。

不幸的是,Oracle無法在第一個JDK 7版本中提供這些模式的完整實現。 他們希望將其添加到更新版本中,因此情況將來可能會發生變化。 Oracle錯誤數據庫包含兩個相關的 錯誤 。

Java 1.7.0_01仍然沒有它們。

密碼塊鏈接(CBC)

在描述承諾的攻擊之前,我們需要做的最后一件事是密碼塊鏈接(CBC)操作模式。 這種操作模式足以抵御被動攻擊者,相當快速且易于實施。

不幸的是,它也容易受到主動攻擊。

基本

CBC用于使用分組密碼對長消息進行加密。 分組密碼只能加密短數據塊,因此它首先將消息拆分為短數據塊。

第一個和最后一個塊是特殊情況。 我們將在以下子章節中說明如何處理它們。 現在,假設消息開頭已被加密,并且其第i個塊m i與密文c i相對應。

分兩個步驟對下一個消息塊進行加密:

  • 用上一個塊的密文對該塊進行異或(例如, m i ?c i-1 ),
  • 使用分組密碼(例如Blowfish(key, m i ?c i-1 ) )對結果進行加密。

示例:假設該秘密消息有三個塊,我們正在嘗試使用Blowfish-CBC對其進行加密。 第一塊已經被加密,其密文為1, 2, 3, 4, 5, 6, 7, 8 。 第二個塊是字節數組1, 0, 1, 0, 1, 0, 1, 0

步驟1:將第一個塊密文與第二個塊異或:

1, 2, 3, 4, 5, 6, 7, 8 ? 1, 0, 1, 0, 1, 0, 1, 0 = 0, 2, 2, 4, 4, 6, 6, 8

步驟2:使用河豚算法對結果進行加密:

Blowfish(secret_key, {0, 2, 2, 4, 4, 6, 6, 8})

第一塊–初始化向量

第一個塊沒有要合并的前一個塊。 因此,我們將生成一個稱為初始化向量的隨機數據塊。 初始化向量用作數據的第一塊。 它與第一個消息塊進行異或運算,并使用塊密碼對結果進行加密。

初始化向量作為密文的第一個塊未經加密地發送。 如果沒有密文,接收者將無法解密密文,也沒有理由對其保密。

示例:假設該秘密消息有三個塊,我們正在嘗試使用Blowfish-CBC對其進行加密。 第一個塊是一個字節數組1, 1, 1, 1, 1, 1, 1, 1

步驟1:產生隨機初始化向量:

1, 8, 2, 7, 3, 6, 4, 5

步驟2:將第一個塊與初始化向量進行異或:

1, 8, 2, 7, 3, 6, 4, 5 ? 1, 1, 1, 1, 1, 1, 1, 1 = 0, 9, 3, 6, 2, 7, 5, 4

步驟3:使用河豚算法對結果進行加密:

Blowfish(secret_key, {0, 9, 3, 6, 2, 7, 5, 4})

步驟4:結合初始化向量和密文。 如果上一步中的Blowfish函數結果為1, 2, 3, 4, 5, 6, 7, 8 ,則密文為:

1, 8, 2, 7, 3, 6, 4, 5, 1, 2, 3, 4, 5, 6, 7, 8


最后一塊–填充

分組密碼能夠加密固定長度的消息,而最后一個分組通常比該分組短。 由于密碼無法加密,因此我們需要一種在消息末尾添加其他字節的方法。

Shiro默認使用PKCS#5填充。 每個字節等于填充的長度:

  • 如果最后一塊太短,請計算丟失的字節數,并用該數字填充丟失的字節。
  • 如果最后一個塊的大小正確,則將其視為丟失整個塊的消息。 向其添加一個新的填充塊。 每個字節都等于塊大小。

示例1:假設秘密消息有三個塊,我們正在嘗試使用Blowfish-CBC對其進行加密。 最后的塊是字節數組1, 1, 1, 1 。 填充塊:

1, 1, 1, 1, 4, 4, 4, 4

示例2:假設該秘密消息有三個塊,我們正在嘗試使用Blowfish-CBC對其進行加密。 最后一個塊是字節數組8, 7, 6, 5, 4, 3, 2, 1 。 最后一塊和填充:

8, 7, 6, 5, 4, 3, 2, 1, 8, 8, 8, 8, 8, 8, 8, 8

進攻

最后,我們準備展示對基于CBC的密碼的兩種不同攻擊,并證明問題是真實的。 我們的樣本項目包含針對AES-CBC和Blowfish-CBC密碼的兩種攻擊的測試案例。

第一部分說明如何將加密文本的開頭更改為我們選擇的任何消息。 第二小節介紹了如何解密密文。

數據篡改

僅當攻擊者已經知道加密消息的內容時 ,才可能進行數據篡改攻擊。 這樣的攻擊者可以將第一個消息塊更改為他希望的任何內容。

特別是可以:

  • 更改AES-CBC加密消息的前16個字節,
  • 更改Blowfish-CBC加密郵件的前8個字節。

潛在危險

這種攻擊是否危險,在很大程度上取決于情況。

如果您使用密碼通過網絡發送密碼,那么數據篡改并不是那么危險。 最壞的情況是,合法用戶的登錄將被拒絕。 同樣,如果加密的數據存儲在某些只讀存儲中,則不必擔心數據被篡改。

但是,如果要通過網絡發送銀行訂單,則數據篡改是真正的威脅。 如果有人將消息Pay Mark 100$更改為Pay Tom 9999$ ,Tom將獲得9999 $,而他不應該得到。

攻擊

加密的消息分為三個部分:

  • 隨機初始向量
  • 第一組密文,
  • 消息的其余部分。

接收者使用塊密文解密第一個密文塊。 這給他message block?initial vector 。 要獲取消息,他必須將此值與初始向量進行異或運算:

message block ? initial vector ? initial vector = message block

初始向量與消息一起傳輸,主動攻擊者可以更改它。 如果攻擊者用another iv替換了原始初始向量,則接收者將解密另一條消息:

message block ? initial vector ? another iv = another message

重新排列前面的等式,您將得到:

another iv = message block ? initial vector ? another message

如果攻擊者同時知道加密消息的初始向量和內容,則可以將消息修改為所需的任何內容。 他要做的就是將已知消息內容和所需消息都與原始初始向量異或。

解密修改后的密文的任何人都將獲得修改后的消息,而不是原始消息。

測試用例

我們創建了一個簡單的測試案例,演示了對使用AES-CBC加密的消息的這種攻擊。

想象一下,攻擊者捕獲了一封加密的電子郵件,并且以某種方式知道其中的內容:

//original message
private static final String EMAIL = "Hi,\n" +"send Martin all requested money please.\n\n" +"With Regards, \n" +"Accounting\n";

攻擊者只能更改消息的前16個字節,因此他決定將資金重定向到Andrea:

//changed message
private static final String MODIFICATION = "Hi,\n" +"give Andrea all requested money please.\n\n" +"With Regards, \n" +"Accounting\n";

以下測試用例對消息進行加密并修改密文。 修改后的密文被解密并與預期消息進行比較:

@Test
public void testModifiedMessage_AES() {//create cipher and the secret key StringCipherService cipher = new StringCipherService(new AesCipherService());byte[] key = cipher.generateNewKey();//encrypt the messagebyte[] ciphertext = cipher.encrypt(EMAIL, key);//attack: modify the encrypted messagefor (int i = 0; i < 16; i++) {ciphertext[i] = (byte)(ciphertext[i] ^ MODIFICATION.getBytes()[i] ^ EMAIL.getBytes()[i]);}//decrypt and verifyString result = cipher.decrypt(ciphertext, key);assertEquals(MODIFICATION, result);
}

當然,可以對河豚CBC進行類似的攻擊。 這次我們只能更改前8個字節:

@Test
public void testModifiedMessage_Blowfish() {String email = "Pay 100 dollars to them, but nothing more. Accounting\n";StringCipherService cipher = new StringCipherService(new BlowfishCipherService());byte[] key = cipher.generateNewKey();byte[] ciphertext = cipher.encrypt(email, key);String modified = "Pay 900 dollars to them, but nothing more. Accounting\n";for (int i = 0; i < 8; i++) {ciphertext[i] = (byte)(ciphertext[i] ^ modified.getBytes()[i] ^ email.getBytes()[i]);}String result = cipher.decrypt(ciphertext, key);assertEquals(modified, result);
}

解密密碼

第二次攻擊使攻擊者可以解密該秘密消息。 僅當解密機密消息的應用程序與攻擊者合作時,才有可能進行攻擊。

填充Oracle

攻擊者會創建許多偽密文,并將其發送給收件人。 當他嘗試解密這些消息時,將發生以下情況之一:

  • 密文解密為毫無意義的垃圾,
  • 修改后的消息將根本不是有效的密文。

如果應用程序在兩種情況下的行為均相同,則一切正常。 如果行為不同,則攻擊者能夠解密密文。 基于CBC的密文只有一種錯誤的方法-如果填充錯誤。

例如,如果密文包含加密的密碼,則當解密的密碼錯誤時,易受攻擊的服務器可能會以“拒絕登錄”進行響應,而在密文無效的情況下,則可能會出現運行時異常。 在這種情況下,攻擊者可以恢復密碼。

大概的概念

每條虛假消息都有兩個部分:一個虛假的初始向量和一個消息塊。 兩者都發送到服務器。 如果它回答“正確填充”,那么我們知道:

message ? original iv ? fake iv = valid padding

上述方程式中唯一未知的變量是消息。 original iv是先前的密文塊, fake iv是由我們創建的,有效填充是12, 23, 3, 3...8, 8, ..., 8等之一。

因此,我們可以將塊內容計算為:

message = valid padding ? original iv ? fake iv

算法

從恢復最后一個塊字節開始。 每個偽初始向量都以0開頭,以不同的最后字節結尾。 這樣,我們幾乎可以確定服務器僅在以1結尾的消息上回答“向右填充”。使用上一章公式計算最后一個塊字節。

獲取消息的倒數第二個字節非常相似。 唯一的區別是我們必須制作一個密文,該密文解密為第二個最短的填充2, 2 。 消息的最后一個字節是已知的,因此將2強制為最后一個值很容易。 初始向量的開頭并不重要,請將其設置為0。

然后,我們嘗試初始向量的倒數第二個字節的所有可能值。 服務器回答“正確填充”后,我們可以從與前面相同的公式中獲取倒數第二個消息字節: original iv ? fake iv ? 2 original iv ? fake iv ? 2 original iv ? fake iv ? 2

我們計算倒數第三個消息字節出來的假消息與填充3, 3, 3 ; 用填充4、4、4、4填充消息中的第四4, 4, 4, 4 ; 以此類推,直到整個塊被解密為止。

測試用例

易受攻擊的服務器使用PaddingOraculum類進行模擬。 此類的每個實例都會生成一個隨機密鑰,并將其保密。 它僅公開兩個公共方法:

  • byte[] encrypt(String message) –用密鑰加密一個字符串,
  • boolean verifyPadding(byte[] ciphertext) –返回填充是否正確。

填充oraculum攻擊是用decryptLastBlock方法實現的。 該方法解密加密消息的最后一塊:

private String decryptLastBlock(PaddingOraculum oraculum, byte[] ciphertext) {// extract relevant part of the ciphertextbyte[] ivAndBlock = getLastTwoBlocks(ciphertext, oraculum.getBlockSize());// modified initial vectorbyte[] ivMod = new byte[oraculum.getBlockSize()];Arrays.fill(ivMod, (byte) 0);// Start with last byte of the last block and // continue to the first byte.for (int i = oraculum.getBlockSize()-1; i >= 0; i--) {// add padding to the initial vector    int expectedPadding = oraculum.getBlockSize() - i;xorPad(ivMod, expectedPadding);// loop through possible values of ivModification[i]for (ivMod[i] =  -128; ivMod[i] <  127; ivMod[i]++) {// create fake message and verify its paddingbyte[] modifiedCiphertext = replaceBeginning(ivAndBlock, ivMod);if (oraculum.verifyPadding(modifiedCiphertext)) {// we can stop looping// the ivModification[i] =//    = solution ^ expectedPadding ^ ivAndBlock[i]break;}}// remove the padding from the initial vectorxorPad(ivMod, expectedPadding);}// modified initial vector now contains the solution xor // original initial vectorString result = "";for (int i = 0; i < ivMod.length; i++) {ivMod[i] = (byte) (ivMod[i] ^ ivAndBlock[i]);result += (char) ivMod[i];}return result;
}

我們的示例項目包含兩個測試用例 。 一個人用AES-CBC加密消息,然后使用填充字眼到密文的最后一塊。 另一個對河豚-CBC也做同樣的事情。

解密Blowfish-CBC測試案例:

@Test
public void testPaddingOracle_Blowfish() {String message = "secret message!";PaddingOraculum oraculum = new PaddingOraculum(new BlowfishCipherService());//Oraculum encrypts the message with a secret key.byte[] ciphertext = oraculum.encrypt(message);//use oraculum to decrypt the messageString result = decryptLastBlock(oraculum, ciphertext);//the original message had padding 1assertEquals("essage!"+(char)1, result);
}

資源資源

其他相關資源:

  • 免費在線斯坦福加密課程 。
  • 從2002年開始用padding oracle攻擊的原始文件。
  • 填充oracle攻擊的一個很好的替代解釋 。
  • 解釋了對CBC的野獸襲擊 。 它基于padding oracle攻擊。
  • 關于常見密碼錯誤的堆棧交換線程 。

結束

沒有密碼可以絕對安全地防御所有可能的攻擊。 相反,它們僅提供針對定義明確的攻擊類別的保護。 只有對系統的潛在威脅與密碼強度匹配時,密碼才是安全的。

可以通過兩種方式來防御主動攻擊:

  • 通過設計使主動攻擊不可能。
  • 使用經過身份驗證的加密。

使用經過身份驗證的加密可以說更容易,并且應該是首選。 排除主動攻擊者容易出錯,而且風險更大。

Github上提供了本文中使用的所有代碼示例。

參考: This is Stuff博客上的JCG合作伙伴 Maria Jurcovicova提供的Java安全加密 。


翻譯自: https://www.javacodegeeks.com/2012/05/secure-encryption-in-java.html

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

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

相關文章

真機調試問題

1.拔掉插頭重新插入 2.轉載于:https://www.cnblogs.com/sanvow/p/5633976.html

vsftp

它的配置文件在/etc/vsftpd/vsftpd.conf在里面加入 anonymous_enableYES &#xff03;允許匿名用戶登錄FTPanon_upload_enableYES &#xff03;打開匿名用戶的上傳權限anon_mkdir_write_enableYES &#xff03;打開匿名用戶創建目錄的權限anon_other_write_enableYES …

java scrollpane源碼_JScrollPane用法 Java實例

時間&#xff1a;2019-10-07概述&#xff1a;JScrollPane 滾動條在Java中使用JScrollPane的例子&#xff0c;特別是滾動條的設置等&#xff0c;程序代碼中將設置水平與垂直表頭、設置scrollPane的邊角圖案、設置scrollPane的邊框凹陷立體邊框。適時水平滾動軸的參數設置等內容&…

ANTLR教程– Hello Word

Antlr代表另一種語言識別工具。 該工具能夠為任何計算機語言生成編譯器或解釋器。 除了明顯的用途&#xff08;例如需要解析一種真正的“大型”編程語言&#xff0c;例如Java&#xff0c;PHP或SQL&#xff09;外&#xff0c;它還可以幫助執行更小&#xff0c;更常見的任務。 每…

centOS 6.5安裝python和nginx

一、安裝python3.5 1、安裝python3.5 2、安裝pip并升級到最新 下載wget --no-check-certificate https://github.com/pypa/pip/archive/1.5.5.tar.gz 注意&#xff1a;wget獲取https的時候要加上&#xff1a;--no-check-certificate tar zvxf 1.5.5.tar.gz #解壓文件 cd pip…

rabbitmq 學習-9- RpcClient發送消息和同步接收消息原理

rabbitmq 學習-9- RpcClient發送消息和同步接收消息原理 轉載于:https://www.cnblogs.com/gotodsp/p/6532824.html

匯編寫java模塊_java – maven匯編插件moduleset源指令不包括任何文件,不符合附帶的模塊...

我有一個多模塊的maven項目,我正在嘗試獲取組件插件的moduleset源部分.我有模塊“module_parent”,“module_a”和“module_assembly”.module_a和module_assembly是module_parent的子項.module_assembly對module_a有一個聲明的pom依賴關系.module_assmebly具有程序集插件,asse…

用于RIA的JavaFX 2與HTML5

這些天來&#xff0c;我們正在啟動一個新項目&#xff0c;以實現Rich Internet Application&#xff08;RIA&#xff09; 。 第一個問題是&#xff1a;我們應該使用哪些技術和框架&#xff1f; 后端將是Java或其他現代JVM語言&#xff0c;因為我們主要是經驗豐富的Java開發人員…

插件化編程實現的一份糖炒栗子~~

迷茫的原因是因為想得太多&#xff0c;做得太少。因為只是 想 真的很容易&#xff0c;轉瞬之間就會產生無數個念頭&#xff0c;或許是該做點什么了吧。 但是整個人都是懶的&#xff0c;是廢的&#xff0c;是大腦控制不住自己的行為的。解決方案唯有一步一步的去把行為變成習慣。…

用C#來學習唐詩三百首和全唐詩

Begin 最近把項目做完了&#xff0c;閑來無事&#xff0c;就想做點好玩的事情&#xff0c;剛好前幾天下載了【唐詩三百首】和【全唐詩】這兩個txt文件&#xff0c;正好用C#來整理一下。 然后導出QData格式&#xff0c;可以給其他軟件讀取。 以后弄個開機自動顯示一句詩&#xf…

JRockit JRCMD教程

本文將為您提供概述和教程&#xff0c;說明如何使用jrcmd工具對JRockit Java Heap問題進行初始分析和問題隔離。 將來的文章中將介紹使用JRockit任務控制和堆轉儲分析&#xff08;僅限JRockit R28 版&#xff09;的更深入的分析和教程。 有關JRockit Java堆空間的快速概述&…

sts java配置tomcat_STS配置Tomcat.9.0

今天&#xff0c;心血來潮&#xff0c;弄了一下STS,按著建立WEB項目的方式建立工程。一、新建工程(FILE --NEW--Dynamic Web project)二、輸入項目名稱&#xff0c;TestWeb&#xff0c;然后下一步&#xff0c;點擊FInish.三、新建index.jsp并打開index.jsp,書寫測試成功&#x…

javaweb國際化

根據數據的類型不同&#xff0c;國際化分為2類&#xff1a;靜態數據國際化和動態數據的國際化。 靜態數據&#xff0c;包括 “標題”、“用戶名”、“密碼”這樣的文字數據。 動態數據&#xff0c;包括日期、貨幣等可以動態生成的數據。 國際化涉及到java.util.Locale和java.ut…

20145335郝昊《網絡攻防》Bof逆向基礎——ShellCode注入與執行

20145335郝昊《網絡攻防》Bof逆向基礎——ShellCode注入與執行 實驗原理 關于ShellCode&#xff1a;ShellCode是一段代碼&#xff0c;作為數據發送給受攻擊服務器&#xff0c;是溢出程序和蠕蟲病毒的核心&#xff0c;一般可以獲取權限。我們將代碼存儲到對方的堆棧中&#xff0…

Java枚舉益智游戲

假設我們有以下代碼&#xff1a; enum Case {CASE_ONE,CASE_TWO,CASE_THREE;private static final int counter;private int valueDependsOnCounter;static {int sum 0;for(int i 0; i<10; i) {sum i;}counter sum;} Case() {this.valueDependsOnCounter counter*counte…

jp在java中無法編譯_JPanal上加圖片的問題!

JPanal上加圖片的問題&#xff01;import java.awt.BorderLayout;import java.awt.Dimension;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.*;import java.awt.*;public class Frame1 extends JFrame {JPanel contentPane;JLabel jLabel1 new JLa…

玩轉Android之加速度傳感器的使用,模仿微信搖一搖

Android系統帶的傳感器有很多種&#xff0c;最常見的莫過于微信的搖一搖了&#xff0c;那么今天我們就來看看Anroid中傳感器的使用&#xff0c;做一個類似于微信搖一搖的效果。 OK ,廢話不多說&#xff0c;我們就先來看看效果圖吧&#xff1a; 當我搖動手機的時候這里的動畫效果…

圖像

背景圖案的設置 將圖片插入到網頁中去 用圖像作為超鏈接 使用工具建立地圖索引 切片索引 為網站添加圖標 5.1 背景圖案的設置&#xff08;背景不占位置&#xff0c;不影響文本的輸入&#xff09; 格式&#xff1a;<body background"URL"> 5.2 將圖片插入…

Maven構建依賴項

熟悉發行版和快照依賴項的Maven和Gradle用戶可能不了解TeamCity快照依賴項&#xff0c;或者認為他們與Maven相關&#xff08;這是不正確的&#xff09;。 熟悉工件和快照依賴關系的TeamCity用戶可能不知道&#xff0c;除了TeamCity提供的插件之外&#xff0c;添加Artifactory插…

Java兩種設計模式_23種設計模式(11)java策略模式

23種設計模式第四篇&#xff1a;java策略模式定義&#xff1a;定義一組算法&#xff0c;將每個算法都封裝起來&#xff0c;并且使他們之間可以互換。類型&#xff1a;行為類模式類圖&#xff1a;策略模式是對算法的封裝&#xff0c;把一系列的算法分別封裝到對應的類中&#xf…