AI写作智能体 自主规划任务,支持联网查询和网页读取,多模态高效创作各类分析报告、商业计划、营销方案、教学内容等。 广告
# 例子:第三方登录 ## 一、第三方登录的原理 所谓第三方登录,实质就是 OAuth 授权。用户想要登录 A 网站,A 网站让用户提供第三方网站的数据,证明自己的身份。获取第三方网站的身份数据,就需要 OAuth 授权。 举例来说,A 网站允许 GitHub 登录,背后就是下面的流程。 > 1. A 网站让用户跳转到 GitHub。 > 2. GitHub 要求用户登录,然后询问"A 网站要求获得 xx 权限,你是否同意?" > 3. 用户同意,GitHub 就会重定向回 A 网站,同时发回一个授权码。 > 4. A 网站使用授权码,向 GitHub 请求令牌。 > 5. GitHub 返回令牌. > 6. A 网站使用令牌,向 GitHub 请求用户数据。 ## 二、应用登记 一个应用要求 OAuth 授权,必须先到对方网站登记,让对方知道是谁在请求。 所以,你要先去 GitHub 登记一下。当然,我已经登记过了,你使用我的登记信息也可以,但为了完整走一遍流程,还是建议大家自己登记。这是免费的。 访问这个[网址](https://github.com/settings/applications/new),填写登记表。 ![](https://img.kancloud.cn/8e/b1/8eb16caae5456af933edb8854485a551_517x436.png) ![](https://img.kancloud.cn/5d/b4/5db4d5d3dd755760e646b967f5ca3df0_493x412.png) [OAuth文档](https://developer.github.com/v3/oauth/) 应用的名称随便填,主页 URL 填写`http://localhost:80`,跳转网址填写`http://localhost:80/oauth/redirect`。 提交表单以后,GitHub 应该会返回客户端 ID(client ID)和客户端密钥(client secret),这就是应用的身份识别码。 ![](https://img.kancloud.cn/9a/6c/9a6c311b2557ad8e3f320bed190fbd8e_413x107.png) - - - - - - ``` <pre class="calibre10">``` <span class="token1"><</span><span class="token1">!</span>DOCTYPE html<span class="token1">></span> <span class="token1"><</span>html<span class="token1">></span> <span class="token1"><</span>head<span class="token1">></span> <span class="token1"><</span>meta charset<span class="token1">=</span><span class="token2">"utf-8"</span> <span class="token1">/</span><span class="token1">></span> <span class="token1"><</span>meta http<span class="token1">-</span>equiv<span class="token1">=</span><span class="token2">"X-UA-Compatible"</span> content<span class="token1">=</span><span class="token2">"IE=edge"</span><span class="token1">></span> <span class="token1"><</span>title<span class="token1">></span>OAuth2 Demo<span class="token1"><</span><span class="token1">/</span>title<span class="token1">></span> <span class="token1"><</span>meta name<span class="token1">=</span><span class="token2">"viewport"</span> content<span class="token1">=</span><span class="token2">"width=device-width, initial-scale=1"</span><span class="token1">></span> <span class="token1"><</span><span class="token1">/</span>head<span class="token1">></span> <span class="token1"><</span>body<span class="token1">></span> <span class="token1"><</span>a id<span class="token1">=</span><span class="token2">"login"</span><span class="token1">></span>GitHub登录<span class="token1"><</span><span class="token1">/</span>a<span class="token1">></span> <span class="token1"><</span>script<span class="token1">></span> <span class="token">// fill in your cliend_id</span> const client_id <span class="token1">=</span> <span class="token2">'cdeca9e8ee6c9522d22e'</span><span class="token3">;</span> const authorize_uri <span class="token1">=</span> <span class="token2">'https://github.com/login/oauth/authorize'</span><span class="token3">;</span> <span class="token">//这个地址是浏览器跳转的,获取code成功后guthub会将这个跳转地址与code一起回应给客户端,并且httpcode是302(告诉浏览器跳转到这个地址,浏览器知道是302后就会自动跳转了)</span> const redirect_uri <span class="token1">=</span> <span class="token2">'http://localhost:80/oauth/redirect.php'</span><span class="token3">;</span> const link <span class="token1">=</span> document<span class="token3">.</span><span class="token4">getElementById</span><span class="token3">(</span><span class="token2">'login'</span><span class="token3">)</span><span class="token3">;</span> link<span class="token3">.</span>href <span class="token1">=</span> `$<span class="token3">{</span>authorize_uri<span class="token3">}</span><span class="token1">?</span>client_id<span class="token1">=</span>$<span class="token3">{</span>client_id<span class="token3">}</span><span class="token1">&</span>redirect_uri<span class="token1">=</span>$<span class="token3">{</span>redirect_uri<span class="token3">}</span>`<span class="token3">;</span> <span class="token1"><</span><span class="token1">/</span>script<span class="token1">></span> <span class="token1"><</span><span class="token1">/</span>body<span class="token1">></span> <span class="token1"><</span><span class="token1">/</span>html<span class="token1">></span> ``` ``` 点击GitHub登录连接跳转至github,登录github后跳至授权页面 ![](https://img.kancloud.cn/fb/31/fb316ef954fd9ca1984823be3f31e5f0_470x357.png) 跳转格式如下: ``` <pre class="calibre10">``` https<span class="token3">:</span><span class="token1">/</span><span class="token1">/</span>github<span class="token3">.</span>com<span class="token1">/</span>login<span class="token1">/</span>oauth<span class="token1">/</span>authorize<span class="token1">?</span>client_id<span class="token1">=</span>xxoo<span class="token1">&</span>redirect_uri<span class="token1">=</span>xxoo ``` ``` 这个 URL 指向 GitHub 的 OAuth 授权网址,带有两个参数:`client_id`告诉 GitHub 谁在请求,`redirect_uri`是稍后跳转回来的网址 确认后,github携带code跳转至http://localhost/oauth/redirect.php?code=2c2795dda93994a15c8c 七、令牌 后端使用这个授权码,向 GitHub 请求令牌。 redirect.php ``` <pre class="calibre10">``` <span class="token">/** * url get或者post方式请求 * * @param string $url 要请求的url地址 * @param array $data 要发送的数据 存在该参数就启用post提交,否则为get请求 * @return mixed $output 返回请求的结果 */</span> <span class="token5">function</span> <span class="token4">curl</span><span class="token3">(</span>$url<span class="token3">,</span> $data <span class="token1">=</span> <span class="token5">null</span><span class="token3">)</span><span class="token3">{</span> <span class="token">// 1.创建一个新的CURL资源</span> $ch <span class="token1">=</span> <span class="token4">curl_init</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 2.设置URL相应的选项</span> <span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_URL<span class="token3">,</span> $url<span class="token3">)</span><span class="token3">;</span> <span class="token">// 设置请求的URL地址</span> <span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_RETURNTRANSFER<span class="token3">,</span> <span class="token6">1</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 将curl_exec()获取的信息以文件流的形式返回,而不是直接输出(0为直接输出)</span> <span class="token">//curl_setopt($ch, CURLOPT_HEADER, 0); // 启用时会将头文件的信息作为数据流输出</span> <span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_TIMEOUT<span class="token3">,</span> <span class="token6">10</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 设置cURL允许执行的最长秒数</span> <span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_POST<span class="token3">,</span> $data <span class="token1">?</span> <span class="token6">1</span> <span class="token3">:</span> <span class="token6">0</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 存在data就启用post发送 启用时会发送一个常规的POST请求,类型为:application/x-www-form-urlencoded,就像表单提交的一样。</span> <span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_POSTFIELDS<span class="token3">,</span> $data<span class="token3">)</span><span class="token3">;</span> <span class="token">//data必须数组</span> <span class="token">//忽略证书</span> <span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_SSL_VERIFYPEER<span class="token3">,</span> <span class="token6">false</span><span class="token3">)</span><span class="token3">;</span> <span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_SSL_VERIFYHOST<span class="token3">,</span> <span class="token6">false</span><span class="token3">)</span><span class="token3">;</span> <span class="token5">if</span> <span class="token3">(</span><span class="token1">!</span><span class="token4">empty</span><span class="token3">(</span>$header<span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span> <span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span>CURLOPT_HTTPHEADER<span class="token3">,</span>$header<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span><span class="token5">else</span><span class="token3">{</span> <span class="token4">curl_setopt</span><span class="token3">(</span>$curl<span class="token3">,</span> CURLOPT_HEADER<span class="token3">,</span> <span class="token6">0</span><span class="token3">)</span><span class="token3">;</span><span class="token">//返回response头部信息</span> <span class="token3">}</span> <span class="token">// 3.抓去URL并将它传递给浏览器</span> $output <span class="token1">=</span> <span class="token4">curl_exec</span><span class="token3">(</span>$ch<span class="token3">)</span><span class="token3">;</span> <span class="token">// 4.关闭CURL资源,并且释放系统资源</span> <span class="token4">curl_close</span><span class="token3">(</span>$ch<span class="token3">)</span><span class="token3">;</span> <span class="token">// 返回输出</span> <span class="token5">return</span> $output<span class="token3">;</span> <span class="token3">}</span> $data<span class="token1">=</span><span class="token3">[</span> <span class="token2">'client_id'</span><span class="token1">=</span><span class="token1">></span><span class="token2">'cdeca9e8ee6c9522d22e'</span><span class="token3">,</span> <span class="token2">'client_secret'</span><span class="token1">=</span><span class="token1">></span><span class="token2">'e6e767515f87aa45c9a5027f6982f6abf90d0d2b'</span><span class="token3">,</span> <span class="token2">'code'</span><span class="token1">=</span><span class="token1">></span>$_GET<span class="token3">[</span><span class="token2">'code'</span><span class="token3">]</span><span class="token3">,</span> <span class="token3">]</span><span class="token3">;</span> $res<span class="token1">=</span><span class="token4">curl</span><span class="token3">(</span><span class="token2">'https://github.com/login/oauth/access_token'</span><span class="token3">,</span>$data<span class="token3">)</span><span class="token3">;</span> <span class="token4">var_dump</span><span class="token3">(</span>$res<span class="token3">)</span><span class="token3">;</span> <span class="token">//请求</span> $header<span class="token1">=</span><span class="token3">[</span> <span class="token2">'accept'</span><span class="token1">=</span><span class="token1">></span> <span class="token2">'application/json'</span><span class="token3">,</span> <span class="token">//'User-Agent'=> 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36',</span> <span class="token2">'User-Agent'</span><span class="token1">=</span><span class="token1">></span> <span class="token2">'lichihua'</span><span class="token3">,</span> <span class="token2">'Authorization'</span><span class="token1">=</span><span class="token1">></span> <span class="token2">"bearer {$access_token}"</span> <span class="token3">]</span><span class="token3">;</span> <span class="token">//get请求</span> $res<span class="token1">=</span><span class="token4">curl</span><span class="token3">(</span><span class="token2">'https://api.github.com'</span><span class="token3">,</span><span class="token5">null</span><span class="token3">,</span>$header<span class="token3">)</span><span class="token3">;</span> <span class="token4">var_dump</span><span class="token3">(</span>$res<span class="token3">)</span><span class="token3">;</span> ``` ``` 返回结果: ``` <pre class="calibre10">``` <span class="token4">string</span><span class="token3">(</span><span class="token6">78</span><span class="token3">)</span> <span class="token2">"access_token=fe25c09162fc631ccb8b02b03654dd649026c1d2&scope=&token_type=bearer"</span> ``` ``` 上面代码中,GitHub 的令牌接口`https://github.com/login/oauth/access_token`需要提供三个参数。 > - `client_id`:客户端的 ID > - `client_secret`:客户端的密钥 > - `code`:授权码 作为回应,GitHub 会返回令牌`accessToken`。 node例子请看<http://www.ruanyifeng.com/blog/2019/04/github-oauth.html>