如何實現微信小程序接口加密

責任編輯:福建福彩快3开奖结果 //www.yhrpv.com/



福建福彩快3开奖结果請求的所有接口參數必須加密,如何實現小程序接口加密。  

如何實現微信小程序接口加密  

微信applet接口實現加密教程:  

場景 

小程序請求的所有接口參數必須加密,后臺返回的數據也需要加密,添加了令牌驗證。  

首先,小程序結束函數 

 1,下載aesUtil.js源碼的Js版本。 

 [注意:所有相關的類文件都將在文章末尾發布]  

 2,下載md5.js源碼的Js版本。 

 3, pulic.js中的加密和解密操作代碼如下,其中密鑰和密鑰偏移與背景一致。

var CryptoJS = require('aesUtil.js'); //引用AES源碼js

var md5 = require('md5.js')

 

var key = CryptoJS.enc.Utf8.parse("76CAA1C88F7F8D1D"); //十六位十六進制數作為秘鑰

var iv = CryptoJS.enc.Utf8.parse('91129048100F0494'); //十六位十六進制數作為秘鑰偏移量

//解密方法

function Decrypt(word) {

var encryptedHexStr = CryptoJS.enc.Hex.parse(word);

var srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);

var decrypt = CryptoJS.AES.decrypt(srcs, key, {

iv: iv,

mode: CryptoJS.mode.CBC,

padding: CryptoJS.pad.Pkcs7

});

var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);

return decryptedStr.toString();

}

//加密方法

function Encrypt(word) {

var srcs = CryptoJS.enc.Utf8.parse(word);

var encrypted = CryptoJS.AES.encrypt(srcs, key, {

iv: iv,

mode: CryptoJS.mode.CBC,

padding: CryptoJS.pad.Pkcs7

});

return encrypted.ciphertext.toString().toUpperCase();

}

 

//暴露接口

module.exports.Decrypt = Decrypt;

module.exports.Encrypt = Encrypt;

4.在網絡請求幫助類中進行參數的加密和返回數據的解密操作。


 

var aes = require('../utils/public.js')

var md5 = require("../utils/md5.js")

 

...

 

/**

* 網絡請求

*/

function request(method, loading, url, params, success, fail) {

var url = BASE_URL + url;

//請求參數轉為JSON字符串

var jsonStr = JSON.stringify(params);

console.log(url + ' params=> ' + jsonStr)

//根據特定規則生成Token

var token = productionToken(params);

//加密請求參數

var aesData = aes.Encrypt(jsonStr)

console.log('請求=>明文參數:' + jsonStr)

console.log('請求=>加密參數:' + aesData)

...

wx.request({

url: url,

method: method,

header: {

'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',

'Token': token

},

data: {

aesData: aesData

},

// data: params,

success: function(res) {

//判斷請求結果是否成功

if (res.statusCode == 200 && res.data != '' && res.data != null) {

//解密返回數據

console.log('返回=>加密數據:' + res.data);

var result = aes.Decrypt(res.data);

console.log('返回=>明文數據:'+result);

success(JSON.parse(result))

} else {

fail()

}

},

fail: function(res) {

fail()

},

})

}

其中生成Token的規則,【生成Token的規則可根據具體的業務邏輯自己定義,我這里使用的規則是根據請求參數的字母排序取其value并加上當前時間戳再進行MD5加密】


 

/**

* 生成Token

*/

function productionToken(params) {

var obj = util.objKeySort(params);

var value = '';

for (var item in obj) {

value += obj[item];

}

//加上當前時間戳

value += util.getTokenDate(new Date())

//去除所有空格

value = value.replace(/\s+/g, "")

//進行UTF-8編碼

value = encodeURI(value);

//進行MD5碼加密

value = md5.hex_md5(value)

return value;

}

//util的排序函數

function objKeySort(obj) {

//先用Object內置類的keys方法獲取要排序對象的屬性名,再利用Array原型上的sort方法對獲取的屬性名進行排序,newkey是一個數組

var newkey = Object.keys(obj).sort();

//創建一個新的對象,用于存放排好序的鍵值對  

var newObj = {};

//遍歷newkey數組

for (var i = 0; i < newkey.length; i++) {

//向新創建的對象中按照排好的順序依次增加鍵值對

newObj[newkey[i]] = obj[newkey[i]];

}

//返回排好序的新對象

return newObj;

}

二,服務器函數編寫 

由于最初的SpringMVC,使用的方法不一定是最好的和最好的。如果出現問題,請查看建議和建議:  

請求參數被過濾器截獲,參數由自定義參數包裝器解密。 

攔截器獲取請求的令牌并生成服務器端令牌以進行驗證。 

返回參數由JSON轉換器加密。  

 1,重寫HttpServletRequestWrapper并處理自定義HttpServletRequestWrapper 

中的參數

/**

* Describe:請求參數包裝器 主要作用的過濾參數并解密

* Created by 吳蜀黍 on 2018-08-07 09:37

**/

@Slf4j

public class ParameterRequestWrapper extends HttpServletRequestWrapper {

 

private Map<String, String[]> params = new HashMap<>();

 

@SuppressWarnings("unchecked")

public ParameterRequestWrapper(HttpServletRequest request) {

// 將request交給父類,以便于調用對應方法的時候,將其輸出,其實父親類的實現方式和第一種new的方式類似

super(request);

//將參數表,賦予給當前的Map以便于持有request中的參數

this.params.putAll(request.getParameterMap());

this.modifyParameterValues();

}

 

//重載一個構造方法

public ParameterRequestWrapper(HttpServletRequest request, Map<String, Object> extendParams) {

this(request);

addAllParameters(extendParams);//這里將擴展參數寫入參數表

}

 

private void modifyParameterValues() {//將parameter的值去除空格后重寫回去

 

//獲取加密數據

String aesParameter = getParameter(Constants.NetWork.AES_DATA);

log.debug("[modifyParameterValues]==========>加密數據:{}", aesParameter);

//解密

String decryptParameter = null;

try {

decryptParameter = AesUtils.decrypt(aesParameter, Constants.AES.AES_KEY);

log.debug("[modifyParameterValues]==========> 解密數據:{}", decryptParameter);

Map<String, Object> map = JSON.parseObject(decryptParameter);

Set<String> set = map.keySet();

for (String key : set) {

params.put(key, new String[]{String.valueOf(map.get(key))});

}

aesFlag(true);

} catch (CommonBusinessException e) {

aesFlag(false);

log.error("[modifyParameterValues]", e);

log.debug("[modifyParameterValues]==========>", e);

}

}

 

/**

* 解密成功標志

*/

private void aesFlag(boolean flag) {

params.put(Constants.NetWork.AES_SUCCESS, new String[]{String.valueOf(flag)});

}

 

@Override

public Map<String, String[]> getParameterMap() {

// return super.getParameterMap();

return params;

}

 

@Override

public Enumeration<String> getParameterNames() {

return new Vector<>(params.keySet()).elements();

}

 

@Override

public String getParameter(String name) {//重寫getParameter,代表參數從當前類中的map獲取

String[] values = params.get(name);

if (values == null || values.length == 0) {

return null;

}

return values[0];

}

 

public String[] getParameterValues(String name) {//同上

return params.get(name);

}

 

 

public void addAllParameters(Map<String, Object> otherParams) {//增加多個參數

for (Map.Entry<String, Object> entry : otherParams.entrySet()) {

addParameter(entry.getKey(), entry.getValue());

}

}

 

 

public void addParameter(String name, Object value) {//增加參數

if (value != null) {

if (value instanceof String[]) {

params.put(name, (String[]) value);

} else if (value instanceof String) {

params.put(name, new String[]{(String) value});

} else {

params.put(name, new String[]{String.valueOf(value)});

}

}

}

}

新建過濾器,在攔截器中調用自定義的參數包裝器


 

/**

* Describe:請求參數過濾器

* Created by 吳蜀黍 on 2018-08-07 10:02

**/

@Slf4j

public class ParameterFilter implements Filter {

@Override

public void init(FilterConfig filterConfig) throws ServletException {

}

 

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

//使用自定義的參數包裝器對參數進行處理

ParameterRequestWrapper requestWrapper = new ParameterRequestWrapper((HttpServletRequest) servletRequest);

filterChain.doFilter(requestWrapper, servletResponse);

}

 

@Override

public void destroy() {

}

}

web.xml中對過濾器進行配置


 

<!--過濾器-->

<filter>

<filter-name>parameterFilter</filter-name>

<filter-class>com.xxx.xxx.config.filter.ParameterFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>parameterFilter</filter-name>

<!-- 過濾所有以.json結尾的資源-->

<url-pattern>*.json</url-pattern>

</filter-mapping>

AES加解密操作


 

/**

* Describe:AES 加密

* Created by 吳蜀黍 on 2018-08-03 17:47

**/

public class AesUtils {

private static final String CHARSET_NAME = "UTF-8";

private static final String AES_NAME = "AES";

private static final String ALGORITHM = "AES/CBC/PKCS7Padding";

private static final String IV = Constants.AES.AES_IV;

 

static {

Security.addProvider(new BouncyCastleProvider());

}

 

/**

* 加密

*/

public static String encrypt(@NotNull String content, @NotNull String key) throws CommonBusinessException {

try {

Cipher cipher = Cipher.getInstance(ALGORITHM);

SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(CHARSET_NAME), AES_NAME);

AlgorithmParameterSpec paramSpec = new IvParameterSpec(IV.getBytes());

cipher.init(Cipher.ENCRYPT_MODE, keySpec, paramSpec);

return ParseSystemUtil.parseByte2HexStr(cipher.doFinal(content.getBytes(CHARSET_NAME)));

} catch (Exception ex) {

throw new CommonBusinessException("加密失敗");

}

}

 

/**

* 解密

*/

public static String decrypt(@NotNull String content, @NotNull String key) throws CommonBusinessException {

try {

Cipher cipher = Cipher.getInstance(ALGORITHM);

SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(CHARSET_NAME), AES_NAME);

AlgorithmParameterSpec paramSpec = new IvParameterSpec(IV.getBytes());

cipher.init(Cipher.DECRYPT_MODE, keySpec, paramSpec);

return new String(cipher.doFinal(Objects.requireNonNull(ParseSystemUtil.parseHexStr2Byte(content))), CHARSET_NAME);

} catch (Exception ex) {

throw new CommonBusinessException("解密失敗");

}

}

 

}

2.新建攔截器,驗證Token以及解密的判斷


 

 

@Override

public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {

//如果不是映射到方法直接通過

if (!(handler instanceof HandlerMethod)) {

return true;

}

//判斷參數包裝器中對請求參數的解密是否成功

boolean aesSuccess = Boolean.parseBoolean(httpServletRequest.getParameter(Constants.NetWork.AES_SUCCESS));

if (!aesSuccess) {

this.sendMsg(Constants.NetWork.CODE_DECRYPTION_FAILURE, Constants.NetWork.MEG_AES_FAIL, httpServletResponse);

return false;

}

//獲取客戶端上傳Token

String token = httpServletRequest.getHeader(Constants.NetWork.TOKEN_HEAD_KEY);

if (StringUtils.isNullOrEmpty(token)) {

sendMsg(Constants.NetWork.CODE_TOKEN_INVALID, Constants.NetWork.MSG_TOKEN_EMPTY, httpServletResponse);

return false;

}

//驗證Token的有效性

if (!TokenUtils.verificationToken(token, httpServletRequest.getParameterMap())) {

sendMsg(Constants.NetWork.CODE_TOKEN_INVALID, Constants.NetWork.MSG_TOKEN_INVALID, httpServletResponse);

return false;

}

return true;

}

 

/**

* 驗證失敗 發送消息

*/

private void sendMsg(String msgCode, String msg, HttpServletResponse httpServletResponse) throws IOException {

httpServletResponse.setContentType("application/json; charset=utf-8");

PrintWriter writer = httpServletResponse.getWriter();

String jsonString = JSON.toJSONString(StandardResult.create(msgCode, msg));

try {

//對驗證失敗的返回信息進行加密

jsonString = AesUtils.encrypt(jsonString, Constants.AES.AES_KEY);

} catch (CommonBusinessException e) {

e.printStackTrace();

jsonString = null;

log.error("[sendMsg]", e);

}

writer.print(jsonString);

writer.close();

httpServletResponse.flushBuffer();

}

在spring中對攔截器注冊


 

<mvc:interceptors>

<!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 -->

<mvc:interceptor>

<!-- 攔截所有請求 -->

<mvc:mapping path="/**"/>

<!-- 需排除攔截的地址 -->

<!--<mvc:exclude-mapping path="/"/>-->

<bean class="com.xxx.xxx.config.interceptor.AsyncHandlerInterceptor"/>

</mvc:interceptor>

</mvc:interceptors>

Token的驗證


 

 

/**

* Describe:Token幫助類

* Created by 吳蜀黍 on 2018-08-04 14:48

**/

@Slf4j

public class TokenUtils {

/**

* 驗證Token

*

* @param token 客戶端上傳Token

* @param mapTypes 請求參數集合

* @return boolean

*/

public static boolean verificationToken(String token, Map mapTypes) {

try {

return StringUtils.saleEquals(token, getToken(mapTypes));

} catch (UnsupportedEncodingException e) {

log.error("[verificationToken]", e);

return false;

}

}

 

 

/**

* 通過客戶端請求參數產生Token

*/

private static String getToken(Map mapTypes) throws UnsupportedEncodingException {

List<String> mapKes = new ArrayList<>();

for (Object obj : mapTypes.keySet()) {

String value = String.valueOf(obj);

//去除參數中的加密相關key

if (StringUtils.saleEquals(value, Constants.NetWork.AES_SUCCESS) ||

StringUtils.saleEquals(value, Constants.NetWork.AES_DATA)) {

break;

}

mapKes.add(value);

}

//排序key

Collections.sort(mapKes);

StringBuilder sb = new StringBuilder();

for (String key : mapKes) {

String value = ((String[]) mapTypes.get(key))[0];

sb.append(value);

}

//加上時間戳,去除所有空格 進行MD5加密

String string = sb.append(DateUtils.getDateStr(DateUtils.FORMAT_YYYYMMDDHH)).toString().replace(" ", "");

return MD5.getMD5(URLEncoder.encode(string, "UTF-8"));

}

}

3.對返回數據進行加密處理,新建JSON轉換器繼承自阿里的FastJsonHttpMessageConverter


 

/**

* Describe:Json轉換器 將返回數據加密

* Created by 吳蜀黍 on 2018-08-07 13:57

**/

@Slf4j

public class JsonMessageConverter extends FastJsonHttpMessageConverter {

 

@Override

protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException,

HttpMessageNotWritableException {

OutputStream out = outputMessage.getBody();

try {

String jsonString = JSON.toJSONString(object);

log.debug("[writeInternal]======>返回明文數據:{}" + jsonString);

//對返回數據進行AES加密

jsonString = AesUtils.encrypt(jsonString, Constants.AES.AES_KEY);

log.debug("[writeInternal]======>返回加密數據:{}" + jsonString);

out.write(jsonString.getBytes());

} catch (CommonBusinessException e) {

e.printStackTrace();

log.error("[writeInternal]======>", e);

}

out.close();

}

}

spring中對JSON轉換器進行配置


 

<mvc:message-converters>

<!--<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">-->

<bean class="com.xxx.xxx.config.converter.JsonMessageConverter">

<property name="supportedMediaTypes">

<list>

<value>text/html;charset=UTF-8</value>

<value>application/json</value>

<value>application/xml;charset=UTF-8</value>

</list>

</property>

<property name="features">

<list>

<!-- 默認的意思就是不配置這個屬性,配置了就不是默認了 -->

<!-- 是否輸出值為null的字段 ,默認是false-->

<value>WriteMapNullValue</value>

<value>WriteNullNumberAsZero</value>

<value>WriteNullListAsEmpty</value>

<value>WriteNullStringAsEmpty</value>

<value>WriteNullBooleanAsFalse</value>

<value>WriteDateUseDateFormat</value>

</list>

</property>

</bean>

</mvc:message-converters>

以上就是微信小程序接口加密如何實現的開發文檔,更多福建福彩快3开奖结果文檔可以關注網站。




澤群一站式網絡服務機構竭誠為您提供:

福建福彩快3开奖结果,福建福彩快3开奖结果,福建福彩快3开奖结果,福建福彩快3开奖结果,福建福彩快3开奖结果,福建福彩快3开奖结果,福建福彩快3开奖结果,福建福彩快3开奖结果,SEO優化,模板建站,云服務等服務

相關資訊