微信扫码登录(java)

相关视频:

黑马java开发实战,java必会技能,通过OAuth 2.0开放授权实现微信扫码登录第三方平台_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1vh4y187an/?spm_id_from=333.337.search-card.all.click&vd_source=60a35a11f813c6dff0b76089e5e138cc

微信官方文档:

微信网页开发 / 网页授权 (qq.com)icon-default.png?t=N7T8https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

二维码生成平台(网页版):

草料二维码生成器 (cli.im)icon-default.png?t=N7T8https://cli.im/

测试公众号网址:

微信公众平台 (qq.com)icon-default.png?t=N7T8https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

内网穿透工具:

cpolar - secure introspectable tunnels to localhosticon-default.png?t=N7T8https://dashboard.cpolar.com/get-started

微信扫码登录的优点:

微信扫码登录是一种方便快捷的登录方式,它允许用户通过扫描二维码来完成登录过程,无需手动输入账号和密码。以下是微信扫码登录的详细介绍及其优点:

介绍:

  1. 操作流程:在微信的登录界面上,用户可以选择“扫码登录”选项。此时,系统会生成一个二维码,并提示用户使用另一台设备(如手机)打开微信扫一扫功能进行扫描。在另一台设备上打开微信扫一扫功能后,将摄像头对准二维码进行扫描,微信会自动识别并验证二维码的有效性。验证成功后,登录设备将显示用户的微信账号信息,用户只需点击确认登录按钮即可完成登录过程。
  2. 应用场景:微信扫码登录广泛应用于各种场景,如电脑端微信登录、网页版微信登录、小程序登录等。此外,许多第三方应用也支持微信扫码登录功能,方便用户快速登录并授权访问相关信息。

优点:

  1. 方便快捷:微信扫码登录无需手动输入账号和密码,只需简单的扫描操作即可完成登录,大大提高了登录效率。对于经常需要登录的用户来说,这种方式更加省时省力。
  2. 安全性高:相比于传统的账号密码登录方式,微信扫码登录更加安全。因为在扫描过程中不会暴露用户的账号和密码信息,有效降低了账号被盗的风险。同时,微信扫码登录还需要用户在手机端进行确认操作,增加了登录的安全性。
  3. 体验良好:微信扫码登录无需手动输入任何信息,对于移动设备用户来说尤为友好。此外,由于登录过程更加简便快捷,用户的整体使用体验也会得到提升。

理论基础:

学习微信扫码登录的必要知识

OAuth2.0:

OAuth(Open Authorization)是一个关于授权(authorization)的开放性网络标配,允许用户授权第三方应用访问他们储存在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方。

协议特点:

  • 简单:不管是OAuth服务提供者还是应用开发者,都很易于理解与使用。
  • 安全:没有涉及到用户密钥等信息,跟安全更灵活。
  • 开放:任何服务提供商都可以实现OAuth,任何软件开发商都可以使用OAuth。

OAuth在全世界得到广泛应用,目前的版本是2.0版

OAuth(Open Authorization)是一个关于授权(authorization)的开放网络标准,它在全世界得到了广泛应用,并且目前的版本是2.0版。OAuth 2.0允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容。

OAuth 2.0的特点包括简单性、安全性和开放性。对于OAuth服务提供者和应用开发者来说,它都很容易理解和使用。同时,由于它没有涉及到用户密钥等信息,因此更加安全灵活。此外,任何服务提供商都可以实现OAuth,任何软件开发商都可以使用OAuth,这也体现了其开放性。

OAuth 2.0的应用场景非常广泛,包括原生app授权、前后端分离单页面应用以及第三方应用授权登录等。在原生app授权中,app登录请求后台接口需要携带token信息以进行安全认证。在前后端分离单页面应用中,前端请求后台数据需要进行OAuth 2.0安全认证。此外,许多第三方应用也支持OAuth 2.0授权登录,如QQ、微博、微信等。

关于OAuth 2.0的运行流程,当用户打开客户端并请求授权时,客户端会向授权服务器发送授权请求。授权服务器对客户端进行认证后,如果确认无误,就会同意发放令牌。然后,客户端使用这个令牌向资源服务器申请获取资源。

总的来说,OAuth 2.0作为一种开放的网络标准,在保护用户隐私和数据安全的同时,提供了便捷的第三方应用授权方式,使得用户可以更加放心地使用各种网络服务。

角色说明:

OAuth2.0_角色说明
角色说明
客户端本身不存储资源,需要通过资源拥有者授权去请求资源服务器的资源(App游戏、影视网站等)
资源拥有者通常为用户,也可以是应用程序,即资源拥有者
授权服务器(认证服务器)用于服务提供商对资源拥有者的身份进行认证、对访问资源进行授权,认证成功后会给客户发放令牌,作为客户端访问资源服务器的凭据
资源服务器储存资源的服务器,比如微信端储存的用户信息

四种授权模式:

授权码模式(Authorization Code Grant)

隐式授权模式(Implicit Grant)

用户名密码模式(Resource Owner Password Credentials Grant)

客户端模式(Client Credentials Grant)

二维码:

二维码(dimensional barcode),又称二维条码,是在一维条码的基础上扩展出的一种具有可读性的条码。设备扫描二维条码,通过识别条码的长度和宽度中所记载的二进制数据,可获取其中所包含的信息
总之:二维码是信息的载体

二维码,又称二维条码,是一种在平面上按照特定规律分布的黑白相间的图形,用于记录数据符号信息。它的原理是利用计算机内部的“0”和“1”比特流的概念,通过特定的几何图形来表示文字数值信息。二维码具有条码技术的一些共性,如每种码制都有其特定的字符集,每个字符占有一定的宽度,并且具有一定的校验功能。

二维码可以分为堆叠式二维码和矩阵式二维码。在矩阵式二维码中,通过在矩阵相应元素位置上用方点、圆点或其他形状的点来表示二进制“1”,而不出现点则表示二进制的“0”。这些点的排列组合确定了矩阵式二维码所代表的意义。矩阵式二维码是建立在计算机图像处理技术、组合编码原理等基础上的一种新型图形符号自动识读处理码制。

二维码具有许多优点,如数据容量大(最大可存储1850个字符)、纠错能力强、可以表示图像和多种语言、易于加密处理等。因此,二维码被广泛应用于电子公文、票据、证件管理、包裹、货运物品追踪、仓储盘点、出版印刷业信息交换等领域,极大地提高了数据采集和信息处理的速度,提高了工作效率,为管理的科学化和现代化做出了积极贡献。

此外,随着移动设备的普及和二维码技术的发展,移动二维码也逐渐成为了一种新的趋势。移动二维码可以方便地将线下和线上的信息连接起来,为用户提供更加便捷的服务。例如,用户可以通过扫描二维码来快速获取商品信息、参与抽奖活动、进行移动支付等。

二维码生成(网页版):

二维码生成(java版):

Hutool是一个java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类

导入maven依赖:

<dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.7.14</version>
</dependency>
<dependency>
        <groupId>com.google.zxing</groupId>
        <artifactId>core</artifactId>
        <version>3.4.1</version>
</dependency>

生成二维码:

QrCodeUtil.generate(url,width,height,FileUtil.file(path));

例:

生成指定url对应的二维码到文件,宽和高都是300像素

QrCodeUtil.generate("https://hutool.cn",300,300,FileUtil.file("d:/test/test001.jpg"));

  • url:保存的是二维码的信息(String)
  • width:二维码的宽度(int)
  • heigth:二维码的高度(int)
  • path:二维码生成后保存的位置路径(String)
二维码的纠错级别:
  • L、M、Q、H由低到高。
  • 低级别的像素块更大,可以远距离识别,但是遮挡就会造成无法识别。
  • 高级别则相反,像素块小,允许遮挡一定范围,但是像素块更密集。

/**
* 生成一个600 * 600二维码
* 纠错级别设置为H
* L、M、Q、H几个参数,由低到高。低级别的像素块更大
*/
QrConfig config = new QrConfig(600, 600);
config.setErrorCorrection(ErrorCorrectionLevel.H);
QrCodeUtil.generate("hello world", config, FileUtil.file("d:/test001.jpg"));

  • 设置背景颜色为蓝色:config.setBackColor(Color.BLUE);
  • 设置照片:config.setImg();

准备工作:

账号申请:

扫码登录微信有两种实现方式:

基于微信公众平台的扫码登录:
        让第三方应用投入微信的怀抱而设计的,这第三方应用指的是比如android、ios、网站、系统等。
基于微信开放平台的扫码登录:
        为了让程序员小伙伴利用微信自家技术(公众号、小程序)开发公众号、小程序而准备的。

区别:

微信开放平台需要企业认证才能注册。

微信公众平台需要认证微信服务号,才能进行扫码登录的开发。只需要申请一个公众号。

接口配置:

测试公众号申请:

微信公众平台 (qq.com)icon-default.png?t=N7T8https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

注意点:

url可以使用内网穿透工具Cpolar来完成。

cpolar - secure introspectable tunnels to localhosticon-default.png?t=N7T8https://dashboard.cpolar.com/get-started

token目前随意填写不影响配置。

@RestController
public class WeChatController {

    private String url = "http://3e08854f.r11.cpolar.top";

    @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
    ) {
        System.out.println("收到微信效验请求,signature:{}" + signature);
        System.out.println("收到微信效验请求,timestamp:{}" + timestamp);
        System.out.println("收到微信效验请求,nonce:{}" + nonce);
        System.out.println("-------------------------------");
        System.out.println("收到微信效验请求,echostr:{}" + echostr);

        return echostr;
    }
}

测试号二维码:

自己扫码添加测试账号,不然会失败,使用其他的微信号也会失败

和上面配置的接口信息一致就行,不要带有http等

实现细节:

第一步:用户同意授权,获取code

在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(已认证服务号,默认拥有scope参数中的snsapi_base和snsapi_userinfo 权限),引导关注者打开如下页面:

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

private String url = "http://3e08854f.r11.cpolar.top";

@GetMapping("/wxLogin")
    public void wxLoginPage(HttpServletResponse response) throws Exception {
        System.out.println("____________________--wxLogin");
        //redirect_url是回调地址 注意要转换成UrlEncode格式
        String redirectUrl = URLEncoder.encode(url+"/wxCallback","UTF-8");
        //构造二维码链接地址
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=自己写"+"&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());

    }

第二步:通过code换取网页授权access_token

首先请注意,这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。

尤其注意:由于公众号的secret和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。

获取code后,请求以下链接获取access_token:

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

@RequestMapping("/wxCallback")
    public String pcCallback(String code, String state, HttpServletRequest request, HttpServletResponse response,
                             HttpSession session) throws Exception{
        System.out.println("____________________--wxCallback");
        WeChatUser user = WechatUtil.getUserInfo(code);
        //TODO 缓存用户信息,构造session
        return JSON.toJSONString(user);
    }
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WeChatUser {
    /**
     * 用户唯一标识
     */
    private String openid;

    /**
     * 用户昵称
     */
    private String nickname;

    /**
     *  用户性别,值为1时是男性,值为2时是女性,值为0时是未知
     */
    private String sex;

    /**
     * 用户所在国家
     */
    private String country;

    /**
     * 用户所在城市
     */
    private String city;

    /**
     * 用户所在省份
     */
    private String province;

    /**
     * 用户头像
     */
    private String headimgurl;

    /**
     * 用户特权信息,json 数组
     */
    private String privilege;

    /**
     * 用户是否关注公众号
     */
    private String unionid;
}
import com.alibaba.fastjson.JSON;
import com.example.pojo.TokenInfo;

import com.example.pojo.WeChatUser;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;



public class WechatUtil {

   private static String appId = "自己写";
   private static String appSecret = "自己写";

   private static TokenInfo tokenInfo;



    public static WeChatUser getUserInfo(String code) throws Exception{
        //构造http请求客户端
        CloseableHttpClient httpclient = HttpClients.createDefault();
        //用code交换token,code为扫码后微信服务器响应来的值
        String smsUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "appid=" + appId +
                "&SECRET=" + appSecret +
                "&code=" + code +
                "&grant_type=authorization_code";
        //发送请求
        HttpGet httpGet = new HttpGet(smsUrl);
        String responseResult = "";
        //接收返回的数据,转换成utf-8格式
        HttpResponse response = httpclient.execute(httpGet);
        if(response.getStatusLine().getStatusCode() == 200){
            responseResult = EntityUtils.toString(response.getEntity(), "utf-8");
        }
        System.out.println("获取accessToken返回结果:{}" + responseResult);
        //将结果封装到TokenInfo对象中
        JSON.parseObject(responseResult, TokenInfo.class);
        //将结果封装到TokenInfo对象中
        tokenInfo = JSON.parseObject(responseResult, TokenInfo.class);








//第四步代码









        //用accessToken获取扫码人的个人信息
        String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?" +
                "access_token=" + tokenInfo.getAccess_token() +
                "&openid=" + tokenInfo.getOpenid() +
                "&lang=zh_CN";

        //构造http请求客户端
        HttpGet httpGet1 = new HttpGet(userInfoUrl);

        //接收数据
        HttpResponse response1 = httpclient.execute(httpGet1);
        if(response1.getStatusLine().getStatusCode() == 200){
            responseResult = EntityUtils.toString(response1.getEntity(), "utf-8");
        }
        System.out.println("获取个人信息返回:{}" + responseResult);
        //将收到的用户信息转化为WeChatUser对象
        WeChatUser weChatUser = JSON.parseObject(responseResult, WeChatUser.class);

        return weChatUser;

    }
}

第三步:刷新access_token(如果需要)

由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token有效期为30天,当refresh_token失效之后,需要用户重新授权。

获取第二步的refresh_token后,请求以下链接获取access_token:

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

第四步:拉取用户信息(需scope为 snsapi_userinfo)

如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。

http:GET(请使用https协议):

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

疑问(作者也是这个问题,感觉他说的有道理):

  • 13
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懿·格雷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值