diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/WechatFilterConfig.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/WechatFilterConfig.java
index 8bb9ed7..ca3654a 100644
--- a/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/WechatFilterConfig.java
+++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/WechatFilterConfig.java
@@ -1,6 +1,8 @@
package com.cm.common.wechat.config;
+import com.cm.common.wechat.config.pojo.WechatOfficialAccountProperties;
import com.cm.common.wechat.filter.WechatFilter;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -18,13 +20,19 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class WechatFilterConfig {
+ @Autowired
+ private WechatOfficialAccountProperties wechatOfficialAccountProperties;
+
@Bean
public FilterRegistrationBean wechatFilterRegister() {
+ WechatFilter wechatFilter = new WechatFilter();
+ wechatFilter.setWechatOfficialAccountProperties(wechatOfficialAccountProperties);
+
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
- filterRegistrationBean.setFilter(new WechatFilter());
- filterRegistrationBean.addUrlPatterns("/wechat/**", "/wechatroute/**");
+ filterRegistrationBean.setFilter(wechatFilter);
+ filterRegistrationBean.addUrlPatterns("/wechat/*", "/wechatroute/*");
filterRegistrationBean.setName("wechatFilter");
- filterRegistrationBean.setOrder(2);
+ filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatOfficialAccountProperties.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatOfficialAccountProperties.java
index d5a56a3..012ba42 100644
--- a/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatOfficialAccountProperties.java
+++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatOfficialAccountProperties.java
@@ -20,9 +20,11 @@ public class WechatOfficialAccountProperties {
private WechatOfficialAccountAuthorizeProperties authorize;
private String accessTokenUrl;
+ private String bindUserUrl;
private String appId;
private String appSecret;
private String grantType;
+ private String configToken;
public WechatOfficialAccountAuthorizeProperties getAuthorize() {
return authorize;
@@ -40,6 +42,14 @@ public class WechatOfficialAccountProperties {
this.accessTokenUrl = accessTokenUrl;
}
+ public String getBindUserUrl() {
+ return bindUserUrl == null ? "" : bindUserUrl.trim();
+ }
+
+ public void setBindUserUrl(String bindUserUrl) {
+ this.bindUserUrl = bindUserUrl;
+ }
+
public String getAppId() {
return appId == null ? "" : appId.trim();
}
@@ -63,4 +73,33 @@ public class WechatOfficialAccountProperties {
public void setGrantType(String grantType) {
this.grantType = grantType;
}
+
+ public String getConfigToken() {
+ return configToken == null ? "" : configToken.trim();
+ }
+
+ public void setConfigToken(String configToken) {
+ this.configToken = configToken;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("{");
+ sb.append("\"authorize\":")
+ .append(authorize);
+ sb.append(",\"accessTokenUrl\":")
+ .append("\"").append(accessTokenUrl).append("\"");
+ sb.append(",\"bindUserUrl\":")
+ .append("\"").append(bindUserUrl).append("\"");
+ sb.append(",\"appId\":")
+ .append("\"").append(appId).append("\"");
+ sb.append(",\"appSecret\":")
+ .append("\"").append(appSecret).append("\"");
+ sb.append(",\"grantType\":")
+ .append("\"").append(grantType).append("\"");
+ sb.append(",\"configToken\":")
+ .append("\"").append(configToken).append("\"");
+ sb.append('}');
+ return sb.toString();
+ }
}
diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/controller/WechatOfficialAccountTestRouteController.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/controller/WechatOfficialAccountTestRouteController.java
new file mode 100644
index 0000000..d58e647
--- /dev/null
+++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/controller/WechatOfficialAccountTestRouteController.java
@@ -0,0 +1,44 @@
+package com.cm.common.wechat.controller;
+
+import com.cm.common.constants.ISystemConstant;
+import io.swagger.annotations.Api;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * When you feel like quitting. Think about why you started
+ * 当你想要放弃的时候,想想当初你为何开始
+ *
+ * @ClassName: WechatOfficialAccountTestController
+ * @Description: 微信公众号测试
+ * @Author: WangGeng
+ * @Date: 2020/3/3 12:10 下午
+ * @Version: 1.0
+ **/
+@Api(tags = ISystemConstant.API_TAGS_WECHAT_PREFIX + "页面测试")
+@Controller
+@RequestMapping(ISystemConstant.WECHAT_ROUTE_PREFIX + "/officialaccount")
+public class WechatOfficialAccountTestRouteController {
+
+ @GetMapping("index")
+ public void index(HttpServletResponse response) throws IOException {
+ Writer writer = response.getWriter();
+ writer.write("
Hello World!!!
点击跳转");
+ writer.flush();
+ writer.close();
+ }
+
+ @GetMapping("index2")
+ public void index2(HttpServletResponse response) throws IOException {
+ Writer writer = response.getWriter();
+ writer.write("Config Success
返回");
+ writer.flush();
+ writer.close();
+ }
+
+}
diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatFilter.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatFilter.java
index 7d03010..dff413e 100644
--- a/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatFilter.java
+++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatFilter.java
@@ -1,15 +1,25 @@
package com.cm.common.wechat.filter;
import com.cm.common.constants.ISystemConstant;
+import com.cm.common.wechat.config.pojo.WechatOfficialAccountProperties;
import com.cm.common.wechat.manager.officialaccount.WechatOfficialAccountManager;
+import org.apache.shiro.crypto.hash.Sha1Hash;
+import org.apache.shiro.crypto.hash.SimpleHash;
+import org.bouncycastle.crypto.digests.SHA1Digest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.security.crypto.password.MessageDigestPasswordEncoder;
+import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
/**
* When you feel like quitting. Think about why you started
@@ -24,12 +34,48 @@ import java.io.IOException;
public class WechatFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(WechatFilter.class);
+ private WechatOfficialAccountProperties wechatOfficialAccountProperties;
+ private AntPathMatcher antPathMatcher;
+
+ private static final String WECHAT_LOGIN_URL = "/**/wechat/sign/login";
+ /**
+ * 微信放行接口
+ */
+ private static final String WECHAT_RELEASE_URL = "/**/wechatrelease/**";
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ antPathMatcher = new AntPathMatcher();
+ }
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String requestUri = request.getRequestURI();
+ if (antPathMatcher.match(WECHAT_LOGIN_URL, requestUri) || antPathMatcher.match(WECHAT_RELEASE_URL, requestUri)) {
+ filterChain.doFilter(request, response);
+ return;
+ }
+
+ // 判断是不是微信配置校验
+ String signatureParameter = request.getParameter("signature");
+ String timestampParameter = request.getParameter("timestamp");
+ String nonceParameter = request.getParameter("nonce");
+ String echostrParameter = request.getParameter("echostr");
+ boolean isWechatConfig = !StringUtils.isEmpty(signatureParameter)
+ && !StringUtils.isEmpty(timestampParameter)
+ && !StringUtils.isEmpty(nonceParameter)
+ && !StringUtils.isEmpty(echostrParameter);
+ if (isWechatConfig && isWechatOfficialAccountConfigRequest(signatureParameter, timestampParameter, nonceParameter, echostrParameter)) {
+ Writer writer = response.getWriter();
+ writer.write(echostrParameter);
+ writer.flush();
+ writer.close();
+ return;
+ }
+
+ // 绑定校验
// 如果参数都存在,标识从服务器重定向回页面,获取AccessToken后放行
String codeParameter = request.getParameter("code");
String stateParameter = request.getParameter("state");
@@ -37,18 +83,49 @@ public class WechatFilter implements Filter {
try {
WechatOfficialAccountManager.getInstance().setUserAccessToken(codeParameter, stateParameter, request.getSession());
} catch (Exception e) {
- LOG.error("设置微信公众号session异常");
+ LOG.error(e.getMessage(), e);
+ response.setStatus(404);
+ filterChain.doFilter(request, response);
+ return;
}
- return;
}
// 判断session是否存在
Object accessToken = request.getSession().getAttribute(ISystemConstant.SESSION_WECHAT_ACCESS_TOKEN);
// session 不存在重定向登录
if (StringUtils.isEmpty(accessToken)) {
- response.sendRedirect(WechatOfficialAccountManager.getInstance().getAuthorizeUrl(requestUri));
+ response.sendRedirect(WechatOfficialAccountManager.getInstance().getAuthorizeUrl(request.getRequestURL().toString()));
return;
}
filterChain.doFilter(request, response);
}
+ /**
+ * 是来自微信的配置请求
+ *
+ * @param signature
+ * @param timestamp
+ * @param nonce
+ * @param echostr
+ * @return
+ */
+ private boolean isWechatOfficialAccountConfigRequest(String signature, String timestamp, String nonce, String echostr) {
+ List sortList = new ArrayList<>();
+ sortList.add(wechatOfficialAccountProperties.getConfigToken());
+ sortList.add(timestamp);
+ sortList.add(nonce);
+ Collections.sort(sortList);
+ StringBuilder newSignature = new StringBuilder();
+ sortList.forEach(str -> {
+ newSignature.append(str);
+ });
+ if (!StringUtils.pathEquals(signature, new SimpleHash("SHA-1", newSignature.toString()).toString())) {
+ return false;
+ }
+ return true;
+ }
+
+ public void setWechatOfficialAccountProperties(WechatOfficialAccountProperties wechatOfficialAccountProperties) {
+ this.wechatOfficialAccountProperties = wechatOfficialAccountProperties;
+ }
+
}
diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/officialaccount/WechatOfficialAccountManager.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/officialaccount/WechatOfficialAccountManager.java
index d4ebb14..fa48871 100644
--- a/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/officialaccount/WechatOfficialAccountManager.java
+++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/officialaccount/WechatOfficialAccountManager.java
@@ -6,7 +6,6 @@ import com.cm.common.exception.WechatAccessTokenException;
import com.cm.common.exception.WechatAccessTokenForUserException;
import com.cm.common.exception.WechatUserInfoException;
import com.cm.common.utils.AesUtil;
-import com.cm.common.utils.http.RestRequestUtil;
import com.cm.common.wechat.config.pojo.WechatOfficialAccountProperties;
import com.cm.common.wechat.pojo.WechatOfficialAccountAccessToken;
import com.cm.common.wechat.pojo.WechatOfficialAccountAccessTokenForUser;
@@ -14,6 +13,7 @@ import com.cm.common.wechat.pojo.WechatOfficialAccountUser;
import com.cm.common.wechat.pojo.WechatOfficialAccountUserInfo;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
+import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.client.RestTemplateBuilder;
@@ -23,6 +23,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpSession;
+import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -61,6 +62,7 @@ public class WechatOfficialAccountManager {
if ((currentTime - this.updateTime) >= 5400000) {
LOG.debug("刷新公众号 AccessToken 开始");
this.accessToken = getNewAccessToken();
+ LOG.debug("accessToken: {}", this.accessToken);
this.updateTime = System.currentTimeMillis();
LOG.debug("刷新公众号 AccessToken 结束");
}
@@ -95,15 +97,15 @@ public class WechatOfficialAccountManager {
/**
* 重定向url
*
- * @param requestUri
+ * @param redirectUrl
* @return
*/
- public String getAuthorizeUrl(String requestUri) {
+ public String getAuthorizeUrl(String redirectUrl) {
StringBuilder authorizeUrl = new StringBuilder(wechatOfficialAccountProperties.getAuthorize().getAuthorizeUrl());
authorizeUrl.append("?appid=").append(wechatOfficialAccountProperties.getAppId());
authorizeUrl.append("&scope=").append(wechatOfficialAccountProperties.getAuthorize().getScope());
authorizeUrl.append("&state=").append(wechatOfficialAccountProperties.getAuthorize().getState());
- authorizeUrl.append("&redirect_uri=").append(requestUri);
+ authorizeUrl.append("&redirect_uri=").append(redirectUrl);
authorizeUrl.append("&response_type=code#wechat_redirect");
return authorizeUrl.toString();
}
@@ -116,12 +118,12 @@ public class WechatOfficialAccountManager {
* @param session
*/
public void setUserAccessToken(String code, String state, HttpSession session) throws Exception {
- if (!StringUtils.equals(state, wechatOfficialAccountProperties.getAuthorize().getState())) {
+ if (StringUtils.equals(state, wechatOfficialAccountProperties.getAuthorize().getState())) {
WechatOfficialAccountAccessTokenForUser wechatOfficialAccountAccessTokenForUser = getUserAccessToken(code);
WechatOfficialAccountUserInfo wechatOfficialAccountUserInfo = getUserInfo(wechatOfficialAccountAccessTokenForUser.getAccess_token(), wechatOfficialAccountAccessTokenForUser.getOpenid());
WechatOfficialAccountUser wechatOfficialAccountUser = new WechatOfficialAccountUser();
// 绑定用户 | 登录
- String wechatSignInfo = AesUtil.aesCommonEncoder("WECHAT_SIGN_INFO", Base64.encodeBase64String(new StringBuilder(wechatOfficialAccountAccessTokenForUser.getOpenid()).append("_WenG_").append(wechatOfficialAccountProperties.getAppId()).toString().getBytes("UTF-8")));
+ String wechatSignInfo = Base64.encodeBase64String(AesUtil.aesCommonEncoder("WECHAT_SIGN_INFO", new StringBuilder(wechatOfficialAccountAccessTokenForUser.getOpenid()).append("_WenG_").append(wechatOfficialAccountProperties.getAppId()).toString()).getBytes("UTF-8"));
String token = getAppToken(wechatSignInfo);
wechatOfficialAccountUser.setToken(token);
wechatOfficialAccountUser.setWechatOfficialAccountAccessTokenForUser(wechatOfficialAccountAccessTokenForUser);
@@ -142,7 +144,8 @@ public class WechatOfficialAccountManager {
Map params = new HashMap<>(1);
params.put("signInfo", wechatSignInfo);
HttpEntity