我们经常会访问一些网站,用微信登录的时候需要用到授权,那么微信网页授权是怎么一回事呢,一起来看看吧!
 
 
官方的文档有很详细的说明,这里就主要分析重要的几点:
第一,网页授权分类及说明:
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下一个简单的数据库分库帮助类

    简介    前面两篇文章主要讲了数据库读写分离和分表分库的一些问题,这篇文章主要讲一下我个人实现的一个分表分库项目.     在此之前,我有写过一个.Net的分库,最近在做Java的项目,就顺便做出一 ...

  2. CVE-2017-8464远程命令执行漏洞(震网漏洞)复现

    前言 2017年6月13日,微软官方发布编号为CVE-2017-8464的漏洞公告,官方介绍Windows系统在解析快捷方式时存在远程执行任意代码的高危漏洞,黑客可以通过U盘.网络共享等途径触发漏洞, ...

  3. tr的用法

    一.tr的基本功能 功能:转换.挤压或删除字符串,从标准输入接收输入,输出到标准输出基本用法:tr [options] string1 [string2] 二.例子 1.转换 $ echo " ...

  4. 在firefox的flashgot中配置各种下载器

    一.在firefox中安装flashgot下载管理器 flashgot是firefox的一个扩展,在联网的情况下,可以在firefox中的附加组件中搜索flashgot,然后安装. 二.在flashg ...

  5. 开发抓包工具 Mac charles 3.11.5 破解版 安装包

    摘要 在发开过程中,追踪请求和监控请求与返回数据是我们经常会需要的一个需求,在Mac端,Charles是一款非常易用的抓包工具. 一.简介 Charles是Mac端的一款截取与分析网络请求的工具,在网 ...

  6. oracle备份、还原

    ----第一步:设置空表导出 ----由于Oracle 11G在用EXPORT导出时,空表不能导出.解决方法如下:(11G中有个新特性,当表无数据时,不分配segment,以节省空间) select ...

  7. IE6不支持position:fixed的解决方法

    解决IE6不支持position:fixed的方法,非常简单,具体调用请参考下面: /*让position:fixed在IE6下可用! */ .fixed-top /* 头部固定 */{positio ...

  8. 行内元素和块级元素的具体区别是什么?行内元素的padding和margin可设置吗?

    块级元素(block)特性: 总是独占一行,表现为另起一行开始,而且其后的元素也必须另起一行显示; 宽度(width).高度(height).内边距(padding)和外边距(margin)都可控制; ...

  9. MFC简单绘制安卓机器人

    原始日期:2014-03-29 20:35 众所周知,google的安卓机器人形象十分经典,包括眼睛的位置,胳膊以及天线的位置都是有固定位置和比例的,而且是最恰当的,看起来最美.而微软基础类库MFC绘 ...

  10. Reids命令解析-RENAME

    有一天开发突然照过来问,维萨我这个Redis实例这么慢呢?为什么这么慢,于是连上实例SLOWLOG 一看,这些慢日志都是大部分是RENMAE操作导致的,可是为什么RENAME操作会慢呢?不就是改个名字 ...