java接⼝开发参数加密_常见开放接⼝签名简单实现-请求参数
排序加密
常见的签名⽅式实现⼀般分为以下⼏个步骤 :
1 . 将所有(或者特殊)请求参数按特定规则排序;
2 . 将请求参数按特定规则拼装为加密字符串;
3 . 加密算法对加密字符串进⾏加密,得到签名。
下⾯⾃⼰写了⼀个常见的实现⽅式,以便记录,这⾥只是⽰例说明基本常规实现,使⽤则还是根据项⽬的真实情况去选择。
例如,下⾯我简单实现了⼀个restful接⼝,/signTest去验证签名。
1.我这⾥使⽤了MD5加密⽅式,⾸先在l加⼊依赖。
commons-codec
commons-codec
1.10
2 . 因为会对请求的参数进⾏处理,主要是为了获取到所有的请求参数,我写了⼀个⾃定义的HttpUtils.java :
importjavax.servlet.http.HttpServletRequest;importjava.io.UnsupportedEncodingException;importjava.URLDecoder;importjav Created by EalenXie on 2018/6/13 12:47*/
public enumHttpUtils {
getHttpUtil;//获取请求IP
public staticString getIpAddress(HttpServletRequest request) {
String ip= Header("x-forwarded-for");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
ip= Header("Proxy-Client-IP");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
ip= Header("WL-Proxy-Client-IP");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
ip= Header("HTTP_CLIENT_IP");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
ip= Header("HTTP_X_FORWARDED_FOR");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
RemoteAddr();returnip;
}//将请求参数转换成Map
public static MapgetUrlParams(HttpServletRequest request) {
String param= "";try{
param= URLDecoder.QueryString(), "utf-8");
}catch(UnsupportedEncodingException e) {
e.printStackTrace();
}
Map result = new HashMap<>();
String[] params= param.split("&");for(String s : params) {
Integer index= s.indexOf("=");
result.put(s.substring(0, index), s.substring(index + 1));
}returnresult;
}//从请求中获取所有参数
public static SortedMap getAllParams(HttpServletRequest request, MappostParams) {
SortedMap result = new TreeMap<>();
Map urlParams =getUrlParams(request);for(Map.Entry entry : Set()) {
result.put((String) Key(), (String) Value());
}if (postParams != null) {for(Map.Entry entry : Set()) {
result.put((String) Key(), (String) Value());
}
}returnresult;
}
}
3 . 签名⼯具类,实现签名机制 SignUtils.java :
dec.digest.DigestUtils;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springfra Created by EalenXie on 2018/6/13 9:31*/
public enumSignUtil {
getSignUtil;private static final Logger logger = Logger(SignUtil.class);/***@paramparams 所有的请求参数都
会在这⾥进⾏排序加密
*@return得到签名*/
public String getSign(SortedMapparams) {
StringBuilder sb= newStringBuilder();for(Map.Entry entry : Set()) {if (!Key().equals("sign")) { //拼装参数,
排除sign
if (!StringUtils.Key()) && !StringUtils.Value()))
sb.Key()).Value());
}
}
logger.info("Before Sign : {}", sb.toString());returnDigestUtils.String()).toUpperCase();
}/***@paramparams 所有的请求参数都会在这⾥进⾏排序加密
*@return验证签名结果*/
public boolean verifySign(SortedMapparams) {if (params == null || StringUtils.("sign"))) return false;
String sign=getSign(params);
logger.info("verify Sign : {}", sign);return !StringUtils.isEmpty(sign) && ("sign").equals(sign);
}
}
4 . SendGoodsController.java 提供Rest接⼝ /signTest。
packagecom.wuxicloud.web;importcom.wuxicloud.util.HttpUtils;importcom.wuxicloud.util.SignUtil;import
org.springframework.web.bind.annotation.*;importjavax.servlet.http.HttpServletRequest;straints.Null;impor Created by EalenXie on 2018/6/13 11:54*/@RestController
@CrossOrigin//加个注解,解决前端调接⼝跨域,这⾥只是为了⽅便测试,真实情况慎⽤。
public classSendGoodsController {
@RequestMapping("/signTest")
@ResponseBodypublic Map sendGood(@RequestBody(required = false) Mapparams, HttpServletRequest request) {
SortedMap allParams =AllParams(request, params);boolean isSigned
=SignUtil.verifySign(allParams);
Map result= new HashMap<>();if (isSigned) result.put("flag","Signed Success!");else result.put("flag","Signed
Fail");returnresult;
}
}
5 . 启动类,此时服务器端的代码已经准备好了。
importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;/*** Created by EalenXie on 2018/6/13 11:52*/@SpringBootApplicationpublic classGoodsApplication {public static
voidmain(String[] args) {
SpringApplication.run(GoodsApplication.class, args);
}
}
6。此时,假设某前端页⾯要调⽤该接⼝,应该怎么做呢?
1 . 将请求接⼝的参数按照与服务器相同规则进⾏排序;
2 . 将请求接⼝的参数按照与服务器相同规则拼装为加密字符串;
3 . 与服务器相同的加密算法实现加密,得到签名;
针对本例中的签名⽅式,我下⾯写了⼀个基本的实现。
1.因为使⽤到MD5,到⽹上去下载了⼀个md5.min.js(这个js有⽹上⼀⼤把);js获取json的key和value
2.下个jquery.min.js;
3.⾃⼰实现的签名⽅式 Sign.js :
/**
* Created by EalenXie on 2018/6/13 15:11*/
/**
* @param url 请求的url,应该包含请求参数(url的?后⾯的参数)
* @param requestParams 请求参数(POST的JSON参数)
* @returns {string} 获取签名*/
functiongetSign(url, requestParams) {var signString = "";var urlParams =parseQueryString(url);var requestBody
=sortObject(mergeObject(urlParams, requestParams));for (var i inrequestBody) {
signString+= i +requestBody[i];
}returnmd5.hex(signString).toUpperCase();
}/**
* @param url 请求的url
* @returns {{}} 将url中请求参数组装成json对象(url的?后⾯的参数)*/
functionparseQueryString(url) {var urlReg = /^[^\?]+\?([\w\W]+)$/,
paramReg= /([^&=]+)=([\w\W]*?)(&|$|#)/g,
(url),
result={};if (urlArray && urlArray[1]) {var paramString = urlArray[1], paramResult;while ((paramResult =
<(paramString)) != null) {
result[paramResult[1]] = paramResult[2];
}
}returnresult;
}/**
* @param object 传⼊要进⾏属性排序的对象
* @returns {{}} 将对象进⾏属性排序(按⾸字母顺序进⾏排序)*/
functionsortObject(object) {var objectKeys =Object.keys(object).sort();var result ={};for (var i inobjectKeys) {
result[objectKeys[i]]=object[objectKeys[i]];
}returnresult;
}/**
* @returns {*} 将两个对象合并成⼀个*/
functionmergeObject(objectOne, objectTwo) {if (objectTwo != null) {for (var key inobjectTwo) {
objectOne[key]=objectTwo[key]
}
}returnobjectOne;
}
进⾏测试的test.html :
varurl= "localhost:8080/signTest?time=2018-06-13 15:43";varrequestParam= {"username":"EalenXie","password":"admin","gender":"男","age":23};functiontest() {varsign=getSign(url, requestParam);//根据Url和请求参数得到签名
varrequestUrl=url+= "&sign=" +sign;//将签名添加在请求参数后⾯去请求接⼝
$.ajax({
type:'POST',//GET请求效果相同
headers: {'Access-Control-Allow-Origin':"*","content-type":"application/json","Accept":"application/json"}, async:false,
url: requestUrl,
data: JSON.stringify(requestParam),
dataType:'json',
success:function(response) {
alert(response.flag);
}
});
}
Title
点击测试
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论