网页授权-前后端分离(springboot+vue)

0.官方文档

微信网页授权步骤 --> 传送门

1 第一步:用户同意授权,获取code
2 第二步:通过code换取网页授权access_token
3 第三步:刷新access_token(如果需要)
4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
5 附:检验授权凭证(access_token)是否有效

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

组装鉴权链接--->
在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面(直接把url贴到微信,打开链接即可):

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

若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
首先做一个你内网穿透:
https://ray.ngrok.xiaomiqiu.cn 是我本地做的一个内网穿透(小米球),映射到本地6001服务。

image.png

我的:

https://open.weixin.qq.com/connect/oauth2/authorize?appid="+ appid + "&redirect_uri=https%3a%2f%2fray.ngrok.xiaomiqiu.cn%2fwechat%2fgetCode&response_type=code&scope=snsapi_userinfo&state=xxx#wechat_redirect
注意:回调redirect_uri的值需要encode-->
https://ray.ngrok.xiaomiqiu.cn/wechat/getCode  -->utf8-encode--> https%3a%2f%2fray.ngrok.xiaomiqiu.cn%2fwechat%2fgetCode

用户点击该url--->微信跳转回调我们设置的redirect_uri(https://ray.ngrok.xiaomiqiu.cn/wechat/getCode).
那么我们在

image.png

在里面我们可以获取微信传递给我们的code。

2.通过code换取网页授权access_token

    -->>>>>>>>>>获取code后,请求以下链接请求获取access_token
    public static final String WEB_GET_ACCESS_REQ_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

    public static WxOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {
        WxOauth2Token wat = null;
        // 拼接请求地址
        String requestUrl = WEB_GET_ACCESS_REQ_URL;
        requestUrl = requestUrl.replace("APPID", appId);
        requestUrl = requestUrl.replace("SECRET", appSecret);
        requestUrl = requestUrl.replace("CODE", code);
        // 获取网页授权凭证
//        JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
        JSONObject jsonObject = WxUtil.doGetStr(requestUrl);
        if (null != jsonObject) {
            try {
                wat = new WxOauth2Token();
                wat.setAccessToken(jsonObject.getString("access_token"));
                wat.setExpiresIn(jsonObject.getInteger("expires_in"));
                wat.setRefreshToken(jsonObject.getString("refresh_token"));
                wat.setOpenId(jsonObject.getString("openid"));
                wat.setScope(jsonObject.getString("scope"));
            } catch (Exception e) {
                wat = null;
                int errorCode = jsonObject.getInteger("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                logger.error("获取网页授权凭证失败 errcode:{} errmsg:{}" + errorCode + errorMsg);
            }
        }
        return wat;
    }

    WxOauth2Token weixinOauth2Token = WxWebUtil.getOauth2AccessToken(WxAuth.instance().getAppid(), WxAuth.instance().getAppsec(), code);

现在得到了access_token,可以取到用户信息了!!!!!

3.第三步:刷新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
具体参考官方文档。

4.拉取用户信息(需scope为 snsapi_userinfo)

    /**
     * 通过网页授权获取用户信息
     * 
     * @param accessToken 网页授权接口调用凭证
     * @param openId 用户标识
     * @return WxWebUserInfo
     */
    @SuppressWarnings({ "deprecation", "unchecked" })
    public static WxWebUserInfo getSNSUserInfo(String accessToken, String openId) {
        WxWebUserInfo snsUserInfo = null;
        // 拼接请求地址
        String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
        requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace(
                "OPENID", openId);
        // 通过网页授权获取用户信息
        JSONObject jsonObject = WxUtil.doGetStr(requestUrl);
        if (null != jsonObject) {
            try {
                snsUserInfo = new WxWebUserInfo();
                // 用户的标识
                snsUserInfo.setOpenId(jsonObject.getString("openid"));
                // 昵称
                snsUserInfo.setNickname(jsonObject.getString("nickname"));
                // 性别(1是男性,2是女性,0是未知)
                snsUserInfo.setSex(jsonObject.getInteger("sex"));
                // 用户所在国家
                snsUserInfo.setCountry(jsonObject.getString("country"));
                // 用户所在省份
                snsUserInfo.setProvince(jsonObject.getString("province"));
                // 用户所在城市
                snsUserInfo.setCity(jsonObject.getString("city"));
                // 用户头像
                snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
                // 用户特权信息
//              JSONArray.parseArray()
//              snsUserInfo.setPrivilegeList(JSONArray.toList(jsonObject.getJSONArray("privilege"), List.class));
            } catch (Exception e) {
                snsUserInfo = null;
                int errorCode = jsonObject.getInteger("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                logger.error("获取用户信息失败 errcode:{} errmsg:{}" +  errorCode + errorMsg);
            }
        }
        return snsUserInfo;
    }

    //通过第二步,获取accesstoken和openid
    WxOauth2Token weixinOauth2Token = WxWebUtil.getOauth2AccessToken(WxAuth.instance().getAppid(), WxAuth.instance().getAppsec(), code);
    // 网页授权接口访问凭证
    String accessToken = weixinOauth2Token.getAccessToken();
    // 用户标识
    openId = weixinOauth2Token.getOpenId();
    // 获取用户信息
    WxWebUserInfo snsUserInfo = WxWebUtil.getSNSUserInfo(accessToken, openId);

结尾处,重定向到vue前端首页并带上唯一标志:

    /**
     * 鉴权回调
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/getCode")
    public ModelAndView getCode(HttpServletRequest request) {
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        String openId = GlobalConstant.Symbol.EMPTY;
        // 用户同意授权
        if (!"authdeny".equals(code)) {
            // 获取网页授权access_token
            WxOauth2Token weixinOauth2Token = WxWebUtil.getOauth2AccessToken(WxAuth.instance().getAppid(), WxAuth.instance().getAppsec(), code);
            // 网页授权接口访问凭证
            String accessToken = weixinOauth2Token.getAccessToken();
            // 用户标识
            openId = weixinOauth2Token.getOpenId();
            // 获取用户信息
            WxWebUserInfo snsUserInfo = WxWebUtil.getSNSUserInfo(accessToken, openId);

            if (ObjUtils.isNotEmpty(redisDAO)) {
                redisDAO.set(RedisKeyUtil.getPartnerUserAuthInfoKey(openId), weixinOauth2Token, RedisKeyUtil.EXPIRE_TIME_SEC_MAX);
            }

            log.info("获取用户信息: " + snsUserInfo.toString());

            return null;
        }

        // 重定向到vue前端首页并带上唯一标志, 这里你可以带上加密后的token,然后前后端识别就使用该token进行用户身份验证识别,
        //我在此处简单处理,就直接用openid,然后前端展示首页的时候,截取url里面的内容:openid,然后前端vue就获取到了openid了。
        //shaw.ngrok.xiaomiqiu.cn是我做的一个内网穿透,指向前端vue页面。
        String url_to = "http://shaw.ngrok.xiaomiqiu.cn/vue-project?openid=" + openId;


        return new ModelAndView(new RedirectView(url_to));
    }

该链接一般设置到服务号的菜单栏里面,设置微信菜单栏,后期发布文章。
我们在手机端点击开那个鉴权链接,经过上面的操作之后,就会重定向到后台设置的跳转到vue项目首页。首页通过openid获取服务器数据。

5.前端部分:

我做的是将前端打包放到tomcat下

image.png

webapps\vue-project
--static
--index.html
然后tomcat(端口8080)跑起来,做一个内网穿透
image.png

http://shaw.ngrok.xiaomiqiu.cn --> 127.0.0.1:8080
服务端重定向到这个地址,那么前端vue的页面就展示到微信里面了。
OK!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容