正文
如果一个应用中插入另一个应用H5的服务,怎么解决认证的问题?换个说法:用户如何从原应用中登录一个H5新应用。
整体架构就是,原应用生成 H5应用入口图标,用户点击 H5应用入口图标 把 用户ID 和 认证信息 带入H5应用, H5应用 向 原应用后端 确认 认证信息 是否正确以完成 用户ID 的登陆,认证登录成功后, 用户在H5应用中进行操作交互,H5应用与原应用后端进行信息交互。
新应用需要确认入口应用是可信的:入口应用带一个认证字段进入新应用,新应用带着这个认证字段去入口应用确认服务。
我们可以对一个数组json后hash_hmac生成token,把token加入数组,然后对这个数组json后base64编码。
先准备可用于URL传递的base64编码方法:
function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function base64url_decode($data) {
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}
生成过程如下:
$arr = [
"user_id" => 1221,
"app_id" => 342156,
"time" => 1629958838
];
$app_key = "94a08da1fecbb6e8b46990538c7b50b2";
// 生成sign
$sign = hash_hmac('sha256', json_encode($arr), $app_key);
$arr = array_merge($arr, ["sign" => $sign]);
$str = json_encode($arr);
$str_url = base64url_encode($str);
认证过程如下:
$str_url = "eyJ1c2VyX2lkIjoxMjIxLCJhcHBfaWQiOjM0MjE1NiwidGltZSI6MTYyOTk1ODgzOCwic2lnbiI6ImVhMjU0MmJlNmVmOWQxNTZlNDMwOWFlOWU4ZTNhODIwNTZiNjI2MjExOWI2NzNlNjVmOGM2OWY4NjBlOWY4ZDIifQ";
$str = base64url_decode($str_url);
$arr = json_decode($str, true);
$sign = $arr["sign"];
unset($arr["sign"]);
if (hash_hmac('sha256', json_encode($arr), $app_key) != $sign) {
echo "认证失败";
}
URL 函数
base64_decode — 对使用 MIME base64 编码的数据进行解码
base64_encode — 使用 MIME base64 对数据进行编码
rawurldecode — 对已编码的 URL 字符串进行解码
rawurlencode — 按照 RFC 3986 对 URL 进行编码
urldecode — 解码已编码的 URL 字符串
urlencode — 编码 URL 字符串
http_build_query — 生成 URL-encode 之后的请求字符串
parse_url — 解析 URL,返回其组成部分
get_headers — 取得服务器响应一个 HTTP 请求所发送的所有标头
get_meta_tags — 从一个文件中提取所有的 meta 标签 content 属性,返回一个数组
htmlentities() — 将字符转换为 HTML 转义字符, ' -> ' , < -> < , > -> >
html_entity_decode() — 解码(反向操作)
htmlspecialchars — 将特殊字符转换为 HTML 实体,& -> & , " -> " , ' -> ' , < -> < , > -> >
htmlspecialchars_decode— 将特殊的 HTML 实体转换回普通字符
示例:
$uri="my test.php?name=ståle&car=saab&sex=男";
$base64_uri = base64_encode($uri); // bXkgdGVzdC5waHA/bmFtZT1zdMOlbGUmY2FyPXNhYWImc2V4PeeUtw==
$rawurl_uri = rawurlencode($uri); // my%20test.php%3Fname%3Dst%C3%A5le%26car%3Dsaab%26sex%3D%E7%94%B7
$urlencode_uri = urlencode($uri); // my+test.php%3Fname%3Dst%C3%A5le%26car%3Dsaab%26sex%3D%E7%94%B7
$arr = array('foo'=>'bar',
'num1',
'num2',
'baz'=>'boom',
'cow'=>'milk'
);
$str = http_build_query($arr);
// foo=bar&0=num1&1=num2&baz=boom&cow=milk
$str = http_build_query($arr, 'var_', '&');
// foo=bar&var_0=num1&var_1=num2&baz=boom&cow=milk
print_r(parse_url("http://www.abc.com/my test.php?name=ståle&car=saab&sex=男"));
// 输出
Array
(
[scheme] => http
[host] => www.abc.com
[path] => /my test.php
[query] => name=ståle&car=saab&sex=男
)
$url = 'http://www.example.com';
print_r(get_headers($url));
print_r(get_headers($url, 1));
// 输出
Array
(
[0] => HTTP/1.1 200 OK
[1] => Date: Sat, 29 May 2004 12:28:13 GMT
[2] => Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
[3] => Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
[4] => ETag: "3f80f-1b6-3e1cb03b"
[5] => Accept-Ranges: bytes
[6] => Content-Length: 438
[7] => Connection: close
[8] => Content-Type: text/html
)
Array
(
[0] => HTTP/1.1 200 OK
[Date] => Sat, 29 May 2004 12:28:14 GMT
[Server] => Apache/1.3.27 (Unix) (Red-Hat/Linux)
[Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT
[ETag] => "3f80f-1b6-3e1cb03b"
[Accept-Ranges] => bytes
[Content-Length] => 438
[Connection] => close
[Content-Type] => text/html
)
参考资料
PHP 手册 函数参考 其它基本扩展 URLs URL 函数 https://www.php.net/manual/zh/ref.url.php
PHP 手册 函数参考 加密扩展 哈希信息摘要框架 https://www.php.net/manual/zh/book.hash.php
PHP 手册 函数参考 文本处理 字符串 字符串 函数 htmlspecialchars https://www.php.net/htmlspecialchars/