写点什么

华为账号一键登录

作者:flfljh
  • 2024-11-05
    湖南
  • 本文字数:3410 字

    阅读完需:约 11 分钟

华为账号一键登录



服务端实现华为账号一键登录,需通过前端上传的授权码,在服务器获取华为用户信息实现登录业务逻辑。

一、获取用户凭证 access_token

使用 POST 方式对 api <https://oauth-login.cloud.huawei.com/oauth2/v3/token> 发起请求参数为华为后台提供的应用 idclient_id与密钥client_secret 客户端上传的授权码codegrant_type参数固定为 authorization_code


注意请求头信息 Content-Type 为application/x-www-form-urlencoded


php 请求示例


引用 guzzlehttp 包


// 使用guzzlehttpcomposer require guzzlehttp/guzzle
复制代码


发起 POST 请求,成功获取 access_token 后应该在过期时间内缓存起来,避免重复请求消耗接口请求次数,增加失败情况后的重试机制。


use GuzzleHttp\Client;
$code = '客户端上传的授权码';$clientId = '应用id';$secret = '应用密钥';
$options = [ 'http_errors' => false, 'timeout' => 5, 'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'], 'form_params' => [ 'client_id' => $clientId, 'client_secret' => $secret, 'code' => $code, 'grant_type' => 'authorization_code' ]];
try { $guzzle = new Client(); $response = $guzzle->post('https://oauth-login.cloud.huawei.com/oauth2/v3/token', $options); $result = json_decode($response->getBody()->getContents(), true);} catch (Exception $e) { // 异常处理}
// access_toke进行缓存,有效期为1小时,提供失败刷新机制
复制代码


成功响应结果


HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8
{ "access_token": "<Access Token>", "refresh_token": "<Refresh Token>", "expires_in": 3600, "id_token": "<ID Token>", "scope": "openid profile email", "token_type": "Bearer"}
复制代码


失败响应结果


HTTP/1.1 400 Bad RequestContent-Type: application/json;charset=UTF-8
{ "sub_error": 12304, "error_description": "invalid client_secret", "error": 1101}
复制代码

二、获取用户信息

使用 POST 方式对 api <https://account.cloud.huawei.com/rest.php?nsp_svc=GOpen.User.getInfo>发起请求,参数为上一步获取的access_token,成功获取到用户信息后,使用授权用户的手机号或 unionid 进行应用登录。


注意请求头信息 Content-Type 为application/x-www-form-urlencoded


请求示例


$options = [    'http_errors' => false,    'timeout' => 5,    'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],    'form_params' => [        'access_token' => $token,    ]];
try { $guzzle = new Client(); $response = $guzzle->post('https://account.cloud.huawei.com/rest.php?nsp_svc=GOpen.User.getInfo', $options); $result = json_decode($response->getBody()->getContents(), true);} catch (Exception $e) { // 异常处理}
// 使用手机号进行注册或登录逻辑$mobile = $result['mobileNumber']
复制代码


成功响应结果


HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8
{ "displayName": "182******74", "displayNameFlag": 1, "mobileNumber": "18211111174", "openID": "MDFAMTAxMDA1MTg1QGFlMzM0OWIyOGY0*****MDRiaNTI5ODAxYTA3MDh*****A4ZTZmNTA2ZTE4ZT*****lmNGVmN2E1ZjY1OTg4NWRiaN2QxMzQy*****TU0YWQ3", "unionID": "MDF9pBd6xxxxA8iaG4ZNPTw*****3fyXzG9WgUcmY8XibBvQ", "headPictureURL": "https://upfile-*****.jpg"}
复制代码


失败响应结果


HTTP/1.1 200 OKContent-Type: application/json;charset=UTF-8
{ "error": "session timeout"}
复制代码

鸿蒙推送



客户端上报 token, 使用 token 进行业务消息推送到客户端。

一、生成服务账号的鉴权令牌

令牌为 JWT 格式,包含Header(头部)Payload(负载)Signature(签名)三部分组成。


1.创建服务密钥文件(需要在华为开发者联盟上创建并下载推送服务 API 的服务账号密钥文件)


{    "project_id": "*****",    "key_id": "*****",    "private_key": "-----BEGIN PRIVATE KEY-----\nMIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCKw6kJKtCh7qmMvp1u1dI27z2TKZrPOzHbQaXO/Eez0AWZ2EN+ouF496R3pfo7fQXC1XOT/YTbVC4DNZwWSMA54fu3/AOCY9Zzyi46OK*****==\n-----END PRIVATE KEY-----\n",    "sub_account": "*****",    "auth_uri": "https://oauth-login.cloud.huawei.com/oauth2/v3/authorize",    "token_uri": "https://oauth-login.cloud.huawei.com/oauth2/v3/token",    "auth_provider_cert_uri": "https://oauth-login.cloud.huawei.com/oauth2/v3/certs",    "client_cert_uri": "https://oauth-login.cloud.huawei.com/oauth2/v3/x509?client_id=*****"}
复制代码


2.生成 JWT Header 信息,kid 为账号密钥文件中的key_id


{  "kid": "*****",  "typ": "JWT",  "alg": "PS256"}
复制代码


3.生成 JWT Payload 数据,iss 为服务账号密钥文件中sub_account字段,iat为当前时间戳 expiat晚 3600 秒


{  "aud": "https://oauth-login.cloud.huawei.com/oauth2/v3/token",  "iss": "*****",  "exp": 1581410664,  "iat": 1581407064}
复制代码


4.生成 JWT Signature 签名


将完成 BASE64 编码后的 Header 字符串与 Payload 字符串,通过“.”进行连接,通过服务密钥文件中的private_key使用 SHA256withRSA/PSS 算法对拼接的字符串签名。


php 代码示例


$header = base64UrlEncode(json_encode([    'kid' => '<key_id>',    'typ' => 'JWT',    'alg' => 'PS256']));$payload = base64UrlEncode(json_encode([    'aud' => 'https://oauth-login.cloud.huawei.com/oauth2/v3/token',    'iss' => '<sub_account>',    'exp' => time() + 3600,    'iat' => time()]));
// Load the RSA private key$privateKeyResource = openssl_pkey_get_private($privateKey);if (!$privateKeyResource) { die("Failed to load private key.");}
$unsignedToken = $header . '.' . $payload;
// 签名openssl_sign($unsignedToken, $signature, $privateKeyResource, 'sha256WithRSAEncryption');
// 拼接jwt$token = $unsignedToken . '.' . $signature;


// base64编码function base64UrlEncode($data){ return \str_replace('=', '', \strtr(\base64_encode($data), '+/', '-_'));}
复制代码

二、消息推送请求

使用 POST 方式对 api https://push-api.cloud.huawei.com/v3/[projectId]/messages:send发起请求,[projectId]在请求中替换实际项目 id,增加头信息使用上一步获取的jwt鉴权令牌,并进行拼接,格式为:Authorization:Bearer <token>


注意请求头信息 Content-Type 为application/json


推送消息内容格式具体参与官方文档与示例:[官方文档] [示例]


php 代码示例


$jwt = '<jwt令牌>';$pushType = 0 //消息类型 0:Alert消息(通知消息、授权订阅消息)1:卡片刷新消息 2:通知扩展消息 6:后台消息 7:实况窗消息 10:应用内通话消息$projectId = "<项目ID>"$token = "<用户token>";
// 推送内容$payload = [ 'notification' => [ 'category' => 'MARKETING', 'title' => '消息标题', 'body' => '消息描述', 'clickAction' => ['actionType' => $actType] ]];
// target最大支持10000个token$body = [ 'payload' => $payload, 'target' => [ 'token' => [$token] ]];
$options = [ 'headers' => [ 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $jwt, 'push-type' => $type ], 'http_errors' => false, 'timeout' => 5.0, 'json' => $body,];
try { $client = new Client(); $resp = $client->post(sprintf('https://push-api.cloud.huawei.com/v3/%s/messages:send', $projectId), $options); if ($resp->getStatusCode() != 200) { return; } // 响应结果 $content = json_decode($resp->getBody()->getContents(), true); if ($content['code'] != '80000000') { //失败情况处理 }catch (Exception $e) { // 异常处理}
复制代码


发布于: 刚刚阅读数: 4
用户头像

flfljh

关注

还未添加个人签名 2024-10-29 加入

还未添加个人简介

评论

发布
暂无评论
华为账号一键登录_鸿蒙_flfljh_InfoQ写作社区