
<com.huawei.hms.support.hwid.ui.HuaweiIdAuthButton
android:id="@+id/HuaweiIdAuthButton"//自定义
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
(2) 编写帐号登录功能代码:
private void signInCode() {
mAuthParam = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
.setAuthorizationCode()
.createParams();
mAuthService = AccountAuthManager.getService(AuthWithAuthCodeActivity.this, mAuthParam);
startActivityForResult(mAuthService.getSignInIntent(), REQUEST_SIGN_IN_LOGIN_CODE);
}
在需要的Activity(如AuthWithAuthCodeActivity)中编写如上signInCode()方法代码。代码中.setAuthorizatonCode()表示选择Authorization Code模式请求获取code。
之后在华为帐号登录按钮中绑定点击事件,触发按钮点击事件后执行signInCode()方法即可拉起基于Authorization Code模式的帐号登录授权页面。
(3) 登录授权后处理登录结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Process the sign-in authorization result and obtain an ID token from AuthHuaweiId.
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_SIGN_IN_LOGIN_CODE) {
Task<AuthAccount> authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data);
if (authAccountTask.isSuccessful()) {
// The sign-in is successful, and the user's HUAWEI ID information and Code are obtained.
AuthAccount authAccount = authAccountTask.getResult();
Log.i("AuthWithAuthCodeActivity", "Authorization code:" + authAccount.getAuthorizationCode());
} else {
// The sign-in failed.
Log.e("AuthWithAuthCodeActivity", "sign in failed : " +((ApiException)authAccountTask.getException()).getStatusCode());
}
}
}
当登录授权成功后,通过authAccount.getAuthorizationCode()即可获取到code。
(4) 获取到code后,开发者需将code发送给应用服务器,该部分代码由开发者根据自身设计自行开发。
至此,登录授权功能的客户端代码开发完成。
3、 服务器侧开发:
(1) 接收来自客户端发送的code
该部分代码由开发者根据自身设计自行开发。
(2) 用code换Access Token
应用服务器调用华为帐号服务器对应接口将code换成Access Token、Refresh Token。同时将Access Token、Refresh Token保存在应用服务器。
注:code有效期只有5分钟,且用一次就会失效,失效后需要通知客户端重新获取用户授权。
请求参数:
| 参数名 | 描述 |
| grant_type | OAuth 2.0规范定义的字段,该值固定填“authorization_code”。 |
| code | 客户端发送的授权码 |
| client_id | App ID,在创建应用后由华为开发者联盟为应用分配的唯一标识。查询方法请参见查看应用。 |
| client_secret | App SECRET,在创建应用后由华为开发者联盟为应用分配公钥。查询方法请参见查看应用。 |
| redirect_uri | AppGallery Connect中设置应用服务器的回调地址,用于应用服务器在获取用户授权后获取凭证Access Token。 |
POST /oauth2/v3/token HTTP/1.1
Host: oauth-login.cloud.huawei.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=CF3L7XyCVZi52XMdsUzD7Z6ap0/N2qExcNe0AMqTselTtNd1B4DUwTsQ/23FPZasC8yI29v+N2s2jMT/T2MXiuc+178I/sYuWVoTyqwBaDqVW82KCMqaxbeWBguH4hEENxmDSUIE61Qg5R1F074PiS+qJYnbLI2IBqatS37px8pn5qnuq5oX+UX8XN3/w8HLt4GpakW5Dk1v7hGs&
client_id={app_id}&
client_secret={app_secret}&
redirect_uri=https://www.example.com/redirect_uri
响应参数:
| 参数名 | 描述 |
| access_token | 用户的Access Token。 |
| refresh_token | 如果应用申请帐号服务时,入参中包含access_type=offline,则会返回此参数,该参数用于刷新Access Token。 |
| expires_in | Access Token的过期时间,以秒为单位。默认60分钟过期。 |
| id_token | 如果应用申请帐号服务时,入参scope中包含openid,则会返回此参数(JWT格式数据),包含用户基本帐号、用户邮箱等信息。ID Token的描述信息请参见ID Token验证接口中ID Token描述。 |
| scope | 生成的凭证Access Token中包含的scope。 |
| token_type | 固定返回Bearer,标识返回Access Token的类型。 |
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "CFyJ21sNODl16eV9y2vu3CwQk9DBr32BkOcxxgAd7MZUR5th1giyTk5\/kA+QDAyxou+\/5U2zzBRcf3qgLkkFdtbbC+mM3zFV7xj7CCEMHc5Tw92al0Y=",
"refresh_token": "CF13G0sRaGybtYt7SIyeUILNORtTFwMgz4ao5C7j7vtgLPt6ogmXKjdI8RS\/YlyS71z4DyP6kEMnOrRlmNK0KhdOUNWd+qVLLRsEEHkqRIKpuAkPvL8=",
"expires_in": 3600,
"id_token": "eyJraWQiOiI3YTNlYjRkNTJmMDdhODM0NDU4MmRhOGQ3MWE1MGQ5MDlmNWM0YmRiZTFkNDQ3MjQ2MDNhZTA2NGM0ZTlkZGYyIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoiM0hPdFZYOEdMcG1GSDBWRVlSc1BjdyIsImF1ZCI6IjEwMDczNTE2NyIsInN1YiI6Ik1ERTlYaWFoc3MwaWFFNXU2c09PaEY5Mlhvell0Rkt4bUdtbWlhNGtTaEJ3dklLR2ciLCJhenAiOiIxMDA3MzUxNjciLCJpc3MiOiJodHRwczovL2FjY291bnRzLmh1YXdlaS5jb20",
"scope": "openid profile email",
"token_type": "Bearer"
}
(3) 解析Access Token
获取到Access Token,要对其进行解析鉴权,获取Access Token中包含的union_id、open_id、expire_in、scope等信息。
请求示例:
POST /rest.php?nsp_fmt=JSON&nsp_svc=huawei.oauth2.user.getTokenInfo HTTP/1.1
Host: oauth-api.cloud.huawei.com
Content-Type: application/x-www-form-urlencoded
open_id=OPENID&
access_token=CFwaKaGpgXEj9LlsDKVARTUL7DFkvbAE2a22HYpRx%2F520JO5UvfWqSc6X7XUwf4Pzo5%2FxC8mByagdMPG%2FHeHDBldhW3tYizcw3xXSVwJPWK82C8zPM%3D
其中open_id为固定值“OPENID”。
响应示例:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"union_id": "MDHSI1UnQ9wzGzibtoqicNNnUmJbwhicPzHxxiaVHvMtmNd3xw",
"scope": "https://www.huawei.com/auth/account",
"open_id": "MDFAMzAwMDE3NTAxQGI4ODgzNWRmYjE4ZTI2NGFiaZDE2YjI5ODMwMDM3MDA0QDIxYWY3NzVkZmM1ODk1MWY4NzI4YzFiaNGJkMjE2Y2QyZTUxNzg3NzUzMDcyZTM4ZjkyZTQxYw",
"expire_in": 1123,
"client_id": "300017501"
}
响应参数说明:
| 参数 | 是否必选 | 参数类型 | 描述 |
| client_id | 是 | Long | 应用App ID。 |
| expire_in | 是 | int | Access Token的过期时间,单位为秒。默认为60分钟。 |
| union_id | 否 | string | 用户的union_id,由用户帐号和应用开发者帐号签名而成,需要应用ID包含com.huawei.android.hms.account.getUnionId权限时才会返回。对于同一个用户,同一个开发者帐号下管理的不同应用,UnionId值相同,它是开发者帐号的唯一标识 |
| open_id | 否 | string | 用户的union_id,由用户帐号和应用ID加密生成的,当Access Token为用户级,且入参open_id为OPENID时才返回。同一个用户,不同应用,OpenId值不同,它是用户的唯一标识 |
| scope | 否 | string | 用户授权scope列表,当Access Token为用户级时才返回。 |
POST /oauth2/v3/token HTTP/1.1
Host: oauth-login.cloud.huawei.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&
client_id=12345&
client_secret=bKaZ0VE3EYrXaXCdCe3d2k9few&
refresh_token=CF2Mm03n0aos9iZZ8nIhfyDtoXy74CXeBi50gVVhMpB0IUzlv9ZwizEvTBhVoF820ZPim0JwNR9j2p1qgEQWnIVYZRlp4T6ezMgekUnsHBkvNev5rd2MdfQMLP
响应示例:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "CFyJ4J\/l6wuwcFqYOJG4maq2ca8RAV+g0i+mel6qCV5lvqH0PYtW0+BNwfHWg0AqMnW6ZdBvUgs7ijkxMFh1xVP\/B+vQXz3PWsivkKCuL78XtbLt7vs=",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjExOGRmMjU0YjgzNzE4OWQxYmMyYmU5NjUwYTgyMTEyYzAwZGY1YTQiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI3ODI0NTY2Njc4OTgtc2M0MzE3Y2l0NGEwMjB0NzdrbGdsbWo1ZjA4YWtnMWIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI3ODI0NTY2Njc4OTgtN2NkNGJpYWRkaGVwNGc4cnZic2VlOGtwcDA5Zm1hNzIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDE3MTIxMzkwMzgwNDE2MDc0MTQiLCJlbWFpbCI6Inh1ZXpoZW5odWF0anVAc2l",
"expires_in": 3600,
"scope": "openid profile email",
"token_type": "Bearer"
}
(6) Refresh Token过期后,应用服务器需通知客户端重新申请用户授权,重新获取code,刷新AT和RT
该部分代码由开发者根据自身设计自行开发。
(7) 使用Access Token去华为帐号服务器获取用户信息
应用已经获取到Access Token并已申请帐号开放信息对应权限后,应用需要获取帐号用户名称、头像、手机号码、年龄等信息。
请求示例:
POST /rest.php?nsp_svc=GOpen.User.getInfo HTTP/1.1
Host: account.cloud.huawei.com
Content-Type: application/x-www-form-urlencoded
access_token=CV46i%2BFdM3LEja3z7%2BjOGu27mNBsKwBznSoe4MMfKmNw4aGNLisoCKYgbSOJIVhWLOIIVr0nMwVXFu9AvFGKoJmGk%2FUZdMDytv2bsamauePs3FG6ZkU%3D&
getNickName=0
响应示例:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"displayName":"182******74",
"openID":"MDFAMTAxMDA1MTg1QGFlMzM0OWIyOGY0MzNiaNjI1MDRiaNTI5ODAxYTA3MDhkQDU1MDA4ZTZmNTA2ZTE4ZTg0Yzc2YTlmNGVmN2E1ZjY1OTg4NWRiaN2QxMzQyMDUzNGMzNTU0YWQ3",
"headPictureURL":"https://upfile-drcn.platform.hicloud.com/FileServer/image/b.0150086000130905592.20180407082531.08157939582468778294625163020035.1000.9C3EE92B95EFEF4CAC263604A15953F32C7BC9E8A47D52B774511F75EF34C0D4.jpg"
}
响应参数说明:
| 参数 | 是否必选 | 参数类型 | 描述 |
| openID | 是 | string | 用户openID。 |
| displayName | 是 | string | getNickName为0或不传时,按照匿名化帐号、昵称的先后顺序返回。 |
| getNickName为1时,按照昵称、匿名化帐号的先后顺序返回。 | |||
| headPictureURL | 否 | string | 用户头像。 |
| mobileNumber | 否 | string | 用户手机号。 |
| srvNationalCode | 否 | string | 用户服务地国家。 |
| nationalCode | 否 | string | 用户注册地。 |
| birthDate | 否 | string | 生日。 |
| ageGroupFlag | 否 | Int | 年龄段。 |
| -1:年龄未知(没输入生日) 。 | |||
| 0:成人。 | |||
| 1:未成人,介于儿童和成人之间。 | |||
| 2:儿童。 | |||
| 否 | string | 用户邮箱。 |
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最