点击关注公众号,利用碎片时间学习

微信开放平台:微信扫码登录功能

官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

1. 授权流程说明

微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。

微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:

① 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;

② 通过code参数加上AppID和AppSecret等,通过API换取access_token;

③ 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

第一步:请求CODE

第三方使用网站应用授权登录前请注意已获取相应网页授权作用域(scope=snsapi_login),则可以通过在PC端打开以下链接:https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

返回说明

用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数

redirect_uri?code=CODE&state=STATE

若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数

redirect_uri?state=STATE

例如:登录一号店网站应用 https://passport.yhd.com/wechat/login.do 打开后,一号店会生成state参数,跳转到 https://open.weixin.qq.com/connect/qrconnect?appid=wxbdc5610cc59c1631&redirect_uri=https%3A%2F%2Fpassport.yhd.com%2Fwechat%2Fcallback.do&response_type=code&scope=snsapi_login&state=3d6be0a4035d839573b04816624a415e#wechat_redirect 微信用户使用微信扫描二维码并且确认登录后,PC端会跳转到 https://passport.yhd.com/wechat/callback.do?code=CODE&state=3d6be0a4035d839573b04816624a415e

第二步:通过code获取access_token

通过code获取access_token

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

返回说明

正确的返回:

{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

错误返回样例:

{"errcode":40029,"errmsg":"invalid code"}
  • Appsecret 是应用接口使用密钥,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);

  • access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;

  • refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上。

建议将secret、用户数据(如access_token)放在App云端服务器,由云端中转接口调用请求。

学习资料:Java进阶视频资源

第三步:通过access_token调用接口

获取access_token后,进行接口调用,有以下前提:

  1. access_token有效且未超时;

  2. 微信用户已授权给第三方应用帐号相应接口作用域(scope)。

对于接口作用域(scope),能调用的接口有以下:

2. 授权流程代码

因为微信开放平台的AppiD和APPSecret和微信公众平台的AppiD和AppSecret都是不同的,因此需要配置一下:

# 开放平台
wechat.open-app-id=wx6ad144e54af67d87
wechat.open-app-secret=91a2ff6d38a2bbccfb7e9f9079108e2e
@Data
@Component
@ConfigurationProperties(prefix = "wechat")
public class WechatAccountConfig {//公众号appidprivate String mpAppId;//公众号appSecretprivate String mpAppSecret;//商户号private String mchId;//商户秘钥private String mchKey;//商户证书路径private String keyPath;//微信支付异步通知private String notifyUrl;//开放平台idprivate String openAppId;//开放平台秘钥private String openAppSecret;
}
@Configuration
public class WechatOpenConfig {@Autowiredprivate WechatAccountConfig accountConfig;@Beanpublic WxMpService wxOpenService() {WxMpService wxOpenService = new WxMpServiceImpl();wxOpenService.setWxMpConfigStorage(wxOpenConfigStorage());return wxOpenService;}@Beanpublic WxMpConfigStorage wxOpenConfigStorage() {WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage();wxMpInMemoryConfigStorage.setAppId(accountConfig.getOpenAppId());wxMpInMemoryConfigStorage.setSecret(accountConfig.getOpenAppSecret());return wxMpInMemoryConfigStorage;}
}
@Controller
@RequestMapping("/wechat")
@Slf4j
public class WeChatController {@Autowiredprivate WxMpService wxMpService;@Autowiredprivate WxMpService wxOpenService;@GetMapping("/qrAuthorize")public String qrAuthorize() {//returnUrl就是用户授权同意后回调的地址String returnUrl = "http://heng.nat300.top/sell/wechat/qrUserInfo";//引导用户访问这个链接,进行授权String url = wxOpenService.buildQrConnectUrl(returnUrl, WxConsts.QRCONNECT_SCOPE_SNSAPI_LOGIN, URLEncoder.encode(returnUrl));return "redirect:" + url;}//用户授权同意后回调的地址,从请求参数中获取code@GetMapping("/qrUserInfo")public String qrUserInfo(@RequestParam("code") String code) {WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();try {//通过code获取access_tokenwxMpOAuth2AccessToken = wxOpenService.oauth2getAccessToken(code);} catch (WxErrorException e) {log.error("【微信网页授权】{}", e);throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(), e.getError().getErrorMsg());}//从token中获取openidString openId = wxMpOAuth2AccessToken.getOpenId();//这个地址可有可无,反正只是为了拿到openid,但是如果没有会报404错误,为了好看随便返回一个百度的地址String  returnUrl = "http://www.baidu.com";log.info("openid={}", openId);return "redirect:" + returnUrl + "?openid="+openId;}
}

请求路径:在浏览器打开

https://open.weixin.qq.com/connect/qrconnect?appid=wx6ad144e54af67d87&redirect_uri=http%3A%2F%2Fsell.springboot.cn%2Fsell%2Fqr%2FoTgZpwenC6lwO2eTDDf_-UYyFtqI&response_type=code&scope=snsapi_login&state=http%3a%2f%2fheng.nat300.top%2fsell%2fwechat%2fqrUserInfo

获取了openid:openid=o9AREv7Xr22ZUk6BtVqw82bb6AFk

3. 用户登录和登出

@Controller
@RequestMapping("/seller")
public class SellerUserController {@Autowiredprivate SellerService sellerService;@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate ProjectUrlConfig projectUrlConfig;@GetMapping("/login")public ModelAndView login(@RequestParam("openid") String openid,HttpServletResponse response,Map<String, Object> map) {//1. openid去和数据库里的数据匹配SellerInfo sellerInfo = sellerService.findSellerInfoByOpenid(openid);if (sellerInfo == null) {map.put("msg", ResultEnum.LOGIN_FAIL.getMessage());map.put("url", "/sell/seller/order/list");return new ModelAndView("common/error");}//2. 设置token至redisString token = UUID.randomUUID().toString();//设置token的过期时间Integer expire = RedisConstant.EXPIRE;redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX, token), openid, expire, TimeUnit.SECONDS);//3. 设置token至cookieCookieUtil.set(response, CookieConstant.TOKEN, token, expire);return new ModelAndView("redirect:" + "http://heng.nat300.top/sell/seller/order/list");}@GetMapping("/logout")public ModelAndView logout(HttpServletRequest request,HttpServletResponse response,Map<String, Object> map) {//1. 从cookie里查询Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN);if (cookie != null) {//2. 清除redisredisTemplate.opsForValue().getOperations().delete(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue()));//3. 清除cookieCookieUtil.set(response, CookieConstant.TOKEN, null, 0);}map.put("msg", ResultEnum.LOGOUT_SUCCESS.getMessage());map.put("url", "/sell/seller/order/list");return new ModelAndView("common/success", map);}
}

① 将上一步获取到的openid存入数据库

② 将授权后跳转的地址改为登录地址

//用户授权同意后回调的地址,从请求参数中获取code@GetMapping("/qrUserInfo")public String qrUserInfo(@RequestParam("code") String code) {WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();try {//通过code获取access_tokenwxMpOAuth2AccessToken = wxOpenService.oauth2getAccessToken(code);} catch (WxErrorException e) {log.error("【微信网页授权】{}", e);throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(), e.getError().getErrorMsg());}//从token中获取openidString openId = wxMpOAuth2AccessToken.getOpenId();//授权成功后跳转到卖家系统的登录地址String  returnUrl = "http://heng.nat300.top/sell/seller/login";log.info("openid={}", openId);return "redirect:" + returnUrl + "?openid="+openId;}

③ 在浏览器请求这个链接:https://open.weixin.qq.com/connect/qrconnect?appid=wx6ad144e54af67d87&redirect_uri=http%3A%2F%2Fsell.springboot.cn%2Fsell%2Fqr%2FoTgZpwenC6lwO2eTDDf_-UYyFtqI&response_type=code&scope=snsapi_login&state=http%3a%2f%2fheng.nat300.top%2fsell%2fwechat%2fqrUserInfo

第三应用请求使用微信扫码登录,而不是使用本网站的密码:

用户同意授权后登入第三方应用的后台管理系统:

4. Spring AOP校验用户有没有登录

@Aspect
@Component
@Slf4j
public class SellerAuthorizeAspect {@Autowiredprivate StringRedisTemplate redisTemplate;@Pointcut("execution(public * com.hh.controller.Seller*.*(..))" +"&& !execution(public * com.hh.controller.SellerUserController.*(..))")public void verify() {}@Before("verify()")public void doVerify() {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();//查询cookieCookie cookie = CookieUtil.get(request, CookieConstant.TOKEN);//如果cookie中没有token说明已经登出或者根本没有登录if (cookie == null) {log.warn("【登录校验】Cookie中查不到token");//校验不通过,抛出异常throw new SellerAuthorizeException();}//去redis里查询String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue()));//如果redis中没有对应的openid,同样表示登出或者根本没有登录if (StringUtils.isEmpty(tokenValue)) {log.warn("【登录校验】Redis中查不到token");throw new SellerAuthorizeException();}}
}

5. 拦截登录校验不通过抛出的异常

拦截及登录校验不通过的异常,让其跳转到登录页面,扫码登录

@ControllerAdvice
public class SellExceptionHandler {//拦截登录异常@ExceptionHandler(value = SellerAuthorizeException.class)public ModelAndView handlerAuthorizeException() {//拦截异常后,跳转到登录界面return new ModelAndView("redirect:".concat("https://open.weixin.qq.com/connect/qrconnect?" +"appid=wx6ad144e54af67d87" +"&redirect_uri=http%3A%2F%2Fsell.springboot.cn%2Fsell%2Fqr%2F" +"oTgZpwenC6lwO2eTDDf_-UYyFtqI" +"&response_type=code&scope=snsapi_login" +"&state=http%3a%2f%2fheng.nat300.top%2fsell%2fwechat%2fqrUserInfo"));}@ExceptionHandler(value = SellException.class)@ResponseBodypublic ResultVO handlerSellerException(SellException e) {return ResultVOUtil.error(e.getCode(), e.getMessage());}@ExceptionHandler(value = ResponseBankException.class)@ResponseStatus(HttpStatus.FORBIDDEN)public void handleResponseBankException() {}
}

来源:hengheng.blog.csdn.net/article/details/107823201

推荐:

主流Java进阶技术(学习资料分享)

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!

微信扫码登录很难吗?5步帮你搞定相关推荐

  1. 微信扫码登录很难吗?5步帮你登陆

    1. 授权流程说明 微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(acce ...

  2. 微信开放平台开发——网页微信扫码登录(OAuth2.0)

    1.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提供 ...

  3. Spring学习笔记(二十三)——实现网站微信扫码登录获取微信用户信息Demo

    目录 微信扫码登录介绍 开发步骤 微信扫码登录示例 微信开放文档 遇到的问题 使用第三方工具实现网站微信扫码登录 开发前介绍 开发步骤 微信扫码登录获取微信用户信息Demo实现流程 实现效果 实现过程 ...

  4. 微信扫码登录_JAVA

    一.需求 在PC端的登录页面加个微信扫码的按钮,点击按钮弹出二维码,实现微信扫码登录网站的功能.如图: 二.调研 扫码登录属于微信开放平台提供的API,不是微信公众平台.这里需要注册等配置,暂不赘述. ...

  5. 通过微信扫码登录剖析 oauth2 认证授权技术

    本文目录 前言 趣味解读oauth2 oauth2精髓 oauth2核心概念 结合微信登录深刻理解oauht2 本文小结 前言 相信很多小伙伴在学习 JAVA 的过程中或多或少接触或者开发过类似于 x ...

  6. 【vue+pc端】实现微信扫码登录pc端,后端通过微信开发平台,前端生成二维码(仅供参考)

    这两周的需求是通过微信扫码登录pc端,刚定下需求原型图还没出来前,后端特意发了微信开发平台的链接给我,关于如何生成二维码的文档,以及扫码跳转后如何传code给他. 请戳这里准备工作|微信开放文档 我最 ...

  7. 微信扫码登录功能实现

    原因:很简单,公司的账号登录需要用到微信扫码登录与QQ的登录功能,所以,在做好了微信的扫码登录之后,本人就写这篇微信扫码登录功能实现的教程 教程开始 需要用到的网站: https://open.wei ...

  8. vue实现网页端企业微信扫码登录功能(前端部分)

     时至今日,企业微信在企业日常工作中的使用越来越频繁也越来越重要,不少企业已使用企业微信进行着日常的工作安排管理.在这种背景下,各类系统和企业微信对接的需求也不断增加,今天要说的就是一个比较常见的需求 ...

  9. 一篇文章,带你了解微信扫码登录

    文章目录 前言 一.功能背景 二.扫码登录原理 1.基本原理 三.实现效果图 1.登录页 2.点击微信账号登录 3.已绑定微信的账号 4.未绑定微信号的账号 四.代码实现 1.准备工作 2.编写代码 ...

最新文章

  1. java编辑简单文本编辑器_简单的Java纯文本编辑器
  2. python是软件吗-python运行环境是什么
  3. C语言实例第6期:反转字符串
  4. 如何在 SAPGUI 的同一个屏幕显示两个 ALV list
  5. Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式。
  6. C#LeetCode刷题之#167-两数之和 II - 输入有序数组(Two Sum II - Input array is sorted)
  7. ansible web_最小的Web浏览器,Microsoft Access替代品,Ansible,Kubernetes,JavaScript,piwheel等
  8. Java笔记(十七) 异步任务执行服务
  9. LeetCode(606)——根据二叉树创建字符串(JavaScript)
  10. GB28181-2016系统相关技术介绍
  11. 短信验证码和语音验证码
  12. cesium设置相机的初始位置
  13. 启发式算法Python代码库——scikit-opt
  14. mysql存emoji_如何在MySQL中存储emoji?
  15. svn服务器安装位置,ubuntu下svn服务器安装配置--经过本人测试(非wwj)
  16. js混淆还原工具_js混淆解密 还原混淆方法
  17. FlashFXP的使用
  18. 红白机 编译6502汇编生成NES文件的通用Makefile
  19. 北京海纳互联网研究中心:中国数字对讲机市场纷杂,MOTO继续领跑高端
  20. cfc 教程_通用开发人员第2部分的CFC

热门文章

  1. 解决:is not eligible for getting processed by all BeanPostProcessors
  2. ASP.NET 入门
  3. CVPR 2022 Oral 学习不分割的内容:关于小样本分割的新视角
  4. android 调试驱动程序,Android驱动程序开发和调试环境配置
  5. 用禅宗理解、软件开发的境界
  6. Functional Programming in Java venkat(3) Using Collections part1
  7. 2019北大计算机夏令营,2019年北京大学化学学院“全国优秀大学生夏令营”第三轮通知...
  8. DIAC-WOZ数据集(二)---Visual signals
  9. 生物智能与AI——关乎创造、关乎理解
  10. vue element 日期范围选择器限制只能选今天之前的时间,或者只能选今天之后的时间