diff --git a/src/main/java/chanjarster/weixin/api/WxService.java b/src/main/java/chanjarster/weixin/api/WxService.java index 6300310f..48588a72 100644 --- a/src/main/java/chanjarster/weixin/api/WxService.java +++ b/src/main/java/chanjarster/weixin/api/WxService.java @@ -9,6 +9,18 @@ import chanjarster.weixin.exception.WxErrorException; */ public interface WxService { + /** + *
+ * 验证推送过来的消息的正确性 + * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=接入指南 + *+ * @param timestamp + * @param nonce + * @param signature + * @return + */ + public boolean checkSignature(String timestamp, String nonce, String signature); + /** *
* 获取access_token,本方法线程安全 diff --git a/src/main/java/chanjarster/weixin/api/WxServiceImpl.java b/src/main/java/chanjarster/weixin/api/WxServiceImpl.java index 1c203ef4..27debf4e 100644 --- a/src/main/java/chanjarster/weixin/api/WxServiceImpl.java +++ b/src/main/java/chanjarster/weixin/api/WxServiceImpl.java @@ -1,6 +1,8 @@ package chanjarster.weixin.api; import java.io.IOException; +import java.security.MessageDigest; +import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.lang3.StringUtils; @@ -35,6 +37,35 @@ public class WxServiceImpl implements WxService { protected WxConfigStorage wxConfigProvider; + public boolean checkSignature(String timestamp, String nonce, String signature) { + try { + String token = wxConfigProvider.getToken(); + MessageDigest sha1 = MessageDigest.getInstance("SHA1"); + String[] arr = new String[] { token, timestamp, nonce }; + Arrays.sort(arr); + StringBuilder sb = new StringBuilder(); + for(String a : arr) { + sb.append(a); + } + sha1.update(sb.toString().getBytes()); + byte[] output = sha1.digest(); + return bytesToHex(output).equals(signature); + } catch (Exception e) { + return false; + } + } + + protected static String bytesToHex(byte[] b) { + char hexDigit[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + StringBuffer buf = new StringBuffer(); + for (int j = 0; j < b.length; j++) { + buf.append(hexDigit[(b[j] >> 4) & 0x0f]); + buf.append(hexDigit[b[j] & 0x0f]); + } + return buf.toString(); + } + public void refreshAccessToken() throws WxErrorException { if (!GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.getAndSet(true)) { try { diff --git a/src/test/java/chanjarster/weixin/api/WxServiceTest.java b/src/test/java/chanjarster/weixin/api/WxServiceTest.java index 58650bee..a9290c18 100644 --- a/src/test/java/chanjarster/weixin/api/WxServiceTest.java +++ b/src/test/java/chanjarster/weixin/api/WxServiceTest.java @@ -69,6 +69,14 @@ public class WxServiceTest { wxService.deleteMenu(); } + @Test + public void testCheckSignature() throws WxErrorException { + String timestamp = "23234235423246"; + String nonce = "y7didfkcmvnbd90sdofjkiefhsd"; + String signature = "77b6651628dfb9a64bfb0d3432ee053ac566a459"; + Assert.assertTrue(wxService.checkSignature(timestamp, nonce, signature)); + } + @DataProvider(name="menu") public Object[][] getMenu() throws JAXBException { WxMenu menu = new WxMenu(); @@ -116,7 +124,6 @@ public class WxServiceTest { } - @XmlRootElement(name = "xml") @XmlAccessorType(XmlAccessType.FIELD) public static class WxXmlConfigStorage extends WxInMemoryConfigStorage {