您的位置:首页 > 移动开发 > 微信开发

微信授权登录

2017-08-18 15:24 232 查看
微信网页授权登陆,官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

一、创建授权URL

例子:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
其中state参数,微信会在用户授权之后,回调时,返回给我们的。这个参数很重要,一般需要确保该参数是唯一的(我使用了UUID)

其它参数含义,参照官方文档。

由于该授权链接太长,生成的二维码很密集,这会导致扫码响应时间边长,特别是性能不好的手机。

所以在这里建议将长链接转成短链接。

可以调用微信的接口(长链接转短链接接口),

长链接转短链接接口微信官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433600

生成短链接后,我将短链接和state参数一起返回给前端

前端用短链接生成二维码,

state参数用于页面的轮询

具体代码:
// 公众号的唯一标识
private static String APP_ID = "";
// 用户同意授权URL(对urlEncode之后)
private static String REDIRECT_URL = "";
// 用户同意授权URL
private static String AUTHORIZATION_URL = "https://open.weixin.qq.com/connect/oauth2/authorize";
/**
* 创建授权URL
*
* @param commontoken 微信普通token
* @param state
* @return
* @throws Exception
*/
public Map<String, String> createAuthorizationURL(String commontoken,
String state) throws Exception {
// 微信用户登录授权URL
String longUrl = AUTHORIZATION_URL +"?appid=" + APP_ID + "&redirect_uri=" + REDIRECT_URL
+ "&response_type=code&scope=snsapi_userinfo&state=" + state + "#wechat_redirect";
// 请求路径(将长链接转成短链接)
String url = "https://api.weixin.qq.com/cgi-bin/shorturl?access_token=" + commontoken;
// json参数
JSONObject jsonParam = new JSONObject();
jsonParam.put("action", "long2short");
jsonParam.put("long_url", longUrl);
// 请求参数
String param = jsonParam.toString();
// 发送请求并获取结果(将长链接转成短链接)
String result = SendHttpRequest.sendPostRequest(url, param);
if (!result.contains("short_url")) {
throw new Exception(result);
}
// 转成json
JSONObject json = JSONObject.parseObject(result);
// 保存state
Map<String, Object> data = new HashMap<String, Object>();
data.put("state", state);
data.put("expiredTime", (System.currentTimeMillis() + 300000)); // state过期时间
// 保存state
// 注:由于本人没有接触过redis,再加上项目紧,来不及现学
//       所以我这一步是将state存放在了数据库里,
//       个人建议最好存放在缓存中(当然主要还是要根据项目来)
weChatStateDao.add(data);
// 返回值
Map<String, String> resultMap = new HashMap<String, String>();
resultMap.put("state", state);
resultMap.put("shortURL", json.getString("short_url"));
return resultMap;
}
二、通过code换取网页授权access_token

微信回调之后会返回code,state(我们传过去的参数)

用code换取access_token相关信息,包括用户的openId

用state从数据库获取state相关信息,并将openId存放进去

(之后轮询调用接口时,state记录中有无openId将作为用户是否已经授权登录的依据)
微信回调函数

/**
* 获取授权认证(for user)
* (用户扫码之后,微信会调用该接口,并传递2个参数code,state)
* code 用于换取特殊(access_token,该token可以获取用户相关信息)
* state 用于验证
*
* @param request
* @return
*/
@RequestMapping(value = "")
public void getAuthorization(HttpServletRequest request, HttpServletResponse response) {
// 获取微信授权端返回的code
String code = request.getParameter("code");
// 获取微信授权端返回的status
String state = request.getParameter("state");
try {
// 根据state获取state相关信息
Map<String, Object> entity = authenticationService.getState(state);
if(entity == null) {
throw new Exception("状态码不存");
}
// 获取过期时间
Long expiredTime = (Long) entity.get("expiredTime");
if (expiredTime < System.currentTimeMillis()) {
throw new Exception("状态码已过期");
}
// 用code换取access_token相关信息
JSONObject tokenJson = authenticationService.getAccessToken(code);
// access_token
String accessToken = (String) tokenJson.get("access_token");
// 用户唯一标识
String openId = (String) tokenJson.get("openid");
// 更新state
entity.put("openId", openId);
authenticationService.updateState(entity);
// 根据openid获取用户信息,判断用户是否注册过
UserInfo userInfo = userInfoService.getByOpenId(openId);
// 如果用户未注册过,则新增
if (userInfo == null) {
userInfo = new UserInfoVo();
// 拉取用户信息
JSONObject userInfoJson = authenticationService.getUserInfo(accessToken, openId);
String nickName = userInfoJson.getString("nickname"); // 昵称 (这里需要处理带有表情的昵称,否则可能会导致无法存入到数据库)
String headImgUrl = userInfoJson.getString("headimgurl"); // 头像(如果用户修改了头像,此路径会无效)
userInfo.setUserName(nickName); // 设置用户姓名
userInfo.setHeadImage(headImgUrl); // 设置用户头像
userInfo.setWechatOpenId(openId); // 设置openId
userInfo.setCreateTime
9f3d
(new Date());// 创建时间
userInfoService.add(userInfo);
}
// 重定向,用户授权之后,微信端的页面显示
response.sendRedirect("");
} catch (Exception e) {
e.printStackTrace();
}
}


三、页面轮询

/**
* 校验state(页面轮询调用 for user)
*
* @param request
* @return
*/
@RequestMapping(value = "")
public String checkedState(HttpServletRequest request) {
String state = request.getParameter("state");
try {
// 根据state获取state相关信息
Map<String, Object> data = weChatStateService.get(state);
String openId = (String) data.get("openId");
if (StringUtils.isBlank(openId)) {
return JacksonUtil.toBizJson("4001", "未扫码", null);
}
return JacksonUtil.toBizJson("0", "验证通过", data);
} catch (Exception e) {
e.printStackTrace();
return JacksonUtil.toBizJson("1", "系统错误", null);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: