微信开放平台:微信扫码登录功能
正式文件:develo .
1.批准流程说明
微信OAu认证登录允许微信用户使用微信id安全登录第三方应用程序或网站,在微信用户授权访问微信OAu的第三方应用程序登录后,第三方可以获取用户的接口调用凭证(access_token),通过ACESS _ TOKEN可以进行微信开放平台认证关系接口调用,从而获得微信用户的基本开放信息
微信OAu授权登录目前支持authorization_CODE模式,适用于拥有server端的应用授权。该模式整体流程为:
① 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
② 通过code参数加上AppID和AppSecret等,通过API换取access_token;
③ 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
第一步:请求CODE
第三方使用网站应用授权登录前请注意已获取相应网页授权作用域(scope=snsapi_login),则可以通过在PC端打开以下链接:;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 复制代码
例如:登录一号店网站应用 打开后,一号店会生成state参数,跳转到 ;redirect_uri=https%3A%2F%2F;response_type=code&scope=snsapi_login&state=3d6be0a4035d839573b04816624a415e#wechat_redirect 微信用户使用微信扫描二维码并且确认登录后,PC端会跳转到 ;state=3d6be0a4035d839573b04816624a415e
第二步:通过code获取access_token
通过code获取access_token
a…
返回说明
正确的返回:
{ "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云端服务器,由云端中转接口调用请求。
第三步:通过access_token调用接口
获取access_token后,进行接口调用,有以下前提:
- access_token有效且未超时;
- 微信用户已授权给第三方应用帐号相应接口作用域(scope)。
对于接口作用域(scope),能调用的接口有以下:
2. 授权流程代码
因为微信开放平台的AppiD和APPSecret和微信公众平台的AppiD和AppSecret都是不同的,因此需要配置一下:
# 开放平台 wec wec 复制代码
@Data @Component @ConfigurationProperties(prefix = "wechat") public class WechatAccountConfig { //公众号appid private String mpAppId; //公众号appSecret private String mpAppSecret; //商户号 private String mchId; //商户秘钥 private String mchKey; //商户证书路径 private String keyPath; //微信支付异步通知 private String notifyUrl; //开放平台id private String openAppId; //开放平台秘钥 private String openAppSecret; }
@Configuration public class WechatOpenConfig { @Autowired private WechatAccountConfig accountConfig; @Bean public WxMpService wxOpenService() { WxMpService wxOpenService = new WxMpServiceImpl(); wxO(wxOpenConfigStorage()); return wxOpenService; } @Bean public WxMpConfigStorage wxOpenConfigStorage() { WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage(); wxM()); wxM()); return wxMpInMemoryConfigStorage; } }
@Controller @RequestMapping("/wechat") @Slf4j public class WeChatController { @Autowired private WxMpService wxMpService; @Autowired private WxMpService wxOpenService; @GetMapping("/qrAuthorize") public String qrAuthorize() { //returnUrl就是用户授权同意后回调的地址 String returnUrl = ";; //引导用户访问这个链接,进行授权 String url = wxO(returnUrl, WxCon, URLEncoder.encode(returnUrl)); return "redirect:" + url; } //用户授权同意后回调的地址,从请求参数中获取code @GetMapping("/qrUserInfo") public String qrUserInfo(@RequestParam("code") String code) { WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken(); try { //通过code获取access_token wxMpOAuth2AccessToken = wxO(code); } catch (WxErrorException e) { log.error("【微信网页授权】{}", e); throw new SellException(), e.getError().getErrorMsg()); } //从token中获取openid String openId = wxM(); //这个地址可有可无,反正只是为了拿到openid,但是如果没有会报404错误,为了好看随便返回一个百度的地址 String returnUrl = ";; log.info("openid={}", openId); return "redirect:" + returnUrl + "?openid="+openId; } }
请求路径:在浏览器打开
o…
获取了openid:openid=o9AREv7Xr22ZUk6BtVqw82bb6AFk
3. 用户登录和登出
@Controller @RequestMapping("/seller") public class SellerUserController { @Autowired private SellerService sellerService; @Autowired private StringRedisTemplate redisTemplate; @Autowired private ProjectUrlConfig projectUrlConfig; @GetMapping("/login") public ModelAndView login(@RequestParam("openid") String openid, HttpServletResponse response, Map<String, Object> map) { //1. openid去和数据库里的数据匹配 SellerInfo sellerInfo = (openid); if (sellerInfo == null) { map.put("msg", Re()); map.put("url", "/sell/seller/order/list"); return new ModelAndView("common/error"); } //2. 设置token至redis String token = UUID.randomUUID().toString(); //设置token的过期时间 Integer expire = Redi; redi().se, token), openid, expire, TimeUnit.SECONDS); //3. 设置token至cookie CookieU(response, CookieCon, token, expire); return new ModelAndView("redirect:" + ";); } @GetMapping("/logout") public ModelAndView logout(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) { //1. 从cookie里查询 Cookie cookie = CookieU(request, CookieCon); if (cookie != null) { //2. 清除Redis redi().getOperations().delete, cookie.getValue())); //3. 清除cookie CookieU(response, CookieCon, null, 0); } map.put("msg", Re()); 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_token wxMpOAuth2AccessToken = wxO(code); } catch (WxErrorException e) { log.error("【微信网页授权】{}", e); throw new SellException(), e.getError().getErrorMsg()); } //从token中获取openid String openId = wxM(); //授权成功后跳转到卖家系统的登录地址 String returnUrl = ";; log.info("openid={}", openId); return "redirect:" + returnUrl + "?openid="+openId; }
③ 在浏览器请求这个链接:https://oonnect?appid=wx6ad144e54af67d87&redirect_uri=http%3A%2F%2F;response_type=code&scope=snsapi_login&state=http%3a%2f%2
第三应用请求使用微信扫码登录,而不是使用本网站的密码:
用户同意授权后登入第三方应用的后台管理系统:
4. Spring AOP校验用户有没有登录
@Aspect @Component @Slf4j public class SellerAuthorizeAspect { @Autowired private StringRedisTemplate redisTemplate; @Pointcut("execution(public * com.*.*(..))" + "&& !execution(public * com.UserController.*(..))") public void verify() {} @Before("verify()") public void doVerify() { ServletRequestAttributes attributes = (ServletRequestAttributes) Reque(); HttpServletRequest request = a(); //查询cookie Cookie cookie = CookieU(request, CookieCon); //如果cookie中没有token说明已经登出或者根本没有登录 if (cookie == null) { log.warn("【登录校验】Cookie中查不到token"); //校验不通过,抛出异常 throw new SellerAuthorizeException(); } //去redis里查询 String tokenValue = redi().ge, cookie.getValue())); //如果redis中没有对应的openid,同样表示登出或者根本没有登录 if (tokenValue)) { log.warn("【登录校验】Redis中查不到token"); throw new SellerAuthorizeException(); } } }
5. 拦截登录校验不通过抛出的异常
拦截及登录校验不通过的异常,让其跳转到登录页面,扫码登录
@ControllerAdvice public class SellExceptionHandler { //拦截登录异常 @ExceptionHandler(value = SellerAu) public ModelAndView handlerAuthorizeException() { //拦截异常后,跳转到登录界面 return new ModelAndView("redirect:".concat("https://oonnect?" + "appid=wx6ad144e54af67d87" + "&redirect_uri=http%3A%2F%2F; + "oTgZpwenC6lwO2eTDDf_-UYyFtqI" + "&response_type=code&scope=snsapi_login" + "&state=http%3a%2f%2")); } @ExceptionHandler(value = SellExce) @ResponseBody public ResultVO handlerSellerException(SellException e) { return Re(), e.getMessage()); } @ExceptionHandler(value = ResponseBankExce) @ResponseStatu) public void handleResponseBankException() { } }
作者:公众号_IT老哥
链接:
1.《【微信登录二维码扫一扫】微信扫码登录很难吗?5步帮你搞定》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《【微信登录二维码扫一扫】微信扫码登录很难吗?5步帮你搞定》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/yule/3188919.html