为了在公众号里配置下图时使用的代码:
Controller层代码:
import com.weixin.wxDemo.service.CheckTokenService;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Log4j
@Controller
@RequestMapping("/checkTokenUtil")
public class CheckTokenController {
@Autowired
private CheckTokenService checkTokenService;
/**
* 验证消息是否来自微信服务器
* signature:微信加密签名
* timestamp:时间戳
* nonce:随机数
* echostr:随机字符串
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "checkToken", method = RequestMethod.GET)
public void checkToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
//验证
String newStr = checkTokenService.checkToken(signature, timestamp, nonce, echostr);
if (!echostr.equals(newStr)) {
log.error("消息不是来自微信服务器!");
} else {
response.getOutputStream().println(echostr);
}
}
}
Service层代码:
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Arrays;
/**
* @Auther: 抹茶冰冰冰
* @Date: 2020-04-02
* @Description: 验证消息是否来自微信服务器
**/
@Service
@RequestMapping("checkTokenService")
public class CheckTokenService {
/**
* 这里获取的是配置文件里的token的值
*/
@Value("${weixin.token}")
private String token;
/*
* 获取accessToken的服务接口
*/
@Autowired
private GetAccessTokenService getAccessTokenService;
public String checkToken(
String signature,
String timestamp,
String nonce,
String echostr) {
//调用所有接口前都需要获取accessToken
String accessToken = getAccessTokenService.getAccessToken();
if(StringUtils.isBlank(accessToken)){
return "";
}
//放入数组,进行字典排序后组成一个字符串。
String[] arr = new String[]{token, timestamp, nonce};
Arrays.sort(arr);
String str = arr[0] + arr[1] + arr[2];
//sha1加密,这里可以手写也可以用jar包,我选择用jar包,具体的maven依赖在该系列文章的第一章里。
//如果选择手写,可以参考第三段的代码段。
String resultMsg = DigestUtils.sha1Hex(str);
if (!resultMsg.equals(signature)) {
return "";
}
return echostr;
}
}
上一段代码中的sha1加密我使用的是工具包,如果大家需要手写,可以将“ String resultMsg = DigestUtils.sha1Hex(str);”这段代码
修改成如下代码(这段代码不是我写的,具体出处也是各路大神。注意:手写这段代码里的英文都是大写的,在判断相等时要把equals()方法改成equalsIgnoreCase()方法或者将resultMsg转换成小写的也可以):
MessageDigest md = null;
String resultMsg = null;
try {
md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(str.getBytes());
resultMsg = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
再在Service里加入如下两个方法:
private static String byteToStr(byte[] byteArray) {
StringBuilder strDigest = new StringBuilder();
for (int i = 0; i < byteArray.length; i++) {
strDigest.append(byteToHexStr(byteArray[i]));
}
return strDigest.toString();
}
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}