网页授权的回调域名
关于网页授权的两种scope的区别说明
-
以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。
-
以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
-
用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。
关于网页授权access_token和普通access_token的区别
关于UnionID机制
-
请注意,网页授权获取用户基本信息也遵循UnionID机制。即如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。
-
UnionID机制的作用说明:如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。
关于特殊场景下的静默授权
网页授权流程
参考链接
scope为snsapi_base
1
| https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect
|
scope为snsapi_userinfo
1
| https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
|
尤其注意:跳转回调redirect_uri,应当使用https链接来确保授权code的安全性。
制作二维码的工具类QRCodeGenerator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Hashtable;
public class QRCodeGenerator {
public static void creatRrCode(String contents, int width, int height,HttpServletResponse response) { Hashtable hints = new Hashtable(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); //容错级别最高 hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); //设置字符编码 hints.put(EncodeHintType.MARGIN, 1); //二维码空白区域,最小为0也有白边,只是很小,最小是6像素左右 try { // 1、读取文件转换为字节数组 BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);
BufferedImage image = toBufferedImage(bitMatrix);
//转换成png格式的IO流 ImageIO.write(image, "png", response.getOutputStream()); // byte[] bytes = out.toByteArray(); // 2、将字节数组转为二进制 // BASE64Encoder encoder = new BASE64Encoder(); // binary = encoder.encodeBuffer(bytes).trim(); } catch (WriterException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
/** * image流数据处理 * * @author ianly */ public static BufferedImage toBufferedImage(BitMatrix matrix) { int width = matrix.getWidth(); int height = matrix.getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } return image; } }
|
显示二维码的页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>微信登录</title> </head> <body> <img id="qrcode" style="padding-left: 20px" src="qrcode"> </body> <script> </script> </html>
|
二维码的地址,后台controller代码
1 2 3 4 5 6 7 8 9 10
| public String appid = "wxe6774713a448fb6f"; public String secret = "1fec63da4f2a53c3224e6adf6dd4876e";
@RequestMapping("qrcode") public void login(HttpServletResponse response){ String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; String redirect_uri = URLEncoder.encode("http://eeee.free.idcfengye.com/getCode"); String params = "appid="+appid+"&secret="+secret+"&redirect_uri="+redirect_uri+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; QRCodeGenerator.creatRrCode(url+params, 180,180,response); }
|
code传递二维码的redirect_uri,然后通过code获取access_token,再刷新access_token,最后拉取用户信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| //二维码地址的redirect_uri @RequestMapping("/getCode") public ModelAndView toSuccess(HttpServletRequest request){ String code = request.getParameter("code");
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?"; String params = "appid="+appid+"&secret="+secret+"&code="+code+"&grant_type=authorization_code";
//调用httpGet方法发送url并返回json对象,可以获取access_token和refresh_token JSONObject jsonObject = this.httpGet(url+params); //使用refresh_token刷新access_token String refresh_token = jsonObject.getString("refresh_token");
String url1 = "https://api.weixin.qq.com/sns/oauth2/refresh_token?"; String params1 = "appid="+appid+"&grant_type=refresh_token&refresh_token="+refresh_token;
//调用httpGet方法发送url并返回json对象,可以获取刷新后的access_token JSONObject jsonObject1 = this.httpGet(url1+params1); //使用刷新的access_token和openid获取用户信息 String access_token = jsonObject.getString("access_token"); String openid = jsonObject.getString("openid");
String url2 = "https://api.weixin.qq.com/sns/userinfo?"; String params2 = "access_token="+access_token+"&openid="+openid+"&lang=zh_CN";
//调用httpGet方法发送url并返回json对象,获取用户信息 JSONObject jsonObject2 = this.httpGet(url2+params2); //System.out.println(jsonObject2);
ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("success"); modelAndView.addObject("userInfo", jsonObject2); return modelAndView; }
|
使用htpClient发送url请求获取返回,用阿里的fastjson解析json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public JSONObject httpGet(String url) { JSONObject jsonResult = null; try { //目前HttpClient最新版的实现类为CloseableHttpClient CloseableHttpClient client = HttpClients.createDefault(); //get方法 HttpGet request = new HttpGet(url); //post方法 //HttpPost request = new HttpPost(url);
//执行Request请求,CloseableHttpClient的execute方法返回的response都是CloseableHttpResponse类型 CloseableHttpResponse response = client.execute(request);
//判断响应的状态码是否为200 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { //用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串,防止服务器返回的数据带有中文,所以在转换的时候将字符集指定成utf-8就可以了 String strResult = EntityUtils.toString(response.getEntity(),"UTF-8"); //将字符串转换json对象 jsonResult = JSON.parseObject(strResult); } else { System.out.println("请求出错"); } } catch (IOException e) { e.printStackTrace(); } return jsonResult; }
|