在開發支付項目時需要讀取密鑰,爲了保證密鑰的安全性和項目的多環境使用便捷性,參考springboot的配置讀取方案,設計一套支付的密鑰讀取方案:
優先在系統相對路徑(jar包相對路徑)查找如果沒有,再查找jar包中的resources目錄下
- 密鑰的安全性建立在:如果是生產環境則讀取系統相對jar包目錄下的密鑰文件,運維人員保密處理
- 項目的多環境使用便捷性建立在:jar包resources中打包進默認的密鑰,測試環境開發環境無需在jar目錄中準備密鑰,使用默認密鑰即可啓動項目
代碼:
SpringUtils:
package com.wjj.application.util;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.*;
/**
* @author hank
*/
public class SpringUtils {
private SpringUtils(){}
/**
* 讀取jar包中resources路徑下的文本文件
* @param path
* @return
* @throws IOException
*/
public static String readResource(String path) throws IOException {
Resource resource = new ClassPathResource(path);
try(InputStream is = resource.getInputStream()) {
try(InputStreamReader isr = new InputStreamReader(is)) {
try(BufferedReader br = new BufferedReader(isr)) {
String data = null;
StringBuilder content = new StringBuilder();
while ((data = br.readLine()) != null) {
content.append(data);
}
return content.toString();
}
}
}
}
/**
* 讀取文本文件,1.優先在系統相對路徑查找如果沒有2.再查找jar包中的resources目錄下
* @param path
* @return
* @throws IOException
*/
public static String readResourcePrioritySys(String path) throws IOException {
String readRelativeFileStr = FileUtils.readRelativeFile(path);
if(readRelativeFileStr == null){
return readResource(path);
}
return readRelativeFileStr;
}
}
FileUtils:
package com.wjj.application.util;
import java.io.*;
/**
* 文件工具集
* @author hank
* @since 2020/3/9 0009 下午 17:58
*/
public class FileUtils {
/**
* 讀取相對路徑下的的文本文件
* @param filePath
* @return 存在返回內容,不存在返回null
* @throws IOException
*/
public static String readRelativeFile(String filePath) throws IOException {
// 只允許讀取相對目錄文件
String relativeFilePath = "."+ File.separator+filePath;
File file = new File(relativeFilePath);
// 不存在或者不是文件返回null
if(!file.exists() || !file.isFile()){
return null;
}
try(InputStreamReader reader = new InputStreamReader(new FileInputStream(file))) {
try (BufferedReader br = new BufferedReader(reader)) {
StringBuilder content = new StringBuilder();
String data = null;
while ((data = br.readLine()) != null) {
content.append(data);
}
return content.toString();
}
}
}
}
使用實例PayConfig:
package com.wjj.application.config;
import com.wjj.application.util.SpringUtils;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* 支付配置
* @author hank
*/
@Component
@ConfigurationProperties(prefix = "pay")
@Getter @Setter
public class PayConfig implements InitializingBean {
private String payAppId;
/**
* 公鑰
*/
private String pubStr;
/**
* 公鑰路徑
*/
private String pubPath;
/**
* 私鑰路徑
*/
private String priPath;
/**
* 私鑰
*/
private String priStr;
/**
* 通知地址
*/
private String notifyUrl;
@Override
public void afterPropertiesSet() throws Exception {
pubStr = SpringUtils.readResourcePrioritySys(pubPath);
priStr = SpringUtils.readResourcePrioritySys(priPath);
}
}