如何实现微信扫码登录 您所在的位置:网站首页 小栗子框架293怎么扫码登录 如何实现微信扫码登录

如何实现微信扫码登录

2023-12-19 16:04| 来源: 网络整理| 查看: 265

第三方登录

用户不想去注册你的网站,觉得输入这些信息麻烦。更愿意像直接扫码进行登录这样,简单。

扫码人的信息自动注册,加入到你的数据库中。

微信登录是一个固定的流程,是腾讯规定的固定流程去做。

微信登录讲解之前,先讲解OAuth2

OAuth2是什么?

OAuth2是针对特定问题的一种解决方案。

主要可以解决两个问题:

   1. 开放系统间授权   2.分布式访问问题

开放系统间授权:

lucy照了很多照片,她把它们都存到了自己的百度网盘上去了。但是百度网盘没法打印照片啊,某公司自己研发了一款系统,专门用于这种云存储的打印服务。

但是,默认情况下,这款系统默认是不能操作lucy存到她百度网盘上的东西的。没有权限。

但是百度网盘提供了授权服务的相关方法。

这个时候,只要lucy授权给这款打印系统,那么就可以实现打印服务。

具体怎么做到的,这就是OAuth2要做的事情。也是百度网盘要规定的流程。

分布式访问

我们只需要把token相关的代码抽取出来,生成一个公共的类。

这样,即使是不同的模块之间,他们的token创建和解析的加密方式也都是一样的,也就能解析到cookie中传过来的token信息,进行登录。

当然了,我们可以使用redis存储token以及对应用户信息,这样不同模块就都能拿到用户信息。否则的话,我们只知道是当前用户,当前用户的用户信息,也只是token解析出来的信息。比如用户id。当然,因为用户id具有唯一性嘛,所以通过用户id关联自己模块的业务也是可以的。比如:某人登录了视频服务,在视频服务会存储一个视频记录的数据表。这个时候,只要数据表关联用户id就可以了。对于视频服务而言,是没有问题的。

OAuth2解决方案:按照一定规则生成字符串,字符串包含用户信息。

OAuth2只是一种解决方案,这种方案具体怎么做由方案提供者自己定。

下面我们开始进行微信扫码登录:

准备工作

1. 首先你想要使用腾讯公司微信做登录这样的相关操作,必须在腾讯的开发者平台注册,获得资质!微信开放平台

(1) 支持企业类型(以前只支持企业注册)

(2) 注册之后,会给你提供微信id和微信密钥

ps:注册需要准备营业执照、1-2个工作日审批、300元认证费

2. 申请网站应用名称。

就是说你扫描二维码,它会显示当前网站的应用名称,比如:我的谷粒。这个一般在7个工作日内审批。

3. 需要域名地址。

地址作用:微信扫完二维码之后,找你的域名做跳转。

熟悉微信登录流程:

下面我们快速看一下

参考文档:微信开放平台

1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数; 2. 通过code参数加上AppID和AppSecret等,通过API换取access_token; 3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

后端开发(重点) 1、添加配置

在你的用户模块中,application.properties添加相关配置信息

# 微信开放平台 appid wx.open.app_id=你的appid # 微信开放平台 appsecret wx.open.app_secret=你的appsecret # 微信开放平台 重定向url wx.open.redirect_url=http://你的服务器名称/api/ucenter/wx/callback 2、创建常量类

创建util包,创建ConstantWxUtils.java常量类

package com.atguigu.educenter.utils; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class ConstantWxUtils implements InitializingBean { @Value("${wx.open.app_id}") private String appId; @Value("${wx.open.app_secret}") private String appSecret; @Value("${wx.open.redirect_url}") private String redirectUrl; public static String WX_OPEN_APP_ID; public static String WX_OPEN_APP_SECRET; public static String WX_OPEN_REDIRECT_URL; @Override public void afterPropertiesSet() throws Exception { WX_OPEN_APP_ID = appId; WX_OPEN_APP_SECRET = appSecret; WX_OPEN_REDIRECT_URL = redirectUrl; } } 3、生成微信扫描的二维码

直接请求微信提供的固定的地址,向地址的后面拼接参数即可。

即重定向到微信的二维码生成地址去。

https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirects

参数说明:

参数是否必须说明appid是应用唯一标识redirect_uri是请使用urlEncode对链接进行处理response_type是填codescope是应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即state否用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验

在当前educenter模块中创建api包

api包中创建WxApiController

代码的写法

package com.atguigu.educenter.controller; import com.atguigu.educenter.utils.ConstantWxUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.net.URLEncoder; @CrossOrigin @Controller //只是请求地址,不需要返回数据,这个时候不能用@RestController @RequestMapping("/api/ucenter/wx") public class WxApiController { //1 生成微信扫描二维码 @GetMapping("login") public String getWxCode() { //固定地址,后面拼接参数 //写法一(这么做效率很低,多了还容易写错): // String url = "https://open.weixin.qq.com/connect/qrconnect" + // "?appid="+ // ConstantWxUtils.WX_OPEN_APP_ID + // "&redirect_uri=" + // ConstantWxUtils.WX_OPEN_REDIRECT_URL + // "&response_type=code" + // "&scope=snsapi_login" + // "state=atguigu" + // "#wechat_redirect"; //当然,上面这个redirect_uri地址要先编码再进行传,不能那样直接传。 //写法二(推荐) // 微信开放平台授权baseUrl %s 相当于?标识占位符 String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" + "?appid=%s" + "&redirect_uri=%s" + "&response_type=code" + "&scope=snsapi_login" + "&state=%s" + "#wechat_redirect"; //对redirect_url进行URLEncoder编码 String redirectUrl = ConstantWxUtils.WX_OPEN_REDIRECT_URL; try { redirectUrl = URLEncoder.encode(redirectUrl, "utf-8"); }catch(Exception e) { } //设置%s里面值 String url = String.format( baseUrl, ConstantWxUtils.WX_OPEN_APP_ID, redirectUrl, "atguigu" ); //重定向到请求微信地址里面 return "redirect:" + url; } }

此时启动改服务,然后请求当前接口:localhost:8160/api/ucenter/wx/login

它会根据你接口中写的代码,重定向到微信的二维码生成地址,拼接的参数就是你传的参数

比如:

https://open.weixin.qq.com/connect/qrconnect?appid=wxed9954c01bb80b37&redirect_uri=http%3A%2F%2Flocalhost%3A8160%2Fapi%2Fucenter%2Fwx%2Fcallback&response_type=code&scope=snsapi_login&state=atguigu#wechat_redirect

 4.扫描后获取用户信息的过程

扫描成功确认之后,微信会获取到用户的一个code值。然后微信会把code值给到我们,跳转到如下我们的回调地址,地址后拼接了code参数和state参数:

localhost:8160/api/ucenter/wx/callback?code=021Grg0w34r37Z2c9S2w3xmv180Grg0o&state=atguigu

api/ucenter/wx/callback肯定不是我们的地址,我们还没有写这个方法。

ps:这个回调地址就是我们之前在配置文件中配置的redirect_url重定向地址,它是当初注册资质时填写的域名地址。在获取验证码时就传递给了微信,这个时候微信在将地址返回给我们。

wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback

这个回调方法的作用就是用于我们获取用户信息。微信说让我们用这个接口去请求用户信息。

下面我们就需要自己来写这个回调方法,在方法里面,通过获取到微信传回来的code值,带着这个值去请求微信另外的一个固定地址获取asses_token,openid

通过httpclint直接请求微信,然后获取到返回的accsess_token 和 openid信息。

接着我们可以把它当前用户信息加入到自己的数据库。(你也可以选择不加入)

首先判断当前用户的openid是否在自己的数据库已经存在,如果存在不用添加了。

如果不存在,那么就通过这个accsess_token 和 openid再去请求微信的又一个固定地址,获取用户信息。

还是通过HttpClient发送请求,然后接收返回值。

一样也需要通过json转换工具转换成字符串。否则是json格式的数据无法操作。

拿到用户信息后我们就可以加入到自己的数据库里面了。

我们看看代码怎么写:

package com.atguigu.educenter.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.atguigu.commonutils.JwtUtils; import com.atguigu.educenter.bean.UcenterMember; import com.atguigu.educenter.service.UcenterMemberService; import com.atguigu.educenter.utils.ConstantWxUtils; import com.atguigu.educenter.utils.HttpClientUtils; import com.atguigu.servicebase.exceptionHandler.GuliException; import com.google.gson.Gson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; @CrossOrigin @Controller //只是请求地址,不需要返回数据。这个时候不能用@RestController @RequestMapping("/api/ucenter/wx") public class WxApiController { @Autowired private UcenterMemberService memberService; //2 获取扫描人信息,添加数据 @GetMapping("callback") public String callback(String code, String state) { try { //1 获取code值,临时票据,类似于验证码 //2 拿着code请求 微信固定的地址,得到两个值 accsess_token 和 openid String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" + "?appid=%s" + "&secret=%s" + "&code=%s" + "&grant_type=authorization_code"; //拼接三个参数 :id 秘钥 和 code值 String accessTokenUrl = String.format( baseAccessTokenUrl, ConstantWxUtils.WX_OPEN_APP_ID, ConstantWxUtils.WX_OPEN_APP_SECRET, code ); //请求这个拼接好的地址,得到返回两个值 accsess_token 和 openid //使用httpclient发送请求,得到返回结果 String accessTokenInfo = HttpClientUtils.get(accessTokenUrl); //从accessTokenInfo字符串获取出来两个值 accsess_token 和 openid //把accessTokenInfo字符串转换map集合,根据map里面key获取对应值 //使用json转换工具 Gson Gson gson = new Gson(); HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class); String access_token = (String)mapAccessToken.get("access_token"); String openid = (String)mapAccessToken.get("openid"); //把扫描人信息添加数据库里面 //判断数据表里面是否存在相同微信信息,根据openid判断 UcenterMember member = memberService.getOpenIdMember(openid); if(member == null) {//memeber是空,表没有相同微信数据,进行添加 //3 拿着得到accsess_token 和 openid,再去请求微信提供固定的地址,获取到扫描人信息 //访问微信的资源服务器,获取用户信息 String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" + "?access_token=%s" + "&openid=%s"; //拼接两个参数 String userInfoUrl = String.format( baseUserInfoUrl, access_token, openid ); //发送请求 String userInfo = HttpClientUtils.get(userInfoUrl); //获取返回userinfo字符串扫描人信息 HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class); String nickname = (String)userInfoMap.get("nickname");//昵称 String headimgurl = (String)userInfoMap.get("headimgurl");//头像 member = new UcenterMember(); member.setOpenid(openid); member.setNickname(nickname); member.setAvatar(headimgurl); memberService.save(member); } //使用jwt根据member对象生成token字符串 String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname()); //最后:返回首页面,通过路径传递token字符串 return "redirect:http://localhost:3000?token="+jwtToken; }catch(Exception e) { throw new GuliException(20001,"登录失败"); } } //1 生成微信扫描二维码 @GetMapping("login") public String getWxCode() { //固定地址,后面拼接参数 //写法一(这么做效率很低,多了还容易写错): // String url = "https://open.weixin.qq.com/connect/qrconnect" + // "?appid="+ // ConstantWxUtils.WX_OPEN_APP_ID + // "&redirect_uri=" + // ConstantWxUtils.WX_OPEN_REDIRECT_URL + // "&response_type=code" + // "&scope=snsapi_login" + // "state=atguigu" + // "#wechat_redirect"; //当然,上面这个redirect_uri地址要先编码再进行传,不能那样直接传。 //写法二(推荐) // 微信开放平台授权baseUrl %s 相当于?标识占位符 String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" + "?appid=%s" + "&redirect_uri=%s" + "&response_type=code" + "&scope=snsapi_login" + "&state=%s" + "#wechat_redirect"; //对redirect_url进行URLEncoder编码 String redirectUrl = ConstantWxUtils.WX_OPEN_REDIRECT_URL; try { redirectUrl = URLEncoder.encode(redirectUrl, "utf-8"); }catch(Exception e) { } //设置%s里面值 String url = String.format( baseUrl, ConstantWxUtils.WX_OPEN_APP_ID, redirectUrl, "atguigu" ); //重定向到请求微信地址里面 return "redirect:" + url; } }

当然json转换工具你自己选择,fastjson也可以。比如:

//对比Gson和FastJson //Gson Gson gson = new Gson(); HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class); String access_token = (String)mapAccessToken.get("access_token"); String openid = (String)mapAccessToken.get("openid"); //FastJson Map parse = (Map) JSON.parse(accessTokenInfo); String access_token1 = (String) parse.get("access_token"); System.out.println(access_token1 +"这是fastjson解析出来的");

 我们这里怎么写都对,因为都是localhost,但是实际项目中,我们不建议这么做。

 然后在首页页面中显示用户信息



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有