微信公众号如何授权登录、获取用户信息(openid) |
您所在的位置:网站首页 › openid怎么获得 › 微信公众号如何授权登录、获取用户信息(openid) |
首先看一下实现的效果,在公众号中,用户进入你的应用之前,会弹出一个授权页面,当用户点击确认后,你就可以获取用户的信息 首先访问微信测试号登录页面,通过打开自己手机的微信,扫一扫登录 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login 当你填完URL和Token点击提交后,微信会访问你填写的URL,所以要在后台写一个servlet来处理这个请求 处理请求的Controller @Controller @RequestMapping("wechat") public class WeiXinController { @RequestMapping(method = { RequestMethod.GET }) public void doGet(HttpServletRequest request, HttpServletResponse response) { // 微信加密签名 String signature = request.getParameter("signature"); // 时间戳 String timestamp = request.getParameter("timestamp"); // 随机数 String nonce = request.getParameter("nonce"); // 随机字符串 String echostr = request.getParameter("echostr"); // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 PrintWriter out = null; try { out = response.getWriter(); if (SignUtil.checkSignature(signature, timestamp, nonce)) { log.debug("weixin get success...."); out.print(echostr); } } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) out.close(); } } }微信请求校验工具类 /** * 微信请求校验工具类 */ public class SignUtil { // 与接口配置信息中的Token要一致 private static String token = "mytoken"; /** * 验证签名 * @param signature * @param timestamp * @param nonce * @return */ public static boolean checkSignature(String signature, String timestamp, String nonce) { String[] arr = new String[] { token, timestamp, nonce }; // 将token、timestamp、nonce三个参数进行字典序排序 Arrays.sort(arr); StringBuilder content = new StringBuilder(); for (int i = 0; i md = MessageDigest.getInstance("SHA-1"); // 将三个参数字符串拼接成一个字符串进行sha1加密 byte[] digest = md.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } content = null; // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; } /** * 将字节数组转换为十六进制字符串 * @param byteArray * @return */ private static String byteToStr(byte[] byteArray) { String strDigest = ""; for (int i = 0; i char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; } }请求的处理程序写完后把项目重新打包发布到服务器上去,再提交你填写的URL和Token,接口配置信息就Ok啦 【JS接口安全域名】 域名:想调用jssdk(如想要通过微信公众号js接口获取地图等工具)必须得填写此域名,在此域名的范围内才能调用jssdk工具,注意这里必须是域名,不是带有http之类的URL 【UserAccessToken】用户AccessToken实体类,用来接收accesstoken以及openid等信息 /** * 用户授权token * */ public class UserAccessToken { // 获取到的凭证 @JsonProperty("access_token") private String accessToken; // 凭证有效时间,单位:秒 @JsonProperty("expires_in") private String expiresIn; // 表示更新令牌,用来获取下一次的访问令牌,这里没太大用处 @JsonProperty("refresh_token") private String refreshToken; // 该用户在此公众号下的身份标识,对于此微信号具有唯一性 @JsonProperty("openid") private String openId; // 表示权限范围,这里可省略 @JsonProperty("scope") private String scope; public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public String getExpiresIn() { return expiresIn; } public void setExpiresIn(String expiresIn) { this.expiresIn = expiresIn; } public String getRefreshToken() { return refreshToken; } public void setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; } 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; } @Override public String toString() { return "accessToken:" + this.getAccessToken() + ",openId:" + this.getOpenId(); } }【WechatUser】微信用户实体类,用来接收昵称 openid等用户信息 /** * 微信用户实体类 */ public class WechatUser implements Serializable { private static final long serialVersionUID = -4684067645282292327L; // openId,标识该公众号下面的该用户的唯一Id @JsonProperty("openid") private String openId; // 用户昵称 @JsonProperty("nickname") private String nickName; // 性别 @JsonProperty("sex") private int sex; // 省份 @JsonProperty("province") private String province; // 城市 @JsonProperty("city") private String city; // 区 @JsonProperty("country") private String country; // 头像图片地址 @JsonProperty("headimgurl") private String headimgurl; // 语言 @JsonProperty("language") private String language; // 用户权限,这里没什么作用 @JsonProperty("privilege") private String[] privilege; 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 int getSex() { return sex; } public void setSex(int 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 String getLanguage() { return language; } public void setLanguage(String language) { this.language = language; } public String[] getPrivilege() { return privilege; } public void setPrivilege(String[] privilege) { this.privilege = privilege; } @Override public String toString() { return "openId:" + this.getOpenId() + ",nikename:" + this.getNickName(); } }【WechatUtil】主要用来提交https请求给微信获取用户信息 /** * 微信工具类 */ public class WechatUtil { private static Logger log = LoggerFactory.getLogger(WechatUtil.class); /** * 获取UserAccessToken实体类 * @param code * @return * @throws IOException */ public static UserAccessToken getUserAccessToken(String code) throws IOException { // 测试号信息里的appId String appId = "您的appId"; log.debug("appId:" + appId); // 测试号信息里的appsecret String appsecret = "您的appsecret"; log.debug("secret:" + appsecret); // 根据传入的code,拼接出访问微信定义好的接口的URL String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appsecret + "&code=" + code + "&grant_type=authorization_code"; // 向相应URL发送请求获取token json字符串 String tokenStr = httpsRequest(url, "GET", null); log.debug("userAccessToken:" + tokenStr); UserAccessToken token = new UserAccessToken(); ObjectMapper objectMapper = new ObjectMapper(); try { // 将json字符串转换成相应对象 token = objectMapper.readValue(tokenStr, UserAccessToken.class); } catch (JsonParseException e) { log.error("获取用户accessToken失败: " + e.getMessage()); e.printStackTrace(); } catch (JsonMappingException e) { log.error("获取用户accessToken失败: " + e.getMessage()); e.printStackTrace(); } catch (IOException e) { log.error("获取用户accessToken失败: " + e.getMessage()); e.printStackTrace(); } if (token == null) { log.error("获取用户accessToken失败。"); return null; } return token; } /** * 获取WechatUser实体类 * @param accessToken * @param openId * @return */ public static WechatUser getUserInfo(String accessToken, String openId) { // 根据传入的accessToken以及openId拼接出访问微信定义的端口并获取用户信息的URL String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN"; // 访问该URL获取用户信息json 字符串 String userStr = httpsRequest(url, "GET", null); log.debug("user info :" + userStr); WechatUser user = new WechatUser(); ObjectMapper objectMapper = new ObjectMapper(); try { // 将json字符串转换成相应对象 user = objectMapper.readValue(userStr, WechatUser.class); } catch (JsonParseException e) { log.error("获取用户信息失败: " + e.getMessage()); e.printStackTrace(); } catch (JsonMappingException e) { log.error("获取用户信息失败: " + e.getMessage()); e.printStackTrace(); } catch (IOException e) { log.error("获取用户信息失败: " + e.getMessage()); e.printStackTrace(); } if (user == null) { log.error("获取用户信息失败。"); return null; } return user; } /** * 发起https请求并获取结果 * @param requestUrl * 请求地址 * @param requestMethod * 请求方式(GET、POST) * @param outputStr * 提交的数据 * @return json字符串 */ public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) { StringBuffer buffer = new StringBuffer(); try { // 创建SSLContext对象,并使用我们指定的信任管理器初始化 TrustManager[] tm = { new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); // 从上述SSLContext对象中得到SSLSocketFactory对象 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl); HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection(); httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); // 设置请求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect(); // 当有数据需要提交时 if (null != outputStr) { OutputStream outputStream = httpUrlConn.getOutputStream(); // 注意编码格式,防止中文乱码 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 将返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); log.debug("https buffer:" + buffer.toString()); } catch (ConnectException ce) { log.error("Weixin server connection timed out."); } catch (Exception e) { log.error("https request error:{}", e); } return buffer.toString(); } }【MyX509TrustManager】主要继承X509TrustManager做https证书信任管理器 /** * 证书信任管理器(用于https请求) * */ public class MyX509TrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }之后重新打包一个新的war包并发布到服务器tomcat webapps目录下 发布成功后,关注你自己的测试号(即扫描测试号的那个二维码),然后在手机微信里面或者微信开发者工具里访问相应链接: https://open.weixin.qq.com/connect/oauth2/authorize?appid=您的appId&redirect_uri=WechatLoginController对应的地址&role_type=1&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |