Last active
June 19, 2020 13:27
-
-
Save greenyleaf/fb7fc9db4629cdaa7ed9b0fa1481373e to your computer and use it in GitHub Desktop.
a Spring controller for Weixin(wechat) page authorization, enhanced security.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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