一、概述
1、什么是OAuth 2.0
OAuth (Open Authorization) 是一个关于授权 (athorization) 的开放网络标准。
允许用户授权第三应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方。OAuth在全世界得到广泛应用,目前的版本是2.0版。
允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。
协议特点:
- 简单: 不管是OAuth服务提供者还是应用开发者,都很易于理解与使用
- 安全:没有涉及到用户密钥等信息,更安全更灵活;
- 开放: 任何服务提供商都可以实现OAuth,任何软件开发商都可以使用OAuth
授权码模式 是最常用的模式
2、使用第三方登录的原因和好处?
- 第三方登录简单快捷,面对不同平台不同的用户名和密码的问题,第三方登录正好解决这个问题,几乎可以直接一个账号搞定所有
- 第三方登录还可以将自己在某个应用的动态信息同步到当前应用下,无需还在为每个应用重新写个人资料
- 第三方登录有很多资料信息可以公用 (比如头像和昵称) ,通常对于敏感资料如手机、邮箱是第三方平台是不会提供的,所以安全信息可以放心
总的来说它可以简化登录过程,降低注册门槛,更能获取海量用户有效降低了用户的流失。
因此本地注册的稳定+第三方登录的便捷才是最合适的登录方案
第三方登录接入后,应用可直接获取用户昵称、头像、用户ID等信息,方便产品获取用户的基本资料,减少产品设计成本
目前市面上的短信验证码的价钱约在0.05元左右,当用户选择使用第三方登录时,可有效减少产品的登录成本。
3、对于第三方平台而言
增加用户对平台的依赖,用户越多使用本平台的第三方登录,就代表着平台对该用户的粘性越高
获得更广泛的影响力,只要用户使用提供第三方登录的应用,那么这个提供第三方登录的品牌就会被用户浏览,有利于对平台的拉新和促活
二、Java生成二维码
二维码(dimensionalbarcode),又称二维条码,是在一维条码的基础上扩展出的一种具有可读性的条码。设备扫描二维条码,通过识别条码的长度和宽度中所记载的二进制数据,可获取其中所包含的信息
简而言之,二维码是信息的载体
比如我们可以将一个网站写入二维码,扫描这个二维码就可打开这个网站。生成二维码我可以直接使用在线的网站生成
但是我们在写程序的时候肯定是无法每次都打开在线网站生成二维码, 因此我们需要导入依赖在java中生成二维码
代码实现
引入依赖
HuTool是一个Java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类。
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.5</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
public class CodeUtil {
public static void main(String[] args) {
QrCodeUtil.generate("https://blog.csdn.net/m0_56308072?spm=1000.2115.3001.5343",
300,300, FileUtil.file("d://qrcode.jpg"));
}
}
纠错级别
三、微信开发平台
准备工作
通常,扫码登录微信有两种实现方式
1、基于微信公众号平台的扫码登录
让第三方应用投入微信的怀抱而设计,这里的第三方指的是比如android、ios、web网站等
2、基于微信开放平台的扫码登录
为了让开发人员利用微信自家的技术,开发公众号、小程序而准备的
我们这里使用微信公众号平台扫码登录实现微信登录,因此需要先申请测试公众号
在这里 微信公众平台 申请
首先我们配置接口信息,注意这个URL是你自己的服务器资源。当点击提交之后,微信服务器就会发送一个GET请求到填写的服务器地址URL上。
首先,这个GET请求携带的参数为
参数 | 描述 |
---|---|
signature | 微信加密签名,signature结合了开发者填写的token和底下那两个时间戳和随机数 |
timestamp | 时间戳 |
nonce | 随机数 |
echostr | 随机字符串 |
这个GET请求发送至我们指定服务器之后,我们需要将其中的参数echostr再return回去,这样是为了告诉微信服务器接入shen了,成为开发者成功;否则接入失败。
加密/校验流程如下
此时我的后端接口为
@GetMapping(value = "/wx", produces = "text/plain;charset=utf-8")
public String authGet(
@RequestParam(name = "signature", required = false) String signature,
@RequestParam(name = "timestamp", required = false) String timestamp,
@RequestParam(name = "nonce", required = false) String nonce,
@RequestParam(name = "echostr", required = false) String echostr) {
log.info("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature,
timestamp, nonce, echostr);
return echostr;
}
注意:此时我们运行起来的springboot服务器是运行在本地的,而上面微信服务器是无法找到我们本地的服务器的。
经过测试,我发现他需要满足两个条件
- 公网上可访问
- 如果使用HTTPS协议,那么就需要有安全的SSL证书
公网上可访问就是指别人或者自己使用不同的网就可以直接访问到我们的网站或者接口,安全SSL证书就是当我们使用https的时候不要报危险
因此为了解决这个问题,我们除了直接将我们springboot服务部署在云服务器上,我们还可以使用内网穿透,将我们的服务器端口暴露在公网上
然后如果你使用https协议的话建议在腾讯云上申请一个域名然后使用腾讯云免费的SSL
具体步骤看这篇博客
springboot开启HTTPS-CSDN博客https://blog.csdn.net/m0_56308072/article/details/135573717?spm=1001.2014.3001.5501
最后 出现配置成功字样即可
之后就是修改网页账号 - 网页授权获取用户基本信息
注意: 这个回调域名不要加协议,不要写端口号、接口,只能写域名
微信网页开发 / 网页授权 (qq.com)https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
代码步骤
@GetMapping("/wxLogin")
@ResponseBody
public void wxLoginPage(HttpServletResponse response) throws Exception{
//回调地址
String redirectUrl = URLEncoder.encode("https://an1ong.online:47727/wxCallback","UTF-8");
//构造二维码链接地址
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=" +
redirectUrl + "&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
response.setContentType("image/png");
//生成二维码
QrCodeUtil.generate(url,300,300,"jpg",response.getOutputStream());
}
这步调用该接口之后会生成一个二维码,扫描该二维码就会回调/wxCallback接口
请求方法
获取code后,请求以下链接获取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?
appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
//构造Http请求客户端
HttpClient httpClient = HttpClients.createDefault();
//用code交换token.code,code为扫码后的微信服务器响应来的值
String tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+ appId +"&secret=" + secret + "&code={}&grant_type=authorization_code";
//发请求
HttpGet httpGet = new HttpGet(tokenUrl);
String responseResult = "";
//结束返回的数据,转成utf-8格式
HttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200){
responseResult = EntityUtils.toString(response.getEntity(),"UTF-8");
}
log.info("获取accessToken结果: [{}}",responseResult);
//将结果封装到TokenInfo对象中
TokenInfo tokenInfo = JSON.parseObject(responseResult,TokenInfo.class);
http:GET(请使用https协议):
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
//用accessToken获取个人扫码信息
String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+ tokenInfo.getAccessToken() +"&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");
}
log.info("获取个人信息返回:{}",responseResult);