微信公众平台开发 OAuth2.0网页授权认证

一、什么是OAuth2.0

官方网站:http://oauth.net/   http://oauth.net/2/

权威定义:OAuth is An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications. 

OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、移动或桌面应用上存储的私密的资源(如用户个人信息、照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用。

OAuth 2.0是OAuth协议的下一版本,但不向后兼容OAuth 1.0。 OAuth 2.0关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。

OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。

新浪微博API目前也使用OAuth 2.0。

二、微信公众平台OAuth2.0授权

微信公众平台OAuth2.0授权详细步骤如下:

1. 用户关注微信公众账号。
2. 微信公众账号提供用户请求授权页面URL。
3. 用户点击授权页面URL,将向服务器发起请求
4. 服务器询问用户是否同意授权给微信公众账号(scope为snsapi_base时无此步骤)
5. 用户同意(scope为snsapi_base时无此步骤)
6. 服务器将CODE通过回调传给微信公众账号
7. 微信公众账号获得CODE
8. 微信公众账号通过CODE向服务器请求Access Token
9. 服务器返回Access Token和OpenID给微信公众账号
10. 微信公众账号通过Access Token向服务器请求用户信息(scope为snsapi_base时无此步骤)
11. 服务器将用户信息回送给微信公众账号(scope为snsapi_base时无此步骤)

如果用户在微信中(Web微信除外)访问公众号的第三方网页,公众号开发者可以通过此接口获取当前用户基本信息(包括昵称、性别、城市、国家)。利用用户信息,可以实现体验优化、用户来源统计、帐号绑定、用户身份鉴权等功能。请注意,“获取用户基本信息接口是在用户和公众号产生消息交互时,才能根据用户OpenID获取用户基本信息,而网页授权的方式获取用户基本信息,则无需消息交互,只是用户进入到公众号的网页,就可弹出请求用户授权的界面,用户授权后,就可获得其基本信息(此过程甚至不需要用户已经关注公众号。)”

微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。

在微信公众号请求用户网页授权之前,开发者需要先到公众平台网站的我的服务页中配置授权回调域名。请注意,这里填写的域名不要加http://

关于配置授权回调域名的说明:

授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com  无法进行OAuth2.0鉴权。

具体而言,网页授权流程分为四步:

  1. 引导用户进入授权页面同意授权,获取code

  2. 通过code换取网页授权access_token(与基础支持中的access_token不同)

  3. 如果需要,开发者可以刷新网页授权access_token,避免过期

  4. 通过网页授权access_token和openid获取用户基本信息

目录

[隐藏]

第一步:用户同意授权,获取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参数对应的授权作用域权限。
参考链接(请在微信客户端中打开此链接体验) Scope为snsapi_base https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=http%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 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

参数说明

参数 是否必须 说明
appid公众号的唯一标识
redirect_uri授权后重定向的回调链接地址,请使用urlencode对链接进行处理
response_type返回类型,请填写code
scope应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息
state重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值
#wechat_redirect无论直接打开还是做页面302重定向时候,必须带此参数

下图为scope等于snsapi_userinfo时的授权页面:

网页授权

用户同意授权后

如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE

code说明 : code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

第二步:通过code换取网页授权access_token

首先请注意,这里通过code换取的网页授权access_token,与基础支持中的access_token不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。

请求方法

获取code后,请求以下链接获取access_token:  https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

参数 是否必须 说明
appid公众号的唯一标识
secret公众号的appsecret
code填写第一步获取的code参数
grant_type填写为authorization_code

返回说明

正确时返回的JSON数据包如下:

{    "access_token":"ACCESS_TOKEN",    "expires_in":7200,    "refresh_token":"REFRESH_TOKEN",    "openid":"OPENID",    "scope":"SCOPE" }
参数 描述
access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
expires_inaccess_token接口调用凭证超时时间,单位(秒)
refresh_token用户刷新access_token
openid用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
scope用户授权的作用域,使用逗号(,)分隔


错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}

全局返回码说明

第三步:刷新access_token(如果需要)

由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token拥有较长的有效期(7天、30天、60天、90天),当refresh_token失效的后,需要用户重新授权。

请求方法

获取第二步的refresh_token后,请求以下链接获取access_token:  https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
参数 是否必须 说明
appid公众号的唯一标识
grant_type填写为refresh_token
refresh_token填写通过access_token获取到的refresh_token参数

返回说明

正确时返回的JSON数据包如下:

{    "access_token":"ACCESS_TOKEN",    "expires_in":7200,    "refresh_token":"REFRESH_TOKEN",    "openid":"OPENID",    "scope":"SCOPE" }
参数 描述
access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
expires_inaccess_token接口调用凭证超时时间,单位(秒)
refresh_token用户刷新access_token
openid用户唯一标识
scope用户授权的作用域,使用逗号(,)分隔


错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}

全局返回码说明

第四步:拉取用户信息(需scope为 snsapi_userinfo)

如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。

请求方法

http:GET(请使用https协议) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

参数说明

参数 描述
access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
openid用户的唯一标识
lang返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语

返回说明

正确时返回的JSON数据包如下:

{    "openid":" OPENID",    " nickname": NICKNAME,    "sex":"1",    "province":"PROVINCE"    "city":"CITY",    "country":"COUNTRY",     "headimgurl":    "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",  "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ] }
参数 描述
openid用户的唯一标识
nickname用户昵称
sex用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
province用户个人资料填写的省份
city普通用户个人资料填写的城市
country国家,如中国为CN
headimgurl用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
privilege用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)


错误时微信会返回JSON数据包如下(示例为openid无效):

{"errcode":40003,"errmsg":" invalid openid "}

全局返回码说明

附:检验授权凭证(access_token)是否有效

请求方法

http:GET(请使用https协议) https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID

参数说明

参数 描述
access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
openid用户的唯一标识

返回说明

正确的Json返回结果:

{ "errcode":0,"errmsg":"ok"}

错误时的Json返回示例:

{ "errcode":40003,"errmsg":"invalid openid"}

 案例代码

请求授权页面的构造方式

url在线编码工具:http://tool.oschina.net/encode?type=4

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

前端代码


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd";><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><meta name="viewport" content="width=device-width,height=device-height,inital-scale=1.0,maximum-scale=1.0,user-scalable=no;"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="format-detection" content="telephone=no"><title>会员注册</title><script type="text/javascript" src="jquery.js"></script>

 <script type="text/javascript"> 
  function callback(result) {  
        alert('cucess');         
  alert(result);  //输出openid    
  } 
  
  function getQueryString(name) {  
   var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");   
   var r = window.location.search.substr(1).match(reg);    
   if (r != null) return unescape(r[2]); return null;   
  }
  var code = getQueryString("code");
  
  $.ajax({ 
  async: false,       url: "http://atest.sinaapp.com/oauth2.php", //这是我的服务端处理文件php的     
  type: "GET",       //下面几行是jsoup,如果去掉下面几行的注释,后端对应的返回结果也要去掉注释      
  // dataType: 'jsonp',      
  // jsonp: 'callback', //jsonp的值自定义,如果使用jsoncallback,那么服务器端,要返回一个jsoncallback的值对应的对象.       
  // jsonpCallback:'callback',      
  data: {code:code}, //传递本页面获取的code到后台,以便后台获取openid      
  timeout: 5000,       
  success: function (result) { 
        callback(result);     
  },       
  error: function (jqXHR, textStatus, errorThrown) {
  alert(textStatus);       }   
  });
  
  </script>
  
  </head><body></body> 


后端代码


<?php
$code = $_GET['code'];//前端传来的code值
$appid = "wx468622291a1e99d6";
$appsecret = "98566dc38863aa4395fabebb0de6ecc1";//获取openid
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$appsecret&code=$code&grant_type=authorization_code";
$result = https_request($url);
$jsoninfo = json_decode($result, true);
$openid = $jsoninfo["openid"];//从返回json结果中读出openid
$access_token = $jsoninfo["access_token"];//从返回json结果中读出openid
$callback=$_GET['callback'];  // echo $callback."({result:'".$openid."'})";

$url1 = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN";
$result1 = https_request($url1);
$jsoninfo1 = json_decode($result1, true);
$nickname=$jsoninfo1["nickname"];
echo $openid.":".$access_token.":".$nickname; //把openid 送回前端

 function https_request($url,$data = null){
  $curl = curl_init();   
  curl_setopt($curl, CURLOPT_URL, $url);   
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);   
  curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);    
  if (!empty($data)){    
  curl_setopt($curl, CURLOPT_POST, 1);  
  curl_setopt($curl, CURLOPT_POSTFIELDS, $data);   
  }    
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 
  $output = curl_exec($curl);    
  curl_close($curl);    
  return $output;
 }


?> 

<think>嗯,用户想实现微信小程序和后端的登录集成,包括身份验证和授权流程的最佳实践。首先,我需要回忆一下微信小程序的登录流程。根据微信官方文档,用户登录主要涉及前端获取code,然后传给后端,后端用code、appid和secret去微信服务器换session_key和openid。对吧? 然后,用户可能需要生成自定义的登录态,比如用JWT或者session机制。这一步需要注意安全性,比如不能在前端存储敏感信息,比如session_key。引用里提到后端应该保管好这些信息,前端只用token来维持会话。 接下来,身份验证和授权的流程。前端调用wx.login获取code,然后发送给后端。后端用code换session_key和openid,这里需要确保后端正确调用微信的接口,比如检查返回的errcode。如果有错误,比如code无效,应该如何处理?可能需要返回错误信息给前端。 生成自定义登录态的时候,JWT是个不错的选择。需要设置合适的过期时间,比如两小时。同时,签名密钥要安全存储,不能泄露。返回给前端后,前端每次请求都要带上这个token,放在header里,比如Authorization字段。 安全性方面,引用里提到用HTTPS通信,这很重要。另外,敏感操作需要二次验证,比如修改密码时需要重新授权。还有,定期刷新token,避免长期有效导致风险。 在数据库设计方面,用户的openid需要存储,可能还要关联其他信息。注意openid是唯一的,所以可以用作唯一标识。 可能遇到的常见问题包括code被多次使用,导致失效,所以后端需要及时处理。另外,网络问题导致获取session_key失败,需要重试机制吗?或者前端重新获取code。 还有,用户登录态过期的处理,比如token过期后,前端需要重新走登录流程,获取新的code,后端生成新token。这时候需要友好的提示,引导用户重新登录。 最佳实践部分,应该建议将登录逻辑封装成独立的服务,方便维护。日志记录和监控也不能少,方便排查问题。比如,记录登录失败的原因,监控微信接口的调用情况,确保没有异常。 用户可能还关心如何防止中间人攻击,所以HTTPS是必须的。另外,用户信息加密传输,比如敏感数据加密存储,比如用户的openid虽然不敏感,但也要保护用户隐私。 测试方面,可能需要模拟各种情况,比如网络错误、微信接口返回错误、code无效等,确保后端能正确处理这些异常,返回合适的错误码给前端。 总之,整个流程需要前后端密切配合,遵循微信的规范,同时注重安全性和用户体验。可能还需要参考微信的文档更新,因为接口可能会有变动,比如参数名称或者新增的安全措施。</think>### 微信小程序与后端登录集成实现步骤 #### **1. 登录流程核心步骤** 微信小程序登录流程基于`code`交换机制,具体步骤如下: - **前端获取临时`code`** 用户点击登录按钮时,小程序调用`wx.login()`获取临时登录凭证`code`: ```javascript wx.login({ success(res) { if (res.code) { // 将code发送至后端服务器 wx.request({ url: 'https://your-backend.com/login', method: 'POST', data: { code: res.code }, // 后续处理... }); } } }); ``` - **后端交换`code`为`session_key`和`openid`** 后端通过微信接口将`code`与小程序凭证(`appid`和`app_secret`)结合,换取用户唯一标识`openid`和会话密钥`session_key`[^3]: ```python # Python示例(Django) import requests def wechat_login(code): url = f"https://api.weixin.qq.com/sns/jscode2session?appid={APPID}&secret={SECRET}&js_code={code}&grant_type=authorization_code" response = requests.get(url) data = response.json() if 'errcode' in data: raise Exception(f"微信接口错误: {data['errmsg']}") return data['openid'], data['session_key'] ``` - **生成自定义登录态(如JWT)** 后端生成自定义登录凭证(例如JWT)返回给小程序,用于后续身份验证: ```python import jwt def generate_token(openid): payload = {'openid': openid, 'exp': datetime.utcnow() + timedelta(hours=2)} token = jwt.encode(payload, SECRET_KEY, algorithm='HS256') return token ``` --- #### **2. 身份验证与授权最佳实践** - **安全性要求** - **`session_key`不暴露给前端**:仅在后端用于解密用户数据(如加密的手机号)[^2]。 - **HTTPS通信**:所有接口必须使用HTTPS,防止中间人攻击。 - **敏感操作二次验证**:如支付或修改密码时,需重新调用`wx.login()`获取新`code`[^1]。 - **Token验证流程** 小程序每次请求需携带Token,后端验证有效性: ```python def verify_token(token): try: payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) return payload['openid'] except jwt.ExpiredSignatureError: raise Exception("Token已过期") except jwt.InvalidTokenError: raise Exception("无效Token") ``` --- #### **3. 数据库设计建议** | 字段 | 类型 | 说明 | |---------------|------------|-------------------------------| | `id` | 自增主键 | 用户唯一标识 | | `openid` | varchar(64)| 微信用户唯一标识(不可重复) | | `session_key` | varchar(64)| 微信会话密钥(加密存储) | | `last_login` | datetime | 最后登录时间 | --- #### **4. 常见问题处理** - **`code`过期或重复使用**:需引导用户重新触发`wx.login()`获取新`code`。 - **Token泄露风险**:设置较短的过期时间(如2小时),并支持黑名单机制。 --- #### **5. 最佳实践总结** 1. **逻辑分层**:将登录逻辑封装为独立服务,便于维护和扩展。 2. **监控与日志**:记录登录失败、Token验证异常等事件。 3. **用户信息关联**:通过`openid`关联业务数据时,避免直接暴露给前端。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值