发布:2024/1/10 22:31:18作者:管理员 来源:本站 浏览次数:706
文章目录
背景
效果预览
流程介绍
前端部分
生成微信登录二维码
微信 wxLogin.js
创建方法
后端部分
认证服务器Nginx配置
重定向到Java程序处理
背景
这里微信扫码登录,没有采用轮询、没有采用WebSocket推送,而是由: 扫码后重定向 -> 微信服务器 -> 我方统一认证服务器 -> 指定业务服务器 -> 返回code前端处理结果执行登录。
因为微信PC网站登录,回调合法域名、不管是子域名还是主域名仅能填写一个,所以如果有多个登录环境的情况下,就需要业务方有一台统一的服务来处理分发扫码请求。
如需进行二维码过期、自动刷新二维码等操作,可自行实现,不在本文介绍范围内。
效果预览
image-20210926143053685
流程介绍
登录过程客户端请求情况
image-20210926151833965
从上述网络资源请求记录中可以看到,从扫码确认登陆后,至少经历了两次302(重定向)
一次是由微信产生code后重定向到Js中配置的redirect_uri去并携带code及state字段。
二次是由Nginx服务器判断该请求属于什么业务的,并将Host替换为指定配置服务,重定向过去。
最后由业务服务器接收到请求后处理完毕,重定向到前端新的页面(登录、绑定)并在URL中携带参数供前端做后续业务处理。
前端部分
生成微信登录二维码
这里不使用跳转到微信自身的扫码授权页面,而是嵌入我们自身的登录页面,所以需要自行通过Js获取到微信的二维码数据,展示到我们的页面。
参考文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
微信 wxLogin.js
如果有其他修改需求,可以自行修改后传入自己的云存储,或者直接使用微信文档中的访问链接。
! function (a, b, c) {
function d(a) {
var c = "default";
a.self_redirect === !0 ? c = "true" : a.self_redirect === !1 && (c = "false");
var d = b.createElement("iframe"),
e = "https://open.weixin.qq.com/connect/qrconnect?appid=" + a.appid + "&scope=" + a.scope +
"&redirect_uri=" + a.redirect_uri + "&state=" + a.state + "&login_type=jssdk&self_redirect=" + c +
'&styletype=' + (a.styletype || '') + '&sizetype=' + (a.sizetype || '') + '&bgcolor=' + (a.bgcolor || '') +
'&rst=' + (a.rst || '');
e += a.style ? "&style=" + a.style : "", e += a.href ? "&href=" + a.href : "", d.src = e, d.frameBorder = "0",
d.allowTransparency = "true", d.scrolling = "no", d.width = "160px", d.height = "160px";
var f = b.getElementById(a.id);
f.innerHTML = "", f.appendChild(d)
}
a.WxLogin = d
}(window, document);
创建方法
/** 生成微信登录二维码 */
createWeChat() {
const s = document.createElement("script");
s.type = "text/javascript";
// 微信提供的访问地址 或 自定义地址
s.src = "https://h5.xxxxxx.com/h5/java-script/wxLogin.js";
const wxElement = document.body.appendChild(s);
wxElement.onload = function () {
// 扫描二维码后重定向地址(这里重定向地址中的/test/可根据不同的环境进行不同的配置)
const redirectUri = `http://auth.xxxxxx.com/test/callback/wx/login`
// 微信登录实例JS对象
const object = new WxLogin({
self_redirect: false,
// 页面中对应展示二维码的容器ID
id: "wxMaContainer",
appid: "xxxxxxxxxx",
scope: "snsapi_login",
redirect_uri: encodeURIComponent(redirectUri),
// 若在业务中需要有多个判定参数 可以通过拼接的方式放在 state 中
state: "login,0",
style: "black",
// 二维码样式及其它(关于样式自定义可在网上查阅到相关的实现)
href: "data:text/css;base64,LmltcG93ZXJCb3ggLnFyY29kZSB7d2lkdGg6IDE0MHB4O30NCi5pbXBvd2VyQm94IC50aXRsZSB7ZGlzcGxheTogbm9uZTt9DQouaW1wb3dlckJveCAuaW5mbyB7ZGlzcGxheTogbm9uZTt9DQouc3RhdHVzX2ljb24ge2Rpc3BsYXk6IG5vbmV9DQouaW1wb3dlckJveCAuc3RhdHVzIHt0ZXh0LWFsaWduOiBjZW50ZXI7fQ=="
});
};
},
关于重定向地址:当创建微信二维码时,前端会将上面的参数全部传给微信服务器,用户扫码确认后,会重定向到设置的redirectUri中,并且携带code参数,
后端部分
认证服务器Nginx配置
server {
listen 80;
server_name auth.xxxxxx.com;
# 根据Host后的Path匹配到Test重定向到如下服务中
location /test/ {
rewrite ^/(.*) http://test.xxxxxx.com/$1 redirect;
}
location /prod/ {
rewrite ^/(.*) http://creator.xxxxxx.com/$1 redirect;
}
}
重定向到Java程序处理
仅展示主要逻辑代码,其他不予展示。
/**
* 微信登陆授权回调
*
* @author zhengshangjin
* created on 2021-03-31
*/
@GetMapping(value = "/callback/wx/login")
public void wxLogin(HttpServletRequest request, HttpServletResponse response) {
oauthService.handleWxWebBack(request, response);
}
/**
* 处理微信回调业务情况
*
* @param request 请求
* @param response 响应
* @author zhengshangjin
* created on 2021-04-01
*/
@Override
public void handleWxWebBack(HttpServletRequest request, HttpServletResponse response) {
String code = request.getParameter("code");
String state = request.getParameter("state");
log.info("handleWxWebBack code:{}, state:{}", code, state);
if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) {
throw new BaseException("微信回调参数错误");
}
// 若在业务中需要有多个判定参数 可以通过拼接的方式放在 state 中
String[] stateArr = state.split(",");
if (stateArr.length < 2) {
throw new BaseException("微信回调参数错误");
}
String type = stateArr[0];
String userId = stateArr[1];
log.info("handleWxWebBack type:{}, userId:{}", type, userId);
// 绑定
if (WX_BIND.equals(type)) {
// 绑定状态
int status = handleWxBind(code, userId);
log.info("status:{}", status);
try {
// 重定向到前端绑定页面处理结果
response.sendRedirect(wxBindNotify + "?status=" + status);
} catch (IOException e) {
log.error("ex msg:{}", e.getMessage());
}
}
// 登录
if (WX_LOGIN.equals(type)) {
try {
// 重定向到前端登录页面处理结果
response.sendRedirect(wxLoginNotify + "?code=" + code);
} catch (IOException e) {
log.error("ex msg:{}", e.getMessage());
}
}
}
至此,就完成了登录或者绑定微信的逻辑处理
© Copyright 2014 - 2024 柏港建站平台 ejk5.com. 渝ICP备16000791号-4