在日常开发过程中我们难免会遇到需要网页授权登录获取用户openId的情况,随着开发的深入我们会有很多网页需要用到用户的openId,而我们不可能每次都去写一个授权登录的接口去匹配每个网页,为了减少我们重复的工作,本篇文章将分享一个所有网页公共授权方案包括未配置的安全域名下的网页。如有不足之处,可在评论区指出。
本次使用开发语言为java。使用框架springboot。
前期配置我们都知道要想实现微信公众号的网页授权登录,需在公众号管理后台“设置与开发”->“公众号设置”->"功能设置"中设置网页授权域名,如下图所示
网页授权域配置
但是微信官方将此域名配置限制为仅可设置两个,那我们需要跳转其他域名怎么办呢,其实很简单,我们接着往下看!
授权流程大家都知道微信网页授权只需要在确保微信公众账号拥有授权作用域(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
需要注意的是这里的授权登录很有可能多次转发,导致code过期的情况,因此可以加入参数connect_redirect=1告诉微信仅跳转一次
REDIRECT_URI就为我们的用户确认授权后 微信转发的地址 我们要实现公共网页的授权登录就在这里做文章
关于scope作用域这里就不再过多地描述snsapi_base仅可以拿到户的 openid,并且用户是无感知的,是静默的。snsapi_userinfo可以拿到用户的基本信息,但不是无感知的需要用户手动确认,特殊情况除外(对于已关注公众号的用户,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是 scope 为snsapi_userinfo,也是静默授权,用户无感知)。
实现代码/**
* 公共重定向
* @param url
* @param Request
* @return
*/
@RequestMapping("/common")
public String authCommonUrl(String url, HttpServletRequest request)
try {
if (StringUtils.isEmpty(url)) {
return "/error";
}
return "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?appid=" environment.getProperty("wechat.appId")
"&redirect_uri="
URLEncoder.encode(
environment.getProperty("wechat.baseRedirectUrl") "/authcommonurl?url=" URLEncoder.encode(url, "utf-8"),
"utf-8")
"&response_type=code&scope=snsapi_userinfo&connect_redirect=1&state=join#wechat_redirect";
} catch (Exception e) {
logger.error("重定向发生异常->RedirectController.authCommon:" ParamsUtils.showParams(request), e);
return "/error";
}
}
可以看到我们将redirect_uri设置成了一个公共的获取用户信息的接口地址,然后在该地址上传入我们需要最终跳转的url,这里的url我们如果需要传递其他参数,也可以直接加在url上。这里我们只要保证redirect_uri在网页授权的安全域名下,而url任意域名都可以啦。
获取用户信息重定向url地址
/**
* 授权回调转发
* @param url
* @param code
* @param request
* @return
*/
@SuppressWarnings({ "unchecked" })
@RequestMapping(value = "/authcommonurl")
public String authCommon(String url, String code, HttpServletRequest request) {
HttpSession session = request.getSession();
try {
if (StringUtils.isEmpty(url)) {
return "/error";
}
if (StringUtils.isEmpty(code)) {
return "/error";
}
// 首先判断session中是否存在用户信息,存在则跳过以下获取用户信息方法,不存在继续执行
String sessionId = session.getId();
CacheObject<JSONObject> cache = MapCacheManager.getInstance().getCache(sessionId);
JSONObject userInfoJO = cache != null ? cache.getObject() : null;
if (userInfoJO == null || StringUtils.isEmpty(userInfoJO.optString("nickname", ""))) {// 里面为整个网页登录授权过程
// 调用获取accessToken接口 获取accessToken
String json = HttpsUtil.httpMethodGet(getAccessTokenUrl(code), "UTF-8");
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(json);
} catch (Exception e) {
logger.error("获取授权accesstoken转换json异常->NotStaticAuthReturnController.authHd:" json, e);
}
if (!jsonObject.has("access_token")) {
return "/error";
}
String access_token = jsonObject.optString("access_token", "");
String openid = jsonObject.optString("openid", "");
// 得到获取用户信息的链接
// 获取用户信息接口 获取用户信息
String userInfoJson = HttpsUtil.httpMethodGet(getUserinfoUrl(access_token, openid), "UTF-8");
try {
userInfoJO = new JSONObject(userInfoJson);
} catch (JSONException e) {
userInfoJO = new JSONObject();
logger.error("获取用户信息转换json异常->NotStaticAuthReturnController.authcommon:" userInfoJson, e);
}
if (!userInfoJO.has("nickname")) {
return "/error";
}
userInfoJO.put("nickname", EmojiFilter.filterEmoji(userInfoJO.optString("nickname", "")));
cache = new CacheObject<>();
cache.setExpires_in(7200L);
cache.setObject(userInfoJO);
MapCacheManager.getInstance().putCache(sessionId, cache);
}
// System.out.println("用户信息:" userInfoJO.toString());//输出用户信息 测试用
String user_openid = userInfoJO.optString("openid", "");
if (StringUtils.isEmpty(user_openid)) {
return "/error";
}
return "redirect:" url (url.contains("?") ? "&" : "?") "openId=" user_openid;
} catch (Exception e) {
e.printStackTrace();
logger.error("微信授权异常->NotStaticAuthReturnController.authCommonurl:" ParamsUtils.showParams(request), e);
return "/error";
}
}
这里我们作用域是snsapi_userinfo有获取用户的基本信息,若无需这些信息,按需求删除代码即可。
如有问题或不足之处可在评论区指出,觉得还行的看官动动小手帮忙点个赞吧!
祝大家健健康康,每天开开心心!