我们经常会访问一些网站,用微信登录的时候需要用到授权,那么微信网页授权是怎么一回事呢,一起来看看吧!
 
 
官方的文档有很详细的说明,这里就主要分析重要的几点:
第一,网页授权分类及说明:
1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
 
第二,网页授权流程分为四步:
1、引导用户进入授权页面同意授权,获取code 
2、通过code换取网页授权access_token(与基础支持中的access_token不同) 
3、如果需要,开发者可以刷新网页授权access_token,避免过期 
4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制) 
 
了解到网页授权的这些知识,下面就开始去实现吧~
 
开始的准备工作:在接口配置中,设置对应的回调域名,地址:“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项
由于我的是个人,因此使用测试账号的配置:

配置好了,就可以进行开发了,首先来看一下具体的流程:

其实很多功能点,前面已经实现过,只用改一下调用地址和参数即可。

首先,调用的定义链接:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

链接中需要使用urlEncode对链接进行处理,可以在工具类中添加一个转码方法:

     /**
* 对URL地址进行EnCode处理
* @param url
* @return
*/
public static String urlEnCode(String url)
{
String enCodedUrl = ""; try
{
enCodedUrl = URLEncoder.encode(url, "utf-8");
}
catch (UnsupportedEncodingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("转码失败!");
} return enCodedUrl;
}

另外将其他参数补充完整,可以得到一个访问链接。

在这里,可以结合之前学的菜单的处理,可以定义一个菜单进行专门的授权验证,这里需要改造上一节学到的点,具体如下:

     /**
* 定义菜单属性
* @return
*/
private Menu getMenu()
{
Menu menu = new Menu(); // 建3个导航菜单
LevelMenu tLevelMenuOne = new LevelMenu();
tLevelMenuOne.setName("Damon");
LevelMenu tLevelMenuTwo = new LevelMenu();
tLevelMenuTwo.setName("Panou");
LevelMenu tLevelMenuThree = new LevelMenu();
tLevelMenuThree.setName("Papaw"); // 第一个导航菜单的子菜单
SubMenuButton tSubMenuButton_oneone = new SubMenuButton();
tSubMenuButton_oneone.setType(SysCon.WECHAT_MENU_TYPE_VIEW);
tSubMenuButton_oneone.setName("网页授权");
tSubMenuButton_oneone.setKey("11");
tSubMenuButton_oneone.setUrl(getAuthorUrl()); SubMenuButton tSubMenuButton_onetwo = new SubMenuButton();
tSubMenuButton_onetwo.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
tSubMenuButton_onetwo.setName("swimming");
tSubMenuButton_onetwo.setKey("12"); // 加入导航菜单
tLevelMenuOne.setSub_button(new SubMenuButton[]
{ tSubMenuButton_oneone, tSubMenuButton_onetwo }); // 第二 个导航菜单的子菜单
SubMenuButton tSubMenuButton_twoone = new SubMenuButton();
tSubMenuButton_twoone.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
tSubMenuButton_twoone.setName("watching TV");
tSubMenuButton_twoone.setKey("21"); SubMenuButton tSubMenuButton_twotwo = new SubMenuButton();
tSubMenuButton_twotwo.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
tSubMenuButton_twotwo.setName("play games");
tSubMenuButton_twotwo.setKey("22"); SubMenuButton tSubMenuButton_twothree = new SubMenuButton();
tSubMenuButton_twothree.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
tSubMenuButton_twothree.setName("shopping");
tSubMenuButton_twothree.setKey("23"); // 加入导航菜单
tLevelMenuTwo.setSub_button(new SubMenuButton[]
{ tSubMenuButton_twoone, tSubMenuButton_twotwo, tSubMenuButton_twothree }); // 第三个导航菜单的子菜单
SubMenuButton tSubMenuButton_threeone = new SubMenuButton();
tSubMenuButton_threeone.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
tSubMenuButton_threeone.setName("cring");
tSubMenuButton_threeone.setKey("31"); SubMenuButton tSubMenuButton_threetwo = new SubMenuButton();
tSubMenuButton_threetwo.setType(SysCon.WECHAT_MENU_TYPE_CLICK);
tSubMenuButton_threetwo.setName("laughing");
tSubMenuButton_threetwo.setKey("32"); // 加入导航菜单
tLevelMenuThree.setSub_button(new SubMenuButton[]
{ tSubMenuButton_threeone, tSubMenuButton_threetwo }); menu.setButton(new MenuButton[]
{ tLevelMenuOne, tLevelMenuTwo, tLevelMenuThree }); return menu; } /**
* 获取微信网页授权页面链接
* @return
*/
private String getAuthorUrl()
{
String uri = "http://damonhouse.iok.la/Servlet/WeChatAuthorService"; uri = WeChatUtil.urlEnCode(uri); String authorUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect"; authorUrl = authorUrl.replace("APPID", "appid").replace("REDIRECT_URI", uri).replace("SCOPE", "snsapi_userinfo"); return authorUrl;
}

先看一下具体效果:

点击会弹出一个授权的页面(由于我已经授权过,所以这里会自动登录)

这个时候后台还没有对应的处理,我们需要进行返回页面的处理,这里定义对应的service类,在doGet方法中进行处理:

 /**
* 微信授权接口类
* @author Damon
*/
public class WeChatAuthorService extends HttpServlet
{ @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
// TODO Auto-generated method stub
System.out.println("授权成功,进行返回处理!");
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8"); String code = req.getParameter("code"); String state = req.getParameter("state"); System.out.println("code :" + code + " and stat :" + state); // 业务处理,获取授权用户信息
WeChatAuthorBL tWeChatAuthorBL = new WeChatAuthorBL();
AuthorUserInfo tAuthorUserInfo = tWeChatAuthorBL.getAuthorData(code, state); req.setAttribute("nickname", tAuthorUserInfo.getNickname());
// 获取信息成功,回写成功页面
req.getRequestDispatcher("../wechat/authorsucc.jsp").forward(req, resp); } @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
// TODO Auto-generated method stub
super.doPost(req, resp);
} }

可以从授权中获取到 code 和state(可自定义用与此处校验), 然后就是通过code来进行获取授权的用户信息:

从前面分析可知,需要先获取授权的acces_token,然后才能获取到授权的用户信息,那么结合前面2节内容,先定义2个实体类:

1、用户授权Token类

 /**
* 用户授权Token
* @author Damon
*/
public class AuthorToken
{
// 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
private String access_token = ""; // access_token接口调用凭证超时时间,单位(秒)
private int expires_in = 0; // 用户刷新access_token ="";
private String refresh_token = ""; // 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
private String openid = ""; // 用户授权的作用域,使用逗号(,)分隔
private String scope = ""; public String getAccess_token()
{
return access_token;
} public void setAccess_token(String access_token)
{
this.access_token = access_token;
} public int getExpires_in()
{
return expires_in;
} public void setExpires_in(int expires_in)
{
this.expires_in = expires_in;
} public String getRefresh_token()
{
return refresh_token;
} public void setRefresh_token(String refresh_token)
{
this.refresh_token = refresh_token;
} public String getOpenid()
{
return openid;
} public void setOpenid(String openid)
{
this.openid = openid;
} public String getScope()
{
return scope;
} public void setScope(String scope)
{
this.scope = scope;
} }

2、授权用户信息类

 /**
* 通过网页授权获取的用户信息
* @author Damon
*/
public class AuthorUserInfo
{
// 用户的唯一标识
private String openid = ""; // 用户昵称
private String nickname = ""; // 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
private String sex = ""; // 用户个人资料填写的省份
private String province = ""; // 普通用户个人资料填写的城市
private String city = ""; // 国家,如中国为CN
private String country = ""; // 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
private String headimgurl = ""; // 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
private List<String> privilege = new ArrayList<String>(); // 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
private String unionid = ""; public String getOpenid()
{
return openid;
} public void setOpenid(String openid)
{
this.openid = openid;
} public String getNickname()
{
return nickname;
} public void setNickname(String nickname)
{
this.nickname = nickname;
} public String getSex()
{
return sex;
} public void setSex(String sex)
{
this.sex = sex;
} public String getProvince()
{
return province;
} public void setProvince(String province)
{
this.province = province;
} public String getCity()
{
return city;
} public void setCity(String city)
{
this.city = city;
} public String getCountry()
{
return country;
} public void setCountry(String country)
{
this.country = country;
} public String getHeadimgurl()
{
return headimgurl;
} public void setHeadimgurl(String headimgurl)
{
this.headimgurl = headimgurl;
} public List<String> getPrivilege()
{
return privilege;
} public void setPrivilege(List<String> privilege)
{
this.privilege = privilege;
} public String getUnionid()
{
return unionid;
} public void setUnionid(String unionid)
{
this.unionid = unionid;
} }

下一步,就是通过调用接口来实现我们的功能了~

     /**
* 获取授权用户
* @param code
* @param state
* @return
*/
public AuthorUserInfo getAuthorData(String code, String state)
{ // 1、通过code获取授权的authortoken
AuthorToken tAuthorToken = getAuthorToken("appid", "appsecret", code); // 2、通过获取的 access_token和 openid 获取用户信息
AuthorUserInfo tAuthorUserInfo = getAuthorUserInfo(tAuthorToken.getAccess_token(), tAuthorToken.getOpenid()); return tAuthorUserInfo;
} /**
* 获取授权的access_token
* @param appid
* @param appsceret
* @param code
* @return
*/
private AuthorToken getAuthorToken(String appid, String appsceret, String code)
{ String path = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code "; path = path.replace("APPID", appid).replace("SECRET", appsceret).replace("CODE", code); AuthorToken tAuthorToken = new AuthorToken(); try
{
String strResp = WeChatUtil.doHttpsGet(path, ""); System.out.println(strResp); // 解析获取的token信息
Map<String, Object> tMap = WeChatUtil.jsonToMap(strResp); System.out.println(tMap.toString()); // 封装 authortoken tAuthorToken.setAccess_token((String) tMap.get("access_token"));
tAuthorToken.setExpires_in(Integer.parseInt((String) tMap.get("expires_in")));
tAuthorToken.setOpenid((String) tMap.get("openid"));
tAuthorToken.setScope((String) tMap.get("scope"));
tAuthorToken.setRefresh_token((String) tMap.get("refresh_token")); }
catch (HttpException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} return tAuthorToken;
} /**
* 通过授权的access_token及用户的openid来拉取用户信息
* @param access_token
* @param openid
* @return
*/
private AuthorUserInfo getAuthorUserInfo(String access_token, String openid)
{
String path = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; path = path.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid); AuthorUserInfo tAuthorUserInfo = new AuthorUserInfo(); try
{
String strResp = WeChatUtil.doHttpsGet(path, ""); System.out.println(strResp); // 解析获取的token信息
Map<String, Object> tMap = WeChatUtil.jsonToMap(strResp); System.out.println(tMap.toString()); // 封装 authortoken
tAuthorUserInfo.setOpenid((String) tMap.get("openid"));
tAuthorUserInfo.setNickname((String) tMap.get("nickname"));
tAuthorUserInfo.setSex((String) tMap.get("sex"));
tAuthorUserInfo.setCountry((String) tMap.get("country"));
tAuthorUserInfo.setProvince((String) tMap.get("province"));
tAuthorUserInfo.setCity((String) tMap.get("city"));
tAuthorUserInfo.setHeadimgurl((String) tMap.get("headimgurl"));
tAuthorUserInfo.setPrivilege((List<String>) tMap.get("privilege"));
tAuthorUserInfo.setUnionid((String) tMap.get("unionid"));
}
catch (HttpException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} return tAuthorUserInfo;
}

这些搞定,我们就已经获取到了用户的信息了。 最后我们来给用户一个好的界面体验~

这里新增一个页面,显示获取到的用户昵称:

 <%@ page language="java" contentType="text/html; charset=GBK"
pageEncoding="GBK"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>damon's house</title>
</head>
<body>
<%
String nickname=request.getAttribute("nickname").toString();
%>
<table><tr><%=nickname %> 您好,感谢授权Damon的奇趣小屋!</tr></table>
</body>
</html>

来看一下效果吧~

微信网页授权,获取用户信息就到这啦~

 

玩玩微信公众号Java版之六:微信网页授权的更多相关文章

  1. 玩玩微信公众号Java版之七:自定义微信分享

    前面已经学会了微信网页授权,现在微信网页的功能也可以开展起来啦! 首先,我们先来学习一下分享,如何在自己的页面获取分享接口及让小伙伴来分享呢? 今天的主人公: 微信 JS-SDK, 对应官方链接为:微 ...

  2. 玩玩微信公众号Java版之一:配置微信公众平台服务器信息

    在进行微信公众平台开发前,前先做好准备工作,好了以后,我们可以开始啦!   第一.准备好服务端接口   定义一个http服务接口,主要分为如下几步:   1.创建一个servlet类,用来接收请求: ...

  3. 玩玩微信公众号Java版之准备

    微信自2013年流行起来,现在的发展已经超过了我们的想象,那么对应的公众平台,小程序等都是让人眼前一亮的东西,这里来学习一下微信工作号的对接,实现为Java,希望大家一起学习!   这里大概描述一下所 ...

  4. 玩玩微信公众号Java版之四:自定义公众号菜单

    序: 微信公众号基本的菜单很难满足个性化及多功能的实现,那么微信能否实现自定菜单呢,具体的功能又如何去实现么?下面就来学习一下微信自定义公众号菜单吧! 自定义菜单接口可实现多种类型按钮,如下: 1.c ...

  5. C#微信公众号开发-高级接口-之网页授权oauth2.0获取用户基本信息(二)

    C#微信公众号开发之网页授权oauth2.0获取用户基本信息(一) 中讲解了如果通过微信授权2.0snsapi_base获取已经关注用户的基本信息,然而很多情况下我们经常需要获取非关注用户的信息,方法 ...

  6. 玩玩微信公众号Java版之三:access_token及存储access_token

    微信官方参考文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183   基本说明: access_token是 ...

  7. 玩玩微信公众号Java版之五:获取关注用户信息

    在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的.对于不同公众号,同一用户的openid不同).公众号可通过本接口来根据Op ...

  8. 玩玩微信公众号Java版之二:接收、处理及返回微信消息

    前面已经配置了微信服务器,那么先开始最简单的接收微信消息吧~   可以用我们的微信号来直接进行测试,下面先看测试效果图:   这是最基本的文本消息的接收.处理及返回,来看看是怎么实现的吧!   首先可 ...

  9. 第八篇 :微信公众平台开发实战Java版之如何网页授权获取用户基本信息

    第一部分:微信授权获取基本信息的介绍 我们首先来看看官方的文档怎么说: 如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑. 关于网页授权回调域 ...

随机推荐

  1. java基础(十四章)

    1.Java中的包(package) 2.1 包,对应到磁盘中的文件夹 2.2 新建一个class,默认保存在缺省包中 2.3 声明包的关键字:package package语句,置顶位置 2.4 导 ...

  2. 演讲小技巧iPhone+Keynote

    原文发布在简书上:http://www.jianshu.com/p/a45538ca611f 今天在公司里分享了一个技术雷达里关于 ECMAScript 2017 的小 Session,分享加问答总共 ...

  3. js实现整数转化为小数

    toFixed 方法 返回一个字符串,代表一个以定点表示法表示的数字. number .toFixed(i) 参数 bumber 必选项.一个 Number 对象. i 可选项.小数点 后的数字位数. ...

  4. 用户权限模块之oauth2.0

    主要是在springsecurity上面扩展即可,所以内容也是基于上一个, sql: CREATE TABLE `auth_access_token` ( `id` int(11) NOT NULL ...

  5. 【Windows 10 应用开发】使用快捷访问键

    UWP 虽然主要面向触控操作,但 Windows 设备是万能工具,不用手指不用笔的时候,也可能会接上键盘耍耍.因此,给应用界面上的一些元素弄个快捷访问键也挺不错的.为了使用 Windows 上的各类应 ...

  6. 数据结构与算法1-2 C语言运行时间检测算法

    #include <stdio.h> #include <math.h> #include <time.h> clock_t start,stop; #define ...

  7. TestNG+ExtentReports生成超漂亮的测试报告

    一个优雅.漂亮的测试报告,能够给我们的测试工作带来不少的加分,而报告的模版实在是让我们这些技术人员头疼的问题,设计的实在是没有什么美感. 那么今天就给大家分享一个自动化测试中,一个超漂亮的测试报告模版 ...

  8. Java 中Calendar、Date、SimpleDateFormat学习总结

    在之前的项目中,经常会遇到Calendar,Date的一些操作时间的类,并且总会遇到时间日期之间的格式转化问题,虽然做完了但是总是忘记,记不清楚,每次还都要查找资料.今天总结一下,加深印象. Cale ...

  9. ecshop循环计数

    循环依次递增+1 <!-- {foreach from=$comments item=comment name=comment} --> {$smarty.foreach.comment. ...

  10. 关于Client_Abort_Exception异常的分析和解决

    1.什么情况下会出现“ClientAbortException:  java.net.socketException:  Broken pipe”? 答:客户端非正常(标准握手协议)退出连接,体现在h ...