需求
使用微信扫码登录的授权方式登录系统
实现
此扫码登陆过程中使用了,微信开放平台(需支付300开通开发者认证)的网站应用实现的。
官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
流程:
大概就是:前端调接口获取后端生成的state(可以用验证登录授权的有效性)——>用户扫码后确认授权——>前端开始调用微信开放平台的接口之后回调服务端接口——>回调时传入了两个参数,code和state——>根据code,appid和appSecret调用接口获取access_token——根据access_token获取微信用户的个人信息
代码:
前端vue:
安装一个插件:
1
| npm install vue-wxlogin --save-dev
|
引入组件:
1 2 3 4 5 6 7 8 9
| <wxlogin appid="xxxxxx" :scope="'snsapi_login'" theme="black" redirect_uri="redirectUrl" :state="xxxxxx" :self_redirect="'true'" rel="external nofollow" />
|
注:重定向地址需要使用urlEncode对链接进行处理
后端SpringBoot:
后端生成state接口
1 2 3 4 5 6 7 8 9
| @ApiOperation(value = "企业端:获取扫码登录的state", notes = " \n author:ZhuGuangLiang") @AnonymousGetMapping("/wx/qrcode") public Result<Object> getQrCode() throws IOException { String state= IdUtil.simpleUUID(); redisUtils.set(state, JSON.toJSON(new CompanyWxDTO()), 5 * 60); return Result.success(state); }
|
回调接口,并携带state和code参数
注:回调接口,尽量不要抛出异常,异常可以在登录接口抛出
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| @ApiOperation(value = "企业端:微信用户授权后,回调地址", notes = " \n author:ZhuGuangLiang") @AnonymousGetMapping("/wx/callback") public void callback(String code, String state) { companyAuthService.callback(code, state); }
@Override public void callback(String code, String state) { JSONObject resultAuthUrl = JSONObject.parseObject(HttpUtil.get(String.format(authUrl, appid, secret, code))); boolean isSuccess = true; if (resultAuthUrl.containsKey("errcode")) { log.error("授权失败"); isSuccess = false; } String openid = resultAuthUrl.getString("openid"); String accessToken = resultAuthUrl.getString("access_token"); String refreshToken = resultAuthUrl.getString("refresh_token"); LambdaQueryWrapper<SpiritCompanyUser> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(SpiritCompanyUser::getOpenid, openid); CompanyWxDTO companyWxDTO = loginUtils.noExceptinCheckCompanyUser(queryWrapper); int type = companyWxDTO.getType(); if (!isSuccess) { companyWxDTO.setType(7); } if (type == 1 && isSuccess) { JSONObject resultCheckToken = JSONObject.parseObject(HttpUtil.get(String.format(checkTokenUrl, accessToken, openid))); if (resultCheckToken.getInteger("errcode") == 40003) { JSONObject resultRefreshToken = JSONObject.parseObject(HttpUtil.get(String.format(refreshTokenUrl, appid, refreshToken))); accessToken = resultRefreshToken.getString("access_token"); } JSONObject resultUserInfoUrl = JSONObject.parseObject(HttpUtil.get(String.format(userInfoUrl, accessToken, openid))); log.info("resultUserInfoUrl:" + resultUserInfoUrl.toString()); if (resultUserInfoUrl.containsKey("errcode")) { log.error("获取用户信息失败"); companyWxDTO.setType(8); } companyWxDTO.setAvatarUrl(resultUserInfoUrl.getString("headimgurl")); companyWxDTO.setNickName(resultUserInfoUrl.getString("nickname")); companyWxDTO.setOpenid(openid); companyWxDTO.setUnionid(resultUserInfoUrl.getString("unionid")); log.info("微信用户授权成功"); } companyWxDTO.setTicket(state); redisUtils.set(state, JSON.toJSON(companyWxDTO), 5 * 60); }
|