关于微信授权的一些个人心得。由于最近做一个微信公众号的开发,所以首先用到的就是微信授权这一块的内容。
首先微信的网页授权分为静默和用户点击允许授权。也就是网页授权中的两种scope(scope=snsapi_base和scope=snsapi_userinfo)。
微信授权的一般步骤:1:用户同意授权,获取code
2:通过code换区网页授权的access_token(静默授权到此结束,即scope=snsapi_base)
3 : 刷新access_token(如果需要的话)
4:拉取用户信息(需要scope=snsapi_userinfo)可以用户的头像、位置等信息。
一:用户同意授权获取code
在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获取高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导用户打开如下页面:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
对于上面参数的理解:appid是公众好的唯一标识。
redirect_url:授权后重定向的回调链接(需要使用)URLEncoder.encode(redirect_url, "utf-8");对其进行编码,
response_type:返回类型,请填写code
scope:应用授权作用域,snsapi_base(不弹出授权页面,直接跳转,只能获取openID)snsapi_userinfo(弹出授权页面,可以通过openID拿到昵称、性别、所在地,即使在未关注的情况下,只要用户授权,也能获取信息)
state:重定向后会带上state参数
#wechar_redirect无论直接打开还是重定向都必须带上此参数
以上参数除了state之外,其他的参数都是必须的。
@RequestMapping("oauth_reg")
public Object oauth_reg(
@RequestParam(required = false) String openid,
@RequestParam(required = false) String redirectUrl,
ModelMap mmap, HttpServletRequest req, HttpSession session)
throws Exception {
String userAgent = req.getHeader("User-Agent");//获取浏览器信息
if (userAgent != null && !userAgent.contains("MicroMessenger")) {//判断用户是否是微信端登录
if (openid == null ) {
return ResponseEntityFactory.textPlain("请在微信客户端打开链接");
}
//
return "redirect:index";
} else {
String redirect = URLEncoder.encode(redirect_url, "utf-8");
String url="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+oauth2_appid+"&redirect_uri="+redirect+
"&response_type=code&scope="+oauth2_scope+"#wechat_redirect";
return "redirect:" + url;
}
}
第二步:回调通过code获取openID
@RequestMapping("oauth_callback")
public Object oauth_callback( String code, HttpServletRequest req) throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
InputStream is = null;
String url="https://api.weixin.qq.com/sns/oauth2/access_token";
//封装请求参数
List<NameValuePair> params = Lists.newArrayList();
params.add(new BasicNameValuePair("appid", oauth2_appid));
params.add(new BasicNameValuePair("secret", oauth2_appsecret));
params.add(new BasicNameValuePair("code", code));
params.add(new BasicNameValuePair("grant_type", "authorization_code"));
String str = "";
try {
//转换为键值对
str = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
//创建Get请求
HttpGet httpGet = new HttpGet(url+"?"+str);
//执行Get请求,
response = httpClient.execute(httpGet);
//得到响应体
HttpEntity entity = response.getEntity();
if(entity != null){
is = entity.getContent();
//转换为字节输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is, Consts.UTF_8));
String body = null;
while((body=br.readLine()) != null){
@SuppressWarnings("unchecked")
Map<String,String> map=om.readValue(body, HashMap.class);
String openid = map.get("openid");
req.getSession().setAttribute("openid", openid);
}
}
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
//关闭输入流,释放资源
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//消耗实体内容
if(response != null){
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭相应 丢弃http连接
if(httpClient != null){
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "redirect:index";
}
对应的httpclient的jar
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.6</version>
</dependency>
<dependency><groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.2</version>
</dependency>