Sfoglia il codice sorgente

@laijj@补充通用接口业务代码

赖骏劼 2 anni fa
parent
commit
6465c770d2

+ 23 - 4
ipu-show-server/pom.xml

@ -70,10 +70,10 @@
70 70
            <artifactId>junit</artifactId>
71 71
            <scope>test</scope>
72 72
        </dependency>
73
<!--        <dependency>-->
74
<!--            <groupId>org.springframework.boot</groupId>-->
75
<!--            <artifactId>spring-boot-starter-log4j2</artifactId>-->
76
<!--        </dependency>-->
73
        <!--        <dependency>-->
74
        <!--            <groupId>org.springframework.boot</groupId>-->
75
        <!--            <artifactId>spring-boot-starter-log4j2</artifactId>-->
76
        <!--        </dependency>-->
77 77
        <!--通用http接口-->
78 78
        <dependency>
79 79
            <groupId>cn.hutool</groupId>
@ -97,6 +97,12 @@
97 97
            <artifactId>ipu-file-system</artifactId>
98 98
            <version>3.0</version>
99 99
        </dependency>
100
        <!--加密依赖包-->
101
        <dependency>
102
            <groupId>org.bouncycastle</groupId>
103
            <artifactId>bcprov-jdk16</artifactId>
104
            <version>1.43</version>
105
        </dependency>
100 106
    </dependencies>
101 107
102 108
@ -110,6 +116,19 @@
110 116
                <groupId>org.codehaus.mojo</groupId>
111 117
                <artifactId>exec-maven-plugin</artifactId>
112 118
            </plugin>
119
            <!--引用本地jdk,主要是加解密组件需要用到-->
120
            <plugin>
121
                <artifactId>maven-compiler-plugin</artifactId>
122
                <configuration>
123
                    <source>1.8</source>
124
                    <target>1.8</target>
125
                    <encoding>UTF-8</encoding>
126
                    <compilerArguments>
127
                        <bootclasspath>${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/jre/lib/jce.jar</bootclasspath>
128
                        <extdirs>${project.basedir}/libs</extdirs>
129
                    </compilerArguments>
130
                </configuration>
131
            </plugin>
113 132
        </plugins>
114 133
        <finalName>ipu-show-server</finalName>
115 134
    </build>

+ 168 - 2
ipu-show-server/src/main/java/com/ai/ipu/show/bean/CommonBean.java

@ -3,21 +3,25 @@ package com.ai.ipu.show.bean;
3 3
import cn.hutool.http.HttpRequest;
4 4
import com.ai.ipu.basic.log.ILogger;
5 5
import com.ai.ipu.basic.log.IpuLoggerFactory;
6
import com.ai.ipu.server.frame.bean.AbstractBean;
6
import com.ai.ipu.server.config.MobileConfig;
7
import com.ai.ipu.show.core.bean.IpuAppBean;
8
import com.ai.ipu.show.util.AesUtils;
7 9
import com.ailk.common.data.IData;
10
import com.ailk.common.data.impl.DataMap;
8 11
import com.alibaba.fastjson.JSON;
9 12
import com.ai.ipu.show.util.Constant;
10 13
import com.ai.ipu.show.util.SpringContextUtils;
11 14
import org.springframework.core.env.Environment;
12 15
import org.springframework.util.StringUtils;
13 16
17
import java.util.HashMap;
14 18
import java.util.Map;
15 19
16 20
/**
17 21
 * @author
18 22
 * @desc
19 23
 */
20
public class CommonBean extends AbstractBean {
24
public class CommonBean extends IpuAppBean {
21 25
22 26
    /**
23 27
     * 环境参数工具
@ -98,5 +102,167 @@ public class CommonBean extends AbstractBean {
98 102
        sb.setLength(sb.length() - 1);
99 103
        return sb.toString();
100 104
    }
105
106
107
    /**
108
     * 通用公用接口请求方法
109
     *
110
     * @param requestParams
111
     * @return
112
     * @throws Exception
113
     */
114
    public IData commonInterfaceHandler(IData requestParams) throws Exception {
115
        //定义返回参数
116
        IData result = null;
117
        //先检查是否加密
118
        String encryptFlag = MobileConfig.getValue(Constant.COMMON_INTERFACE_KEY_ENCRYPTFLAG, Constant.COMMON_INTERFACE_DEFAULT_VALUE);
119
        String signFlag = MobileConfig.getValue(Constant.COMMON_INTERFACE_KEY_SIGNFLAG, Constant.COMMON_INTERFACE_DEFAULT_VALUE);
120
        //初始化正式参数,默认直接取上传的参数作为真实参数
121
        IData realReqParams = requestParams;
122
        if (Constant.COMMON_INTERFACE_TRUE_VALUE.equals(encryptFlag)) {
123
            //需要解密
124
            realReqParams = decryptReqData(requestParams);
125
        }
126
        if (Constant.COMMON_INTERFACE_TRUE_VALUE.equals(signFlag)) {
127
            //需要验签
128
            if (checkReqSign(realReqParams)) {
129
                result = createErrorMsg(realReqParams, "签名错误,请检查接口签名");
130
                return result;
131
            }
132
        }
133
        //请求类型(post/get)
134
        String requestType = realReqParams.getString(Constant.COMMON_INTERFACE_KEY_REQTYPE);
135
        //接口名称
136
        String interfaceName = realReqParams.getString(Constant.COMMON_INTERFACE_KEY_INTFNAME);
137
        if (StringUtils.isEmpty(requestType) || StringUtils.isEmpty(interfaceName)) {
138
            result = createErrorMsg(realReqParams, "请指定接口名称和请求方式");
139
            return result;
140
        }
141
142
        //重新组装业务请求参数
143
        //请求头内容
144
        Map<String, Object> headParamMap = new HashMap<>();
145
        IData headerDatas = realReqParams.getData(Constant.COMMON_INTERFACE_KEY_HEAD);
146
        for (String key : headerDatas.keySet()) {
147
            headParamMap.put(key, headerDatas.get(key));
148
        }
149
        //处理
150
        Map<String, Object> bodyParamMap = new HashMap<>();
151
        IData bodyDatas = realReqParams.getData(Constant.COMMON_INTERFACE_KEY_DATA);
152
        //请求body内容
153
        for (String key : requestParams.keySet()) {
154
            bodyParamMap.put(key, requestParams.get(key));
155
        }
156
157
        //获取json作为body
158
        String jsonParams = JSON.toJSONString(bodyParamMap);
159
        log.debug("获取到的json字符:jsonParams:" + jsonParams);
160
161
//        //接口加签名参数拼装
162
//        String appId = environment.getProperty(Constant.ENV_INTERFACE_APPID);
163
//        String timestamp = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
164
//        Map<String, String> signParam = new HashMap<String, String>();
165
//        signParam.put("appId", appId);
166
//        signParam.put("timestamp", timestamp);
167
//        // 如果业务参数需要加密,则这里需是加密后的值
168
//        signParam.put("content", jsonParams);
169
//        // 应用密钥
170
//        String key = environment.getProperty(Constant.ENV_INTERFACE_APPKEY);
171
//        //签名参数
172
//        String signValue = "";
173
//        try {
174
//            log.debug("接口签名加密参数:signParam:" + signParam.toString() + ",key:" + key);
175
//            signValue = SignUtil.sign(signParam, "HmacSHA256", key);
176
//            log.debug("接口签名加密结果:signValue:" + signValue);
177
//        } catch (Exception e) {
178
//            log.error("接口签名发生加密异常:" + e.getMessage());
179
//        }
180
181
        //外部接口返回的参数
182
        String reqResult = null;
183
        //请求url拼接
184
        String url = environment.getProperty(Constant.ENV_URL_BASEPATH) + interfaceName;
185
186
        //请求代理
187
        if (Boolean.parseBoolean(environment.getProperty(Constant.ENV_PROXY_FLAG))) {
188
            System.setProperty("http.proxySet", "true");
189
            System.setProperty("http.proxyHost", environment.getProperty(Constant.ENV_PROXY_SERVER));
190
            System.setProperty("http.proxyPort", environment.getProperty(Constant.ENV_PROXY_PORT));
191
        }
192
        //发送请求
193
        if (Constant.COMMON_INTERFACE_VALUE_POST.equalsIgnoreCase(requestType)) {
194
            log.debug("调用远端Post接口,接口请求地址:" + url + ",参数:" + jsonParams);
195
            HttpRequest httpRequest = HttpRequest.post(url);
196
            //添加header
197
            for (String headerKey : headParamMap.keySet()) {
198
                httpRequest.header(headerKey, headParamMap.get(headerKey).toString());
199
            }
200
            reqResult = httpRequest.contentType("application/json")
201
                    .body(jsonParams)
202
                    //超时,毫秒
203
                    .timeout(30000)
204
                    .execute().body();
205
            log.debug("调用远端Post接口,接口请求地址:" + url + ",返回:" + result);
206
        } else {
207
            //get请求,先要把参数转换到url里面
208
            String filterStrs = "requestType,interfaceName,token";
209
            String urlStr = idata2Url(requestParams, filterStrs);
210
            String reqUrl = url + urlStr;
211
            log.debug("调用远端get接口,接口请求地址:" + reqUrl);
212
            HttpRequest httpRequest = HttpRequest.get(reqUrl);
213
            //添加header
214
            for (String headerKey : headParamMap.keySet()) {
215
                httpRequest.header(headerKey, headParamMap.get(headerKey).toString());
216
            }
217
            reqResult = httpRequest
218
                    .contentType("x-www-form-urlencoded")
219
                    //超时,毫秒
220
                    .timeout(30000)
221
                    .execute().body();
222
            log.debug("调用远端get接口,接口请求地址:" + reqUrl + ",返回:" + reqResult);
223
        }
224
        IData retMap = createReturnData();
225
        if (Constant.COMMON_INTERFACE_TRUE_VALUE.equals(encryptFlag) && reqResult != null) {
226
            //需要加密
227
            String resultEncrypt = AesUtils.aes256ECBPkcs7PaddingHexEncrypt(reqResult, Constant.AES_KEY);
228
            retMap.put(Constant.COMMON_INTERFACE_KEY_DATA, resultEncrypt);
229
        } else {
230
            retMap.put(Constant.COMMON_INTERFACE_KEY_DATA, reqResult);
231
        }
232
        return retMap;
233
    }
234
235
    /**
236
     * 解密入参
237
     *
238
     * @param reqData
239
     * @return
240
     */
241
    public static IData decryptReqData(IData reqData) throws Exception {
242
        IData retIdata = new DataMap();
243
        //处理接口请求参数加解密
244
        String dataSrcStr = reqData.getString(Constant.COMMON_INTERFACE_KEY_DATA);
245
        log.debug("接口参数密文:" + dataSrcStr);
246
        if (dataSrcStr != null && dataSrcStr.length() > 0) {
247
            String dataJson = AesUtils.aes256ECBPkcs7PaddingHexDecrypt(dataSrcStr, Constant.AES_KEY);
248
            log.debug("接口参数解密后明文:" + dataJson);
249
            //把接口参数再次构造成DataMap赋值给参数对象
250
            retIdata = new DataMap(dataJson);
251
252
        }
253
        return retIdata;
254
    }
255
256
    /**
257
     * 签名验证方法
258
     *
259
     * @param reqData
260
     * @return
261
     * @throws Exception
262
     */
263
    public static boolean checkReqSign(IData reqData) throws Exception {
264
        //TODO Junjie.Lai 方法实现
265
        return true;
266
    }
101 267
}
102 268

+ 112 - 0
ipu-show-server/src/main/java/com/ai/ipu/show/util/AesUtils.java

@ -0,0 +1,112 @@
1
package com.ai.ipu.show.util;
2
3
import org.bouncycastle.jce.provider.BouncyCastleProvider;
4
5
import javax.crypto.Cipher;
6
import javax.crypto.spec.SecretKeySpec;
7
import java.nio.charset.StandardCharsets;
8
import java.security.Security;
9
import java.util.Base64;
10
11
/**
12
 * AES加密工具类
13
 */
14
public class AesUtils {
15
    private static final String SECRET = "AES";
16
    private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";
17
18
    static {
19
        Security.addProvider(new BouncyCastleProvider());
20
    }
21
22
    /**
23
     * AES加密ECB模式PKCS7Padding填充方式(Base64编码)
24
     * @param str 字符串
25
     * @param key 密钥
26
     * @return 加密字符串
27
     * @throws Exception 异常信息
28
     */
29
    public static String aes256ECBPkcs7PaddingEncrypt(String str, String key) throws Exception {
30
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
31
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
32
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, SECRET));
33
        byte[] doFinal = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
34
        return new String(Base64.getEncoder().encode(doFinal));
35
    }
36
37
    public static String encodeHexString(byte[] data) {
38
        StringBuilder sb = new StringBuilder();
39
        for (byte b : data) {
40
            sb.append(String.format("%02x", b));
41
        }
42
        return sb.toString();
43
    }
44
45
    public static String aes256ECBPkcs7PaddingHexEncrypt(String str, String key) throws Exception {
46
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
47
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
48
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, SECRET));
49
        byte[] doFinal = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
50
        return new String(encodeHexString(doFinal));
51
    }
52
53
54
55
    /**
56
     * AES解密ECB模式PKCS7Padding填充方式(Base64编码)
57
     * @param str 字符串
58
     * @param key 密钥
59
     * @return 解密字符串
60
     * @throws Exception 异常信息
61
     */
62
    public static String aes256ECBPkcs7PaddingDecrypt(String str, String key) throws Exception {
63
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
64
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
65
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, SECRET));
66
        byte[] doFinal = cipher.doFinal(Base64.getDecoder().decode(str));
67
        return new String(doFinal);
68
    }
69
70
71
    public static byte[] hexStringToByteArray(String hexString) {
72
        hexString = hexString.replaceAll(" ", "");
73
        int len = hexString.length();
74
        byte[] bytes = new byte[len / 2];
75
        for (int i = 0; i < len; i += 2) {
76
            // 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个字节
77
            bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
78
                    .digit(hexString.charAt(i+1), 16));
79
        }
80
        return bytes;
81
    }
82
    /**
83
     * AES解密ECB模式PKCS7Padding填充方式(Hex编码)
84
     * @param str 字符串
85
     * @param key 密钥
86
     * @return 解密字符串
87
     * @throws Exception 异常信息
88
     */
89
    public static String aes256ECBPkcs7PaddingHexDecrypt(String str, String key) throws Exception {
90
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
91
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
92
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, SECRET));
93
        byte[] doFinal = cipher.doFinal(hexStringToByteArray(str));
94
        return new String(doFinal);
95
    }
96
97
    public static void main(String[] args) throws Exception {
98
        String str = "fjadmin";
99
        System.out.println("字符串:" + str);
100
        String encryptStr = AesUtils.aes256ECBPkcs7PaddingEncrypt(str, "abcdefXXABCDEFxx");
101
        System.out.println("Base64编码,加密后字符串:" + encryptStr);
102
103
        String decryptStr = AesUtils.aes256ECBPkcs7PaddingDecrypt(encryptStr, "abcdefXXABCDEFxx");
104
        System.out.println("Base64编码,解密后字符串:" + decryptStr);
105
106
        String hexEncryptStr = AesUtils.aes256ECBPkcs7PaddingHexEncrypt(str, "abcdefXXABCDEFxx");
107
        System.out.println("Hex编码,加密后字符串:" + hexEncryptStr);
108
109
        String hexDecryptStr = AesUtils.aes256ECBPkcs7PaddingHexDecrypt(hexEncryptStr, "abcdefXXABCDEFxx");
110
        System.out.println("Hex编码,解密后字符串:" + hexDecryptStr);
111
    }
112
}

+ 51 - 0
ipu-show-server/src/main/java/com/ai/ipu/show/util/Constant.java

@ -89,4 +89,55 @@ public class Constant {
89 89
     */
90 90
    public static final String FILE_SAVE_PATH = "appserver.file.savepath";
91 91
92
    /**通用接口固定参数*/
93
    /**
94
     * 请求数据加密标识
95
     */
96
    public static final String COMMON_INTERFACE_KEY_ENCRYPTFLAG = "commInterfaceEncrypt";
97
98
    /**
99
     * 请求数据签名标识
100
     */
101
    public static final String COMMON_INTERFACE_KEY_SIGNFLAG = "commInterfaceSign";
102
103
    /**
104
     * AES加解密的KEY
105
     */
106
    public static final String AES_KEY = "onLineTradeTKAMC";
107
108
    /**
109
     * 参数标识,默认false
110
     */
111
    public static final String COMMON_INTERFACE_DEFAULT_VALUE = "false";
112
113
    /**
114
     * 参数标识,true
115
     */
116
    public static final String COMMON_INTERFACE_TRUE_VALUE = "true";
117
    /**
118
     * 接口请求类型
119
     */
120
    public static final String COMMON_INTERFACE_KEY_REQTYPE = "requestType";
121
122
    /**
123
     * 接口请求值
124
     */
125
    public static final String COMMON_INTERFACE_VALUE_POST = "POST";
126
    public static final String COMMON_INTERFACE_VALUE_GET = "GET";
127
128
    /**
129
     * 接口名称
130
     */
131
    public static final String COMMON_INTERFACE_KEY_INTFNAME = "interfaceName";
132
133
    /**
134
     * 发送到后端的请求head
135
     */
136
    public static final String COMMON_INTERFACE_KEY_HEAD = "head";
137
138
    /**
139
     * 发送到后端的请求data
140
     */
141
    public static final String COMMON_INTERFACE_KEY_DATA = "data";
142
92 143
}

+ 4 - 0
ipu-show-server/src/main/resources/server-config.xml

@ -21,6 +21,10 @@
21 21
    <config name="indexPage" value="Index"/>
22 22
    <!-- 文件是否加密 -->
23 23
    <config name="fileEncrypt" value="true"/>
24
    <!--通用接口是否加密-->
25
    <config name="commInterfaceEncrypt" value="false"/>
26
    <!--通用接口是否签名-->
27
    <config name="commInterfaceSign" value="false"/>
24 28
    <!-- 自定义异常管理器 -->
25 29
    <config name="exceptionHandler" value="com.ai.ipu.show.core.handler.IpuExceptionHandler"/>
26 30
    <!-- 自定义Session管理器 -->

+ 4 - 1
ipu-show-server/src/main/resources/server-data.xml

@ -5,7 +5,6 @@
5 5
    <!-- 模拟发送验证码 -->
6 6
    <action name="LoginBean.sendVerificationCode" class="com.ai.ipu.show.bean.LoginBean" method="sendVerificationCode" verify="false"></action>
7 7
8
    as>
9 8
    <!-- 上传下载 -->
10 9
    <action name="UploadDownloadBean.download" 	class="com.ai.ipu.show.bean.UploadDownloadBean" method="download" verify="false"></action>
11 10
    <action name="UploadDownloadBean.upload" 	class="com.ai.ipu.show.bean.UploadDownloadBean" method="upload" 	verify="false"></action>
@ -61,4 +60,8 @@
61 60
62 61
    <!-- 通用转发接口 -->
63 62
    <action name="CommonBean.interfaceHandler" class="com.ai.ipu.show.bean.CommonBean" method="interfaceHandler" verify="false"></action>
63
64
    <!-- 通用转发功能接口,参数已经过优化处理,支持加密和验签 -->
65
    <action name="CommonBean.commonInterfaceHandler" class="com.ai.ipu.show.bean.CommonBean" method="commonInterfaceHandler" verify="false"></action>
66
64 67
</datas>