转自:http://www.cuiyongzhi.com/post/78.html

好长时间没有写文章了,主要是最近的工作和生活上的事情比较多而且繁琐,其实到现在我依然还是感觉有些迷茫,最后还是决定静下心来坚持一开始的选择,继续我们的微信系列文章的后续更新,也希望在自己有时间的时候能把更多的内容呈现给大家,前面一系列的文章讲述了很多微信开发相关的基础知识点 【微信系列文章】,那么从这一篇开始将讲述微信较深一层次或者说在产品应用中时刻会用到的一些技术点,那么下面就让我们进入正题吧,这一篇我要讲述的是在微信服务号开发中常用到的微信网页授权(OAuth2.0授权)获取用户基本信息!

我们来说下OAuth2.0授权的一些应用场景,例如:示例①希望用户在点击打开一个网页的时候可以获取该用户的微信昵称,微信头像等;示例②:当某个用户在我们会员系统中,希望用户在直接打开网页的时候展示用户在我们的会员系统中的积分情况和消费信息等...,那么这一系列的应用场景中我们是如何在一个网页中获取微信用户的相关信息的呢?这里我们就要用到微信网页授权的功能来解决我们遇到的难题了!

(一)首先在我们开始应用OAuth2.0授权之前我们先来了解一下它,看他本身的实现流程和机制!

①关于网页授权回调域名的说明

  • 在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的开发者中心页配置授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头;

  • 授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0鉴权

  • 如果公众号登录授权给了第三方开发者来进行管理,则不必做任何设置,由第三方代替公众号实现网页授权即可

②关于网页授权的两种scope的区别说明

  • 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)

  • 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

  • 用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。

③关于网页授权access_token和普通access_token的区别(参见:微信开发中的token获取)

  • 微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;

  • 其他微信接口,需要通过基础支持中的“获取access_token”接口来获取到的普通access_token调用。

④关于UnionID机制(参见:开发中微信公众平台/开放平台/商户平台的关联)

  • 请注意,网页授权获取用户基本信息也遵循UnionID机制。即如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。

  • UnionID机制的作用说明:如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。

⑤关于特殊场景下的静默授权

  • 上面已经提到,对于以snsapi_base为scope的网页授权,就静默授权的,用户无感知;

  • 对于已关注公众号的用户,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是scope为snsapi_userinfo,也是静默授权,用户无感知。

(二)OAuth2.0授权获取用户微信信息的具体实现

在整个的授权获取用户信息的流程中可以分为以下几步:

  • 开发前的授权域名配置

  • 引导用户进入授权页面同意授权,获取code

  • 通过code换取网页授权access_token(与基础支持中的access_token不同)并通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

①开发前的授权域名配置

在进行代码实现之前我们需要配置安全授权域名,具体安全域名的配置目录:【微信公众平台】——>【接口权限】——>【网页授权获取用户基本信息】,简单如下图:

②引导用户进入授权页面同意授权,获取code

这一步在整个的网页授权过程中是非常重要的一步,因为只有引导用户授权获取到code才能开始后面信息的获取,在这里需要注意的是我们在配置授权链接中的redirect_uri必须是我们在第一步中配置的安全域名,参考连接如下:

1
2
3
4
Scope为snsapi_base
  
Scope为snsapi_userinfo
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=redirect_uri&response_type=code&scope=snsapi_userinfo&state=2#wechat_redirect

参数 是否必须 说明
appid 公众号的唯一标识
redirect_uri 授权后重定向的回调链接地址,请使用urlencode对链接进行处理
response_type 返回类型,请填写code
scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息
state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect 无论直接打开还是做页面302重定向时候,必须带此参数 

注:code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期!

因为oauth2.0授权机制是在腾讯机器会将最终的url带上code中转到我们所配置的redirect_uri上,所以在我们的服务端我们需要在Controller加入一个weiXinOauth方法用于接收腾讯服务器中转过来的参数code和state,简单实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
     * @Description: 微信授权登录
     * @param @param request
     * @param @param response
     * @param @param code
     * @param @param state
     * @author dapengniao
     * @date 2016年4月26日 上午9:40:18
     */
    @RequestMapping("weixinOauth")
    public void weiXinOauth(HttpServletRequest request,
            HttpServletResponse response,
            @RequestParam(value = "code", required = true) String code,
            @RequestParam(value = "state", required = true) String state) {
        System.out.println("Code============="+code+"==========state======="+state);
         
    }

此时到这里我们对code的获取就完成了,下面继续下一步操作;

③通过code换取网页授权access_token(与基础支持中的access_token不同)并通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

在前面我们通过方法获取到了在授权中需要用到的code,那么我们接下来要做的就是通过code获取token+openid,这里如果我们采用的是snsapi_userinfo的方式授权的话,那么后面我们可以通过token+openid获取用户信息了,在这里我写了一个实用的方法OauthCode_GetUseInfo来实现这些步骤,简单代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package com.cuiyongzhi.wechat.common;
import java.util.HashMap;
import com.cuiyongzhi.web.util.GlobalConstants;
import com.cuiyongzhi.wechat.util.HttpUtils;
import net.sf.json.JSONObject;
/**
 * ClassName: OauthCode_GetUseInfo
 * @Description: 用户oauth2.0授权登录 通过code获取用户真实信息
 * @author dapengniao
 * @date 2016年4月26日 上午9:54:55
 */
public class OauthCode_GetUseInfo {
    
    private String openid;
    private String access_token;
    private String code;
    private String unionid;
    private HashMap<String, String> params = new HashMap<String, String>();
    public OauthCode_GetUseInfo(String code) {
        this.code = code;
        params.put("appid", GlobalConstants.getInterfaceUrl("appid"));
        params.put("secret", GlobalConstants.getInterfaceUrl("AppSecret"));
    }
    /**
     *
     * @param @return hashmap {subscribe是否关注 0没有关注,1关注 unionid openid nickname昵称
     *        sex性别 province省份 city城市 headimgurl图像地址}
     * @param @throws Exception
     * @author dapengniao
     * @date  2016年4月26日 上午9:54:55
     */
    public HashMap<String, String> getUserInfo() throws Exception {
        // 将用户信息获取拼装成map
        // 通过code获取access_token,openid,unionid
        params.put("code", code);
        params.put("grant_type""authorization_code");
        String tokenrs = HttpUtils.sendGet(
                GlobalConstants.getInterfaceUrl("OauthCodeUrl"), params);
        System.out.println("tokenrs======================"+tokenrs);
        access_token = JSONObject.fromObject(tokenrs).getString("access_token");
        openid = JSONObject.fromObject(tokenrs).getString("openid");
        unionid = JSONObject.fromObject(tokenrs).getString("unionid");
        // 通过用户openid信息获取用户详细信息
        params.clear();
        params.put("access_token", access_token);
        params.put("openid", openid);
        params.put("lang""zh_CN");
        String useinfors = HttpUtils.sendGet(
                GlobalConstants.getInterfaceUrl("OauthInfoUrl"), params);
        // 通过用户的openid判断用户是否关注公众账号
        params.clear();
        params.put("access_token", GlobalConstants.getInterfaceUrl("access_token")
                );
        params.put("openid", openid);
        params.put("lang""zh_CN");
        String subscribers = "";
        subscribers = HttpUtils.sendGet(
                GlobalConstants.getInterfaceUrl("SubscribeUrl"), params);
        // 将用户信息获取拼装成map
         
        System.out.println(subscribers);
            params.clear();
        params.put("subscribe",
                    JSONObject.fromObject(subscribers).getString("subscribe"));
        params.put("unionid", unionid);
        params.put("openid", openid);
        params.put("nickname",
                JSONObject.fromObject(useinfors).getString("nickname"));
        params.put("sex", JSONObject.fromObject(useinfors).getString("sex"));
        params.put("province",
                JSONObject.fromObject(useinfors).getString("province"));
        params.put("city", JSONObject.fromObject(useinfors).getString("city"));
        params.put("headimgurl",
                JSONObject.fromObject(useinfors).getString("headimgurl"));
         
         
        return params;
    }
    /**
     * @Description: 通过openid获取用户信息
     * @param @param openid
     * @param @return
     * @param @throws Exception   
     * @author dapengniao
     * @date 2016年4月26日 上午9:53:40
     */
     
    public static HashMap<String, String> Openid_userinfo(String openid)
            throws Exception {
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("access_token",
                GlobalConstants.getInterfaceUrl("access_token"));
        params.put("openid", openid);
        params.put("lang""zh_CN");
        String subscribers = HttpUtils.sendGet(
                GlobalConstants.getInterfaceUrl("SubscribeUrl"), params);
        params.clear();
        params.put("nickname",
                JSONObject.fromObject(subscribers).getString("nickname"));
        params.put("headimgurl",
                JSONObject.fromObject(subscribers).getString("headimgurl"));
        params.put("sex", JSONObject.fromObject(subscribers).getString("sex"));
        return params;
    }
    @SuppressWarnings("unused")
    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}

通过方法我们只需要传入code,就可以将个人的用户信息以Map的形式返回,用于我们在前端的使用,在这里我们将Controller的代码做简单的修改,用于对OauthCode_GetUseInfo中方法对用户信息的获取,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * @Description: 微信授权登录
 * @param @param request
 * @param @param response
 * @param @param code
 * @param @param state
 * @author dapengniao
 * @date 2016年4月26日 上午9:40:18
 */
@RequestMapping("weixinOauth")
public void weiXinOauth(HttpServletRequest request,
        HttpServletResponse response,
        @RequestParam(value = "code", required = true) String code,
        @RequestParam(value = "state", required = true) String state) {
    System.out.println("Code============="+code+"==========state=======" + state);
    try {
        // 用code取得微信用户的基本信息
        OauthCode_GetUseInfo weixin = new OauthCode_GetUseInfo(code);
        Map<String, String> wmap = weixin.getUserInfo();
        System.out.println("用户昵称================================="
                + wmap.get("nickname"));
    catch (Exception e) {
        logger.error(e.toString(), e);
    }
}

转载于:https://www.cnblogs.com/sharpest/p/10255716.html

Java微信公众平台开发(十六)--微信网页授权(OAuth2.0授权)获取用户基本信息相关推荐

  1. 获取微信用户信息java开发_Java微信公众平台开发(十二)--微信用户信息的获取

    前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信用户的信息,在上一篇我们有说道微信用户和微信公众账号之间的联系可以通过Openid关 ...

  2. Java微信公众平台开发(十二)--微信JSSDK的使用

    在前面的文章中有介绍到我们在微信web开发过程中常常用到的 [微信JSSDK中Config配置] ,但是我们在真正的使用中我们不仅仅只是为了配置Config而已,而是要在我们的项目中真正去使用微信JS ...

  3. 微信公众平台开发(六) 翻译功能开发

    转载自:http://www.php100.com/html/php/api/2013/0909/6130.html 微信公众平台开发(六) 翻译功能开发 来源:David Camp   时间:201 ...

  4. 微信公众平台开发(93) 关闭微信浏览器

    原文地址为: 微信公众平台开发(93) 关闭微信浏览器 在这篇微信公众平台开发教程中,我们将介绍如何使用微信JS接口关闭微信内置浏览器返回到微信聊天窗口界面. 微信的JS接口目前已公布了三种:右上角按 ...

  5. java获取微信用户源码_Java微信公众平台开发(十)--微信用户信息的获取

    前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信用户的信息,在上一篇我们有说道微信用户和微信公众账号之间的联系可以通过Openid关 ...

  6. Java微信公众平台开发(一)--接入微信公众平台

    转载自崔用志博客:http://www.cuiyongzhi.com/ 前面几篇文章一直都在说微信公众平台的开发准备工作,那么从这篇开始我们就将正式的进入JAVA微信公众平台开发的整个流程,那么这篇我 ...

  7. Java微信公众平台开发(一)——接入微信公众平台

    前面几篇文章一直都在说微信公众平台的开发准备工作,那么从这篇开始我们就将正式的进入JAVA微信公众平台开发的整个流程,那么这篇我们开始聊聊如何将我们的服务端和微信公众平台对接! (一)接入流程解析 在 ...

  8. php微信公众平台开发类,php微信公众平台开发类实例

    本文实例讲述了php微信公众平台开发类.分享给大家供大家参考.具体分析如下: ThinkWechat.php类文件如下: class Wechat { /** * 微信推送过来的数据或响应数据 * @ ...

  9. Java微信公众平台开发(十)--微信自定义菜单的创建实现

    转自:http://www.cuiyongzhi.com/post/48.html 自定义菜单这个功能在我们普通的编辑模式下是可以直接在后台编辑的,但是一旦我们进入开发模式之后我们的自定义菜单就需要自 ...

最新文章

  1. 深度RNN解决语义搜索难题
  2. Docker Review - docker 容器 常用命令
  3. Scala中的trait特质
  4. 代码生成工具之Winform查询列表界面生成
  5. 服务器tail正常,cat正常,vim打开中文乱码
  6. C#LeetCode刷题之#345-反转字符串中的元音字母​​​​​​​(Reverse Vowels of a String)
  7. Basis Cash动态铸币税阈值和债券发行上限提案正式生效
  8. 想要改变自己,请先突破这3个自我限制
  9. python 在线培训费用-在线Python编程培训哪家机构比较好?
  10. QQlook--QQ空间密码 相册密码查看工具 国庆版 V2.4
  11. Hilbert 变换
  12. MindManager2022注册码-激活码-序列号相关问题解答
  13. ADXRS620/642/646发布:在PX4上我们为什么扔掉了MPU6000这个IMU
  14. 云流化/云渲染技术一种比像素流功能更完善的解决方案
  15. 遇到mysqladmin flush-hosts报错解决思路
  16. ajax传递数组怎么办?
  17. airsim--client
  18. oracle sql 字段值行 连乘,如何使用Oracle数据库将矩阵与其转置相乘,并使用utl_nla...
  19. 计算机网络:数据链路层:有线和无线网络(4)
  20. 如何能百度到自己的博客

热门文章

  1. 易语言连接mysql学习_[易语言]连接MYSQL数据库学习
  2. python 绘制函数曲线图
  3. python脚本获取华为边缘设备NPU信息
  4. Python绘制论文曲线图
  5. HENUOJ-1007-CYT大佬的女装(贪心算法)
  6. HBase 在滴滴出行的应用场景和最佳实践
  7. 瀬名 - 想ひ出小往
  8. 读书 | 《富爸爸穷爸爸》
  9. 给DataTable中添加一行数据
  10. 无人驾驶汽车系统入门(十九)——分层有限状态机和无人车行为规划