官术网_书友最值得收藏!

三、如何實現二維碼管理系統

二維碼的生成

推薦在二維碼標準選擇的時候使用應用最為廣泛的QRCode碼,后續代碼示例中也會以此為基準。

目前開源的二維碼生成工具包有很多,比如QRCodejqueryqrcodezxingBarcode4j等。這里選用一個比較常用的由google開發維護的zxing,具體的代碼可以參考Google代碼測試包中的MatrixToImageWriter類來輔助開發,可以將該類直接拷貝到源碼中使用。

public static BufferedImage toBufferedImage(BitMatrix matrix) {

int width = matrix.getWidth();

int height = matrix.getHeight();

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

for(int x = 0; x < width; x++) {

for (int y = 0; y < height; y++) {

image.setRGB(x, y,(matrix.get(x, y) ? BLACK : WHITE));

}

}

return image;

}

public static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {

BufferedImage image = toBufferedImage(matrix);

LogoConfig logoConfig = new LogoConfig();

image = logoConfig.LogoMatrix(image);

if(!ImageIO.write(image, format, file)) {

throw new IOException("Could not write an image of format " + format + " to " + file);

}

}

對于部分業務系統在生成二維碼的時候可能存在需要在二維碼圖片中心添加logo圖片的業務需求,這里貼出在二維碼中添加logo的示例:

public BufferedImage LogoMatrix(BufferedImage matrixImage, String logoFilePath) throws IOException{

Graphics2D g2 = matrixImage.createGraphics();

int matrixWidth = matrixImage.getWidth();

int matrixHeigh = matrixImage.getHeight();

BufferedImage logo = ImageIO.read(new File(logoFilePath));

g2.drawImage(logo,matrixWidth/5*2,matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5, null);

BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);

g2.setStroke(stroke);

RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth/5*2, matrixHeigh/5*2,

matrixWidth/5, matrixHeigh/5,20,20);

g2.setColor(Color.white);

g2.draw(round);

BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);

g2.setStroke(stroke2);

RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth/5*2+2,

matrixHeigh/5*2+2, matrixWidth/5-4, matrixHeigh/5-4,20,20);

g2.setColor(new Color(128,128,128));

g2.draw(round2);

g2.dispose();

matrixImage.flush() ;

return matrixImage ;

}

二維碼內容的加解密

二維碼內容加密主要分為兩部分,其一是生成用于完整性校驗字段的哈希算法,其二是為了明文加密的對稱加密。

常用于完整性檢驗的哈希算法有很多種,如Ron RivestRSA公司)的消息摘要算法MD系列,這其中MD5因為兼具快速和安全兩大特點被廣泛采。同樣的哈希算法還有美國國家標準技術研究院(NIST)制定的安全哈希算法SHASecure Hash Algorithm)系列算法,國家密碼管理局發布的雜湊算法標準SM3等。這里使用MD5作為代碼范例:


public static String getMD5Text(String data) {

MessageDigest messageDigest = null;

byte[] srcBytes = data.getBytes();

try{

messageDigest = MessageDigest.getInstance("MD5");

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

}

messageDigest.update(srcBytes, 0, srcBytes.length);

BigInteger bigInt = new BigInteger(1, messageDigest.digest());

return bigInt.toString(16);

}

在二維碼密文解析的時候可使用相同方法取原文的MD5值進行檢驗。

二維碼明文加密采用對稱加密算法,對稱密鑰由二維碼管理系統保管,常見的對稱算法有DES算法、AES算法、IDEA算法SM4算法等,這里以AES算法為例。

加密:


public static String encrypt(String content, String password) {

try{

Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 創建密碼器

byte[] byteContent = content.getBytes("utf-8");

cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化為加密模式的密碼器

byte[] result = cipher.doFinal(byteContent);// 加密

return Base64.encodeBase64String(result);//通過Base64轉碼返回

} catch (Exception ex) {

Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);

}

return null;

}

解密:


public static String decrypt(String content, String password) {

try{

//實例化

Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

//使用密鑰初始化,設置為解密模式

cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));

//執行操作

byte[] result = cipher.doFinal(Base64.decodeBase64(content));

return new String(result, "utf-8");

} catch (Exception ex) {

Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);

}

return null;

}

生成密鑰:


private static SecretKeySpec getSecretKey(final String password) {

//返回生成指定算法密鑰生成器的 KeyGenerator 對象

KeyGenerator kg = null;

try{

kg = KeyGenerator.getInstance(KEY_ALGORITHM);

//AES 要求密鑰長度為 128

kg.init(128, new SecureRandom(password.getBytes()));

//生成一個密鑰

SecretKey secretKey = kg.generateKey();

return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 轉換為AES專用密鑰

} catch (NoSuchAlgorithmException ex) {

Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);

}

return null;

}

這里簡要說明了加解密的相關示例,網上也有相關的開源示例,對加解密有興趣的話可以自行深入研究。


推薦閱讀

建設移動統一消息管理中心

淺析web端的消息推送原理

React-native如何變為移動端的弄潮兒


關于作者:風行云,現任普元信息移動團隊開發工程師,畢業于山東大學(威海),主攻移動原生開發、react native開發、JAVA Web開發。先后參與中國郵政集團移動平臺、國家開發銀行移動應用平臺等項目的開發工作。

主站蜘蛛池模板: 海林市| 佳木斯市| 呼和浩特市| 灵山县| 溆浦县| 杭锦旗| 若尔盖县| 文安县| 金阳县| 胶南市| 天柱县| 昌宁县| 阿克苏市| 泽库县| 白山市| 泸定县| 永新县| 宜宾县| 丹阳市| 石台县| 岱山县| 亳州市| 达州市| 安乡县| 普兰店市| 兰西县| 祥云县| 峨眉山市| 玉溪市| 武穴市| 伊金霍洛旗| 元江| 垫江县| 腾冲县| 湘西| 淳化县| 临高县| 双鸭山市| 新兴县| 鲁山县| 姜堰市|