微信web扫码登录的大致流程,最后有源码基本是够用了,后续登录这一块会继续完善,会加上shiro、redis,前端准备用react来做,搞个全套的
开始之前我们先来看几个问题,有兴趣的可以了解下欢迎发表评论提出意见
1.为什么网站应用要使用微信登录?
用户 | 开发者 |
---|---|
方便(不用忙于记录自己的各种账号密码) | 能够收集用户的相关信息(大数据时代没数据怎么分析) |
txbb的社交平台基本人人持有,你可能不用微博,但不用微信估计够呛 | 完善的API,微信开放平台了解下 |
看下面几个图感受下掌控社交平台的力量
2.微信登录的原理是什么
微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统
那这里有童鞋要问了这个OAuth2.0是什么东西?
OAuth普及:
OAuth2.0是OAuth协议的延续版本,但不向前兼容OAuth 1.0(即完全废止了OAuth1.0)。 OAuth 2.0关注客户端开发者的简易性。要么通过组织在资源拥有者和HTTP服务商之间的被批准的交互动作代表用户,要么允许第三方应用代表用户获得访问的权限。同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。2012年10月,OAuth 2.0协议正式发布为RFC 6749。
实际上就是:
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用,以微信为例,大多数是你的对外开放信息比如微信头像,昵称等,支付密码什么的想都不要想。
怎么实现的呢:
token这个东西就出来了,可以吧它理解为虎符,皇帝把这个虎符给你,你就可以调用对应权利的士兵。
也由此产生了认证和授权的过程:
这个过程设计三方,
服务提供方 | 用户 | 客户端 |
---|---|---|
例如微信 | 你 | 网站应用 |
存储受保护的资源,如照片,视频,联系人列表 | 存放在服务提供方的受保护的资源的拥有者 | 要访问服务提供方资源的第三方应用,通常是网站,如提供照片打印服务的网站。在认证过程之前,客户端要向服务提供者申请客户端标识 |
过程如下:
用户想操作存放在服务提供方的资源。
用户登录客户端向服务提供方请求一个临时令牌。
服务提供方验证客户端的身份后,授予一个临时令牌。
客户端获得临时令牌后,将用户引导至服务提供方的授权页面请求用户授权。在这个过程中将临时令牌和客户端的回调连接发送给服务提供方。
用户在服务提供方的网页上输入用户名和密码,然后授权该客户端访问所请求的资源。
授权成功后,服务提供方引导用户返回客户端的网页。
客户端根据临时令牌从服务提供方那里获取访问令牌。
服务提供方根据临时令牌和用户的授权情况授予客户端访问令牌。
客户端使用获取的访问令牌访问存放在服务提供方上的受保护的资源。
3.微信登录开发流程是什么?
首先做好准备工作
- 进入微信开放平台并且注册账号
- 创建一个网站应用并且审核通过,这时候你会获取AppID和AppSecret
微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:
- 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
- 通过code参数加上AppID和AppSecret等,通过API换取access_token;
- 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
再看这个图:
是不是有点感觉了,说了这么多到底怎么实现啊!别急看下边
4.具体开发流程是什么?
第一步:请求CODE
下面代码其实就是带着你的appId去给微信要code。
为什么要这个appId呢?确认你的身份。
这个redirect_uri是什么呢?微信确认你的身份后要把code给你,可以看下图step 4;
例如:redirect_uri: http://192.168.1.53:8080/wx/login
成功之后就会进入这个里了
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
/**
* 回调地址处理
* @return
*/
@RequestMapping("/getLoginUrl")
public ApiResponse getLoginUrl() {
//加密state进行验证 回调地址当天有效 防止恶意攻击
byte[] encrypt = AesUtil.encrypt(PWD_MD5 + DateUtils.getYYYYMMdd(), AesUtil.PASSWORD_SECRET_KEY, 16);
String url = null;
try {
url = String.format(AUTHORIZATION_URL, appid, URLEncoder.encode(redirect_uri, "GBK"), SCOPE, AesUtil.parseByte2HexStr(encrypt));
} catch (UnsupportedEncodingException e) {
log.debug("编码格式--->{},错误", e.getMessage());
}
return ApiResponse.OK(url);
}
这上边 ApiResponse.OK(url),这里是返回这个url给前端,打开是个微信二维码如图:
用户微信扫码授权后就会根据重定向地址到如下代码:
/**
* 登录回调地址处理
* @param request
* @param response
* @param code
* @param state
* @return
* @throws IOException
*/
@RequestMapping("/login")
public Object weChatLogin(HttpServletRequest request, HttpServletResponse response, String code, String state) throws IOException {
if (StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(state)) {
// 验证state防止跨站请求伪造攻击
String decrypt = AesUtil.decrypt(AesUtil.parseHexStr2Byte(state), AesUtil.PASSWORD_SECRET_KEY, 16);
if (!decrypt.equals(PWD_MD5 + DateUtils.getYYYYMMdd())) {
return ApiResponse.ERROR(SYSTEM_ERROR.getCode(), STATE_ERROR.getMsg(), state);
}
String responseContent = HttpClientUtils.getInstance().sendHttpGet(String.format(ACCESS_TOKEN_URL, appid, secret, code));
if (StringUtils.isEmpty(responseContent)) {
return ApiResponse.ERROR(FAILED.getCode(), FAILED.getMsg(), "获取ACCESS_TOKEN失败");
}
JSONObject parseObject = JSONObject.parseObject(responseContent);
AccessToken accessToken = JSONObject.toJavaObject(parseObject, AccessToken.class);
if (accessToken != null) {
// 根据OPENID查询用户是否存在
// SysUserEntity user = weChatLoginService.getUserByOpenId(accessToken.getOpenid());
// 增加日志
// if (user == null) {
// // 重定向到绑定账号页面
// response.sendRedirect(redirect_bindWeChat + accessToken.getOpenid());
// } else {
// //存在则把当前账号信息授权给扫码用户
//
// // 拿到openid获取微信用户的基本信息
// String res = HttpClientUtils.getInstance().sendHttpGet(String.format(GET_UNIONID_URL, accessToken.getAccess_token(), accessToken.getOpenid()));
// if (StringUtils.isEmpty(res)) {
// return null;
// }
// JSONObject object = JSONObject.parseObject(res);
// }
}
}
return null;
}
这里就不过多说了感觉都能看明白,就说下下图这个:
由于是有账号密码登录这种情况的,微信扫码初次登录库里是肯定没有的所以有两种:
1.需要绑定账号,即把openId关联已有账号如下:
/**
* 微信绑定账号
* @param
* @return
*/
@PostMapping("/bindWeChat")
public ApiResponse bindWeChat() {
//把openId绑定给用户
return ApiResponse.OK(Boolean.TRUE);
}
2.以当前获取的用户信息创建账号
最后一步点击进入我的gitHub可以查看源码,至此结束
step 1
step 2
step 3
等待审核通过
step 4
设置域名或ip+port