技术漫谈OAuth2登录协议
FANSEAOAuth2登录协议
本文以微信授权登录来演示说明
参考文档:
- 微信登录功能 / 网站应用微信登录开发指南 (qq.com)
- 微信登录开发者测试平台 (qq.com)

所用到的依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.3</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.17</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
|
所用到的model:
1 2 3 4 5 6 7 8 9
| @Data public class TokenInfo { private String accessToken; private Integer expiresIn; private String refreshToken; private String openid; private String scope;
}
|
1 2 3 4 5 6 7 8 9 10 11 12
| @Data public class WeChatUser { private String openid; private String nickname; private Integer sex; private String province; private String city; private String country; private String headimgurl; private String privilege; private String unionid; }
|
信息配置
此步用于配置信息,这样才能和微信登录服务方连接

1 2 3 4 5 6 7 8 9 10
| @RequestMapping("/wxCheck") public String wxSignatureCheck( @RequestParam(value = "signature") String signature, @RequestParam(value = "timestamp") String timestamp, @RequestParam(value = "nonce") String nonce, @RequestParam(value = "echostr") String echostr ){ log.info("收到微信校验请求,echostr:{}",echostr); return echostr; }
|


定义自己的登录接口
自定义登录接口,采用微信扫码登录的方式向微信服务端发起登录授权请求
1 2 3 4 5 6 7 8 9 10 11
| @GetMapping("/wxLogin") @ResponseBody public void wxLoginPage(HttpServletResponse response) throws Exception{ String redirectUrl = URLEncoder.encode("https://2a644f9d.r15.cpolar.top/wxCallBack", StandardCharsets.UTF_8); String url = " https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx120df5342711e687&redirect_uri=" +redirectUrl+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; response.setContentType("image/png"); QrCodeUtil.generate(url,300,300,"jpg",response.getOutputStream()); }
|
1 2 3 4 5 6 7
| @RequestMapping("/wxCallBack") @ResponseBody public String pcCallback(String code, String state, HttpServletRequest request,HttpServletResponse response,HttpSession session) throws IOException { WeChatUser userInfo = WechatUtil.getUserInfo(code); return JSONUtil.toJsonStr(userInfo); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public static WeChatUser getUserInfo(String code) throws IOException { String responseResult = ""; System.out.println("code = " + code); RestTemplate restTemplate = new RestTemplate(); CloseableHttpClient httpClient = HttpClients.createDefault(); String tokenUrl ="https://api.weixin.qq.com/sns/oauth2/access_token?appid="+APP_ID+"&secret="+APP_SECRET+"&code="+code+"&grant_type=authorization_code"; HttpGet request = new HttpGet(tokenUrl); CloseableHttpResponse response = httpClient.execute(request); if (response.getStatusLine().getStatusCode() == 200){ responseResult = EntityUtils.toString(response.getEntity(),"UTF-8"); } log.info("获取到responseResult:{}",responseResult); TokenInfo tokenInfo = JSONUtil.toBean(responseResult, TokenInfo.class); String userInfoURL = "https://api.weixin.qq.com/sns/userinfo?access_token="+tokenInfo.getAccessToken()+"&openid=" +tokenInfo.getOpenid()+"&lang=zh_CN";
HttpGet request1 = new HttpGet(userInfoURL); CloseableHttpResponse response1 = httpClient.execute(request1); if (response1.getStatusLine().getStatusCode() == 200){ responseResult = EntityUtils.toString(response1.getEntity(),"UTF-8"); } log.info("获取到userInfoResult:{}",responseResult); WeChatUser userInfo = JSONUtil.toBean(responseResult, WeChatUser.class); redisTemplate.opsForValue().set("token:"+tokenInfo.getAccessToken(), JSONUtil.toJsonStr(userInfo)); return userInfo; }
|
BUG笔记
- 这里发送请求获取tokenInfo,weChatUser不能直接用redistemplate直接封装
因为返回的数据还需要进行一步操作response.getEntity(),tokenInfo和weChatUser在response的下一层
- 无法注入redistemplate
redis版本出错,建议不选择版本号,默认选择springboot自带的版本这样适应jdk,不容易出错
1 2 3 4 5 6 7 8
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
|
- 静态类注入redistemplate方法
1 2 3 4 5 6 7 8 9 10 11
| @Component public class WechatUtil {
private static StringRedisTemplate redisTemplate;
@Autowired public void setRedisTemplate(StringRedisTemplate redisTemplate) { WechatUtil.redisTemplate = redisTemplate; } }
|