项目中要请求JAVA接口,发现PHP的md5加密和对方JAVA的md5加密不一致。
请问PHP的要如何写才能和JAVA的一致。
尝试了很多种方法都不行。
下面是JAVA代码。
最后是尝试的PHP代码,求指点。
(主要是和EnUtil.sign(params);返回的结果中sign的值不对应。sign=‘参数名=’.'参数值‘.'&参数名=’.'参数值‘.flysoft.jxsexchange,后再md5加密)
已解决:
通过打印java待加密字符串,得知java字符拼接和php的不一样。
调整php字符串组合顺序后,md5加密结果一致。
浏览器测试通过:
但是现在遇到了新的问题,无论采用curlGet还是curlPost都接收不到数据,但是浏览器直接访问却可以
我猜测,是因为在线运行php代码,是走的网站服务器ip,与内网不通,无法正常访问。
cmd直接ping ip是通的,但是通过网页ping ip是不通的。
目标环境是UOS系统,没有安装php环境,所以无法通过远程直接调试。
代码:
\java\oa\src\EnUtil\Oa.java
package EnUtil;
import java.net.http.HttpRequest;
import java.util.HashMap;
import java.util.Map;
class Oa
{
public static void main (String[] args)
{
String username = "wyxz";
String password = "wyzx123";
Map<String, Object> params = new HashMap<String, Object>();
params.put("username", username);
params.put("password", password);
params = EnUtil.sign(params);
String resultStr = HttpRequest.post("http://10.22.231.177:8080/wydatacenter/services/getMailInfo")
.form(params)
.timeout(10000)
.execute().body();
System.out.printIn(resultStr);
}
}
\java\oa\src\EnUtil\Oa.javaEnUtil.java
package EnUtil;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
/**
* @ClassName EnUtil
* @Description: token
* @Author ybb
* @Date 2021-7-19
* @Version V1.0
**/
public class EnUtil {
/**
* 加密密钥
*/
private final static String SECRET_KEY = "flysoft.jxsexchange";
/**
* 字符编码
*/
private final static String INPUT_CHARSET = "UTF-8";
/**
* 生成要请求的签名参数数组
*
* @param sParaTemp 需要签名的参数
* @return 要请求的签名参数数组
*/
public static Map<String, Object> sign(Map<String, Object> sParaTemp) {
sParaTemp.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
Map<String, Object> sPara = paraFilter(sParaTemp);
//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
String prestr = createLinkString(sPara);
String mysign = getMD5Str(prestr + SECRET_KEY);
sPara.put("sign", mysign);
return sPara;
}
/**
* 生成要请求的签名参数字符串“参数=参数值”&链接
*
* @param sParaTemp 需要签名的参数
* @return
*/
public static String signString(Map<String, Object> sParaTemp) {
Map<String, Object> sign = sign(sParaTemp);
return createLinkString(sign, true);
}
/**
* 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
*
* @param params 需要排序并参与字符拼接的参数组
* @return 拼接后字符串
*/
public static String createLinkString(Map<String, Object> params) {
return createLinkString(params, false);
}
/**
* 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
*
* @param params 需要排序并参与字符拼接的参数组
* @param encode 是否需要UrlEncode
* @return 拼接后字符串
*/
public static String createLinkString(Map<String, Object> params, boolean encode) {
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = (String)params.get(key);
if (encode)
value = urlEncode(value, INPUT_CHARSET);
if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
/**
* URL转码
*
* @param content
* @param charset
* @return
*/
private static String urlEncode(String content, String charset) {
try {
return URLEncoder.encode(content, charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
/**
* 除去数组中的空值和签名参数
*
* @param sArray 签名参数组
* @return 去掉空值与签名参数后的新签名参数组
*/
public static Map<String, Object> paraFilter(Map<String, Object> sArray) {
Map<String, Object> result = new HashMap<String, Object>();
if (sArray == null || sArray.size() <= 0) {
return result;
}
for (String key : sArray.keySet()) {
String value = (String)sArray.get(key);
if (value == null || value.equals("") || key.equalsIgnoreCase("sign")) {
continue;
}
result.put(key, value);
}
return result;
}
public static String getMD5Str(String str) {
byte[] digest = null;
try {
MessageDigest md5 = MessageDigest.getInstance("md5");
digest = md5.digest(getContentBytes(str, INPUT_CHARSET));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
//16是表示转换为16进制数
String md5Str = new BigInteger(1, digest).toString(16);
return md5Str;
}
/**
* 编码转换
*
* @param content
* @param charset
* @return
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
}
oa.php
function String2Hex($string){
$hex='';
for ($i=0; $i < strlen($string); $i++){
$hex .= "\u".dechex(ord($string[$i]));
}
return $hex;
}
function unicode_decode($unistr, $encoding = 'UTF-8', $ishex = false, $prefix = '&#', $postfix = ';') {
$arruni = explode($prefix, $unistr);
$unistr = '';
for($i = 1, $len = count($arruni); $i < $len; $i++) {
if (strlen($postfix) > 0) {
$arruni[$i] = substr($arruni[$i], 0, strlen($arruni[$i]) - strlen($postfix));
}
$temp = $ishex ? hexdec($arruni[$i]) : intval($arruni[$i]);
$unistr .= ($temp < 256) ? chr(0) . chr($temp) : chr($temp / 256) . chr($temp % 256);
}
return iconv('UCS-2', $encoding, $unistr);
}
//加密不一致
function make_sign($sign_str = ''){
$username = "wyzx";
$password = "wyzx123";
$timestamp = time();
//$sign = md5('username='.$username.'&password='.$password.'×tamp='.$timestamp.'flysoft.jxsexchange'); //不一致
$sign_str = 'username='.$username.'&password='.$password.'×tamp='.$timestamp.'flysoft.jxsexchange';
//return substr(md5($str),8,16); //加密不一致
//$secret = 'flysoft.jxsexchange';
//return strtoupper(bin2hex(md5('username='.$username.'&password='.$password.'×tamp='.$timestamp.$secret,true))); //加密不一致
$s = self::String2Hex($sign_str);
//md5加密
$md5_str = md5(self::unicode_decode($s,'utf-8',true,'\u',''));
return strtoupper( $md5_str );
}
正确的请求代码:
function curlGet($url)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
if (curl_errno($curl)) {
return 'ERROR ' . curl_error($curl);
}
curl_close($curl);
return $output;
}
$username = "wyzx";
$password = "wyzx123";
$timestamp = time();
//字符串拼接需要和JAVA接口保持一致MD5后才能生成相同的值
$str = 'password=wyzx123×tamp=1631064103&username=wyzxflysoft.jxsexchange';
$sign = md5($str);
$url = "http://10.22.231.177:8080/wydatacenter/services/getMailInfo?username={$username}&password={$password}×tamp={$timestamp}&sign={$sign}";
$res = json_decode(curlGet($url),true);
var_dump($res);
OR:
function curlPost($url, $data = null)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
if (!empty($data)) {
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
$username = "wyzx";
$password = "wyzx123";
$timestamp = time();
//字符串拼接需要和JAVA接口保持一致MD5后才能生成相同的值
$str = 'password=wyzx123×tamp=1631064103&username=wyzxflysoft.jxsexchange';
$sign = md5($str);
$url = "http://10.22.231.177:8080/wydatacenter/services/getMailInfo";
$param = array(
'username' => $username,
'password' => $password,
'timestamp' => $timestamp,
'sign' => $sign,
);
$res = json_decode(curlPost($url,json_encode($param,JSON_UNESCAPED_SLASHES)),true);
var_dump($res);