Skip to content

Instantly share code, notes, and snippets.

@greenyleaf
Last active June 19, 2020 13:27
Show Gist options
  • Save greenyleaf/fb7fc9db4629cdaa7ed9b0fa1481373e to your computer and use it in GitHub Desktop.
Save greenyleaf/fb7fc9db4629cdaa7ed9b0fa1481373e to your computer and use it in GitHub Desktop.
a Spring controller for Weixin(wechat) page authorization, enhanced security.
package top.sdrkyj.custom.controller;
import top.sdrkyj.custom.config.WxAuthInterceptor;
import top.sdrkyj.custom.dto.RestMsg;
import top.sdrkyj.custom.entity.weixin.WxUserInfo;
import top.sdrkyj.custom.service.WxService;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.http.HttpSession;
import java.net.URI;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
@Controller
@RequestMapping
public class WxController {
private static final Logger logger = LoggerFactory.getLogger(WxController.class);
private static final char[] arr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
private final String token;
private final WxService wxService;
private final String appid;
private final Cache cache;
public WxController(@Value("${weixin.echo-token}") String token, WxService wxService,
@Value("${weixin.appid}") String appid, CacheManager cacheManager) {
this.token = token;
this.wxService = wxService;
this.appid = appid;
cache = cacheManager.getCache("wx-state");
}
@GetMapping(path = "wx-message-endpoint", params = "echostr")
@ResponseBody
public ResponseEntity<String> messageEndPoint(@RequestParam String signature, @RequestParam String timestamp,
@RequestParam String nonce, @RequestParam String echostr) throws NoSuchAlgorithmException {
logger.info("messageEndPoint entered");
logger.info("signature, {}, timestamp, {}, nonce, {}, echostr, {}", signature, timestamp, nonce, echostr);
MessageDigest digest = MessageDigest.getInstance("sha-1");
String[] arr = new String[]{token, timestamp, nonce};
Arrays.sort(arr);
for (String i : arr) {
digest.update(i.getBytes());
}
String encoded = Hex.encodeHexString(digest.digest());
logger.info("encoded, {}", encoded);
logger.info("encoded==signature, {}", encoded.equals(signature));
if (encoded.equals(signature)) {
return ResponseEntity.ok(echostr);
} else {
return ResponseEntity.badRequest().build();
}
}
@RequestMapping("wx-message-endpoint")
@ResponseBody
public ResponseEntity<String> messageEndPoint() {
return ResponseEntity.ok().build();
}
@GetMapping("wx-auth")
@ResponseBody
public ResponseEntity<String> wxAuth(@RequestParam String code, @RequestParam String state, HttpSession session) {
logger.info("wxAuth entered");
logger.info("code, {}", code);
logger.info("state, {}", state);
Cache.ValueWrapper wrapper = cache.get(state);
logger.debug("wrapper, {}", wrapper);
String redirectUri;
if (wrapper != null && (redirectUri = (String) wrapper.get()) != null) {
logger.debug("redirectUrl, {}", redirectUri);
if (session.getAttribute(WxAuthInterceptor.WX_USER_KEY) == null) {
WxUserInfo wxUserInfo = wxService.doGetAuthenticationInfo(code);
if (wxUserInfo == null) {
return ResponseEntity.status(HttpStatus.FOUND).location(URI.create("/error/4xx.html")).build();
}
session.setAttribute(WxAuthInterceptor.WX_USER_KEY, wxUserInfo);
logger.info("wxUserInfo, {}", wxUserInfo);
logger.info("openid, {}", wxUserInfo.getOpenid());
}
return ResponseEntity.status(HttpStatus.FOUND).location(URI.create(redirectUri)).build();
} else {
return ResponseEntity.badRequest().build();
}
}
/**
* 需要验证用户时内部跳转使用
*/
@RequestMapping(path = "wx-authorize", produces = MediaType.TEXT_HTML_VALUE)
public String authorize(@RequestAttribute String redirect) throws NoSuchAlgorithmException {
logger.debug("authorize entered");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 96; i++) {
sb.append(arr[SecureRandom.getInstanceStrong().nextInt(arr.length)]);
}
String state = sb.toString();
logger.info("STATE_KEY, {}", state);
//cache.putIfAbsent(state, UriComponentsBuilder.fromHttpUrl(String.valueOf(request.getRequestURL())).query(request.getQueryString()).build().toUriString());
cache.put(state, redirect);
logger.info("cache, {}", cache);
logger.info("redirect, {}", redirect);
String urlStr = UriComponentsBuilder.fromHttpUrl("https://open.weixin.qq.com/connect/oauth2/authorize?appid={appid}&redirect_uri={redirectUri}&response_type=code&scope=snsapi_userinfo&state={state}")
.fragment("wechat_redirect")
.buildAndExpand(appid, "http://custom.sdrkyj.top/wx-auth", state).encode().toUriString();
return "redirect:" + urlStr;
}
@RequestMapping(path = "wx-authorize", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public RestMsg<Void> authorize() {
RestMsg<Void> restMsg = new RestMsg<>(HttpStatus.UNAUTHORIZED.value());
restMsg.setMessage("请登录");
return restMsg;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment