OAuth2.0是OAuth协议的延续版本,但不向前兼容OAuth 2.0(即彻底废止了OAuth1.0)。 OAuth 2.0关注客户端开发者的简易性。要么经过组织在资源拥有者和HTTP服务商之间的被批准的交互动做表明用户,要么容许第三方应用表明用户得到访问的权限。html
以上来自百度百科,即OAuth由Resourse Owner(资源全部者),Client(客户端),以及Provider(服务提供商)组成,Provider包括Authorization Server(认证服务器)和Resource Server(资源服务器)两部分。java
微信的网页受权是基于OAuth2.0协议。好比当咱们的公众号中要修改用户的基本信息时,公众号就要先获取微信中的用户数据;又或者用户修改图片时须要访问手机的相册。若是按传统的方式,用户登陆公众号以后,第三方的公众号就能够随意从微信端获取用户信息,或是手机的所有数据,这就形成了密码泄露的隐患,当你不想使用该公众号又担忧数据外泄,只能修改密码。web
OAuth协议的出现正是为了解决上述这些问题。他将用户名密码受权方式改成经过令牌受权,第三方应用请求访问资源,资源全部者(用户)赞成受权后,再次访问服务提供商(微信官方)去向认证服务器申请令牌(Token),认证服务器赞成后发放令牌(Token),而后第三方应用再拿这个令牌(Token)去向资源服务器(微信官方)申请想要的资源,资源服务器验证经过后开放这个应用所需的资源。json
具体而言,网页受权流程分为四步:api
具体介绍参见公众号开发文档->微信网页受权安全
1、微信web开发者工具服务器
便于在客户端调式,下载地址:微信web开发者工具微信
2、配置网页帐号app
微信测试公众平台->体验接口权限->网页服务->网页帐号->网页受权获取用户基本信息->修改ide
这里暂时仍是使用内网穿透的域名,若须要开发微信支付功能,需使用真实域名。
3、配置静态页面
根据开发文档的返回json,拟作一个页面,用于显示用户的信息
静态资源位置:templates/person.html,该页面用于显示用户的详细信息
1、URL
根据文档,引导网页受权的URL的格式为:open.weixin.qq.com/connect/oau…
注意:
redirect_uri
,应当使用https连接来确保受权code的安全;snsapi_userinfo
,后续即可以经过access_token
和openid
拉取用户信息;2、添加转发页面的控制器
由于本项目暂时使用的时thymeleaf模板,没法直接访问项目中的静态资源,所以须要配置重定向的Controller。(为了跳转方便,后面页面与URL保持不重名)
@Controller
@RequestMapping("/api/v1/wechat1")
public class IndexController {
// 用于thymeleaf环境下,跳转到字符串相应的html页面
@RequestMapping("/{path}")
public String webPath(@PathVariable String path) {
return path;
}
@RequestMapping("/index")
public void index(String code, Model model, HttpServletRequest request, HttpServletResponse response) throws IOException {
// 显式受权,得到code
if (code != null) {
JSONObject accessTokenJson = WeChatUtil.getWebAccessToken(code);
WXPayUtil.getLogger().info("获取网页受权的AccessToken凭据: "+accessTokenJson.toJSONString());
String openid = accessTokenJson.getString(("openid"));
request.getSession().setAttribute("openid", openid);
WXPayUtil.getLogger().info("index openid={}"+openid);
// 重定向到预下单页面
response.sendRedirect("user"); // 回调的访问地址
} else {
StringBuffer url = RequestUtil.getRequestURL(request);
WXPayUtil.getLogger().info("index 请求路径:{}"+url);
String path = WeChatUtil.WEB_REDIRECT_URL.replace("APPID", WeChatConstants.APP_ID).replace("REDIRECT_URI", url).replace("SCOPE", "snsapi_userinfo");
WXPayUtil.getLogger().info("index 重定向:{}"+path);
// 重定向到受权获取code的页面
response.sendRedirect(path);
}
}
}
复制代码
3、启动项目,访问:chety.mynatapp.cc/api/v1/wech…
4、根据URL的格式,替换相关参数。访问: 微信受权页面
open.weixin.qq.com/connect/oau…
5、点击【赞成】后,页面将自动跳转到【/person.html】中
在重定向的URL中,能够看到code和state(这里没有设置,因此为空)
code说明 : code做为换取access_token的票据,每次用户受权带上的code将不同,code只能使用一次,5分钟未被使用自动过时
经过code换取网页受权access_token
1、URL
获取code后,请求如下连接获取access_token: api.weixin.qq.com/sns/oauth2/…
因为公众号的secret和获取到的access_token安全级别都很是高,必须只保存在服务器,不容许传给客户端。后续刷新access_token、经过access_token获取用户信息等步骤,也必须从服务器发起。
2、添加获取access_token的方法
//获取网页受权accessToken的接口
public static final String GET_WEB_ACCESSTOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
/** * 经过code换取网页受权access_token * @param code * @return */
public static JSONObject getWebAccessToken(String code){
String result = HttpUtil.get(GET_WEB_ACCESSTOKEN_URL.replace("APPID", WeChatConstants.APP_ID).replace("SECRET", WeChatConstants.APPSECRET).replace("CODE", code));
return JSONObject.parseObject(result);
}
复制代码
返回说明
因为access_token拥有较短的有效期,当access_token超时后,可使用refresh_token进行刷新,refresh_token有效期为30天,当refresh_token失效以后,须要用户从新受权。
1、URL
获取第二步的refresh_token后,请求如下连接获取access_token: api.weixin.qq.com/sns/oauth2/…
grant_type填写为refresh_token
2、添加工具类方法
// 获取网页受权accessToken的接口
public static final String GET_WEB_ACCESSTOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
/** * 刷新access_token * @param refresh_token * @return */
public static JSONObject refreshWebAccessToken(String refresh_token){
String result = HttpUtil.get(GET_WEB_ACCESSTOKEN_URL.replace("APPID", WeChatConstants.APP_ID).replace("REFRESH_TOKEN", refresh_token));
return JSONObject.parseObject(result);
}
复制代码
1、URL
http:GET(请使用https协议) api.weixin.qq.com/sns/userinf…
2、添加工具类方法
/** * 获取用户信息 * @param accessToken * @param openId * @return */
public static JSONObject getUserInfo(String accessToken,String openId){
String result = HttpUtil.get(GET_USERINFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID",openId));
return JSONObject.parseObject(result);
}
复制代码
3、添加跳转用户信息的接口
/** * 网页受权获取用户信息 * @param code * @return */
@RequestMapping("/user")
public String person(String code,ModelMap map){
if(code!=null) {
//经过code来换取access_token
JSONObject result = WeChatUtil.getWebAccessToken(code);
//经过access_token和openid拉取用户信息
JSONObject userInfo = WeChatUtil.getUserInfo(result.getString("access_token"), result.getString("openid"));
WXPayUtil.getLogger().info("用户信息为:{}"+ JSON.toJSONString(userInfo));
//获取json对象中的键值对集合
Set<Map.Entry<String, Object>> entries = userInfo.entrySet();
for (Map.Entry<String, Object> entry : entries) {
map.addAttribute(entry.getKey(),entry.getValue());
}
}
return "person";
}
复制代码
这里包含用户信息的键名直接用了微信返回的默认值,person页面也使用该默认名。
4、再次访问:
open.weixin.qq.com/connect/oau…
能够看到,已经获取了微信中返回的信息
http:GET(请使用https协议) api.weixin.qq.com/sns/auth?ac…