oauth免登开发

本章主要介绍部署在边缘集群托管的应用,实现免登及用户信息获取相关流程。

1.边缘应用OAuth免登介绍

1.1 OAuth免登调用流程

  1. 系统应用环境变量中获取访问域名。System.getenv(“iot.hosting.api.domain”)。

  2. 应用跳转IoT oauth验证地址,同时携带认证后跳转的callback地址。

  3. IoT认证后,携带授权码oauthcode跳转第2步callback的地址。

  4. 应用获取到oauthcode后可以换取accesscode,并通过accesscode获取到用户的完整信息。

免登流程

2.实操效果展示

2.1 部署组件

单击组件管理>访问入口 复制IP+端口号,打开新的浏览器页面进行访问,如下图所示:

部署组件

2.2 登录边缘控制台。

使用“超级账户iotedgeadmin”登录“集群控制台”,用户名与密码一致,首次登录强制修改密码,此连接为内网地址,请保证电脑可以正常连接至内网,如下图所示:

边缘控制台

2.3 查看部署应用

登录成功后,可单击部署应用的应用卡片,进入应用详情,如下图所示:

查看部署应用

2.4 点击应用进行免登

点击部署的应用,直接跳转到应用内部,验证免登,如下图所示:

图片

3.开发API

3.1 获取应用入口地址

授权类型

APPSIGN

协议

HTTP

请求方法

get

域名(环境变量中获取)

System.getenv(“iot.hosting.api.domain”)

路径

/api/console/app/get

入参名称

数据类型

是否必须

入参示例

入参描述

appKey

字符串

213124133

appkey

port

int

80443

请求的服务端口

出参名称

数据类型

出参描述

code

整形

响应码, 200: 成功

message

字符串

错误消息

localizedMsg

字符串

本地语言错误消息

data

长整型

响应结果 返回为app的相关应用url

http://30.42.82.42:32187/api/console/app/get?appKey=28135051
   /**
    * 获取环境变量和回调的url
    * @return
    */
//iot.hosting.api.schema----是请求协议格式http
private
static
final
StringAPI_GATEWAY_SCHEMA=System.getenv("iot.hosting.api.schema");
//iot.hosting.api.domain--是跳转路径的回调ip地址
private
static
final
StringAPI_GATEWAY_DOMAIN=System.getenv("iot.hosting.api.domain");
//iot.hosting.api.port----是请求端口
private
static
final
StringAPI_GATEWAY_SCHEMA=System.getenv("iot.hosting.api.port");
// iot.hosting.appKey----是请求的appkey
private
static
final
StringAPI_GATEWAY_SCHEMA=System.getenv(" iot.hosting.appKey");
//PATH_APP_GET是请求应用app的响应路径
private
static
final
StringPATH_APP_GET="/api/console/app/get";


@Override
   
public
StringgetAppIndex(){
       RequestBuilderbuilder=RequestBuilder.create(METHOD_GET);
       Map<String,String>queryParams=Maps.newHashMap();
       queryParams.put(PARAM_APP_KEY,appKey);


       builder.setUri(HttpUtils.buildUrl(schema,apiGatewayDomain,apiGatewayPort,PATH_APP_GET,queryParams));


       IoTxResult<AppDTO>result=httpProxy.invoke(
               (HttpRequestBase)builder.build(),
               
new
TypeReference<IoTxResult<AppDTO>>(){
               }
       );


       logger.info("path={}; params={}; result={}",PATH_APP_GET,JSON.toJSONString(queryParams),JSON.toJSONString(result));


       Assert.assertSuccess(result);
       AppDTOapp=result.getData();
return
app.getLoginUrl();
   }

{
 {
   "code":200,
   "data":{
     "aliyunPk":"101248722030****",
     "appKey":"28135***",
     "appMeta":{
       "logoUrl":"http://192.168.11.130:32628/index/28135***",
       "name":"oauth2边缘托管",
       "subVersionId":"1.0",
       "uuid":"937aaa**************0b0d1629c6",
       "versionUuid":"9ff097*************f1d14ce56"
     },
     "appSecret":"NGNiOW*******************IyNTg2MzlhY2Q=",
     "clusterId":"bbeba04d880d49dc80bf83632619341c",
     "configName":"oauth2边缘托管",
     "configUuid":"a7b996c*************d81b88ea",
     "configVersionUuid":"8e43f4d************af079df8bb",
     "loginUrl":"http://192.168.11.130:30313/index",//-----应用登录url
     "name":"Oauth2演示",
     "oauth":{
       "path":"/index",
       "port":8080,
       "protocol":"",
       "serviceName":"edge",
       "serviceUuid":""
     },
     "type":"GENERAL_APP",
     "uuid":"731082ac0c**************c915b8a6f"
   },
   "message":"success"
 }
}

3.2 获取API网关地址

授权类型

APPSIGN

协议

HTTP

请求方法

get

域名(环境变量中获取)

System.getenv(“iot.hosting.api.domain”)

路径

/api/console/host/account

入参名称

数据类型

是否必须

入参示例

入参描述

chema

字符串

http

请求协议

ports

int

80443

请求的服务端口

url

字符型

/api/console/host/account

请求url

host

字符型

30.42.82.42:32187

请求host

出参名称

数据类型

出参描述

code

整形

响应码, 200: 成功

message

字符串

错误消息

localizedMsg

字符串

本地语言错误消息

data

长整型

响应结果

 http://30.42.82.42:32187/api/console/host/account
 /**
    *
    * /api/console/host/account
    * @param path
    * @return
    */
   @Override
   
public
URI getURI(Stringpath){
       RequestBuilderbuilder=RequestBuilder.create(METHOD_GET);
       Map<String,String>queryParams=Maps.newHashMap();
       builder.setUri(HttpUtils.buildUrl(schema,apiGatewayDomain,apiGatewayPort,path,queryParams));
       logger.info("RequestBuilder请求url");
       IoTxResult<String>result=httpProxy.invoke(
               (HttpRequestBase)builder.build(),
               
new
TypeReference<IoTxResult<String>>(){


               }
       );
       logger.info("path={}; params={}; result={}",path,JSON.toJSONString(queryParams),JSON.toJSONString(result));
       Assert.assertSuccess(result);
       
try
{
           
return
new
URI(result.getData());
       }
catch
(URISyntaxExceptione){
           
throw
new
RuntimeException(e);
       }
   }

{
   "code":200,
   "data":{
       "oauth":{
       "path":"/index",
       "port":32187,
       "host":30.42.82.42
       "protocol":"",
       "serviceName":"edge",
       "serviceUuid":""
     },
     "type":"GENERAL_APP",
     "uuid":"731082ac0c***********c915b8a6f"
   },
   "message":"success"
 }

3.3 发起免登验证

授权类型

APPSIGN

协议

HTTP

请求方法

get

域名(环境变量中获取)

System.getenv(“iot.hosting.api.domain”)

路径

/oauth2/auth

入参名称

数据类型

是否必须

入参示例

入参描述

client_id

String

28135051

应用的appkey

redirect_uri

String

http://30.42.82.42:32187/index

OAuth认证通过后的重定向应用的URI,包含完整的域名

response_type

String

code

返回类型。根据OAuth 2.0标准,目前支持设置此参数的取值为code

state

String

28135051

应用的appkey携带项

scope

String

空格分隔的OAuth范围列表。如不指定此参数取值,则默认为应用注册的全部OAuth范围,加上scopid

出参名称

数据类型

出参描述

code

整形

响应码, 200: 成功

message

字符串

错误消息

localizedMsg

字符串

本地语言错误消息

data

长整型

响应结果

http://30.42.82.42:32187/oauth2/auth?
redirect_uri=http://30.42.82.42:32187/index&
client_id=28135051&state=28135051&
response_type=code





   /**
    *获取免登url和code
    * @param appKey
    * @param redirectUri
    * @return
    */
   
public
StringgetLoginRedirectUrl(StringappKey,StringredirectUri){
       Map<String,String>queryParams=Maps.newHashMap();
       queryParams.put(PARAM_CLIENT_ID,appKey);
       queryParams.put(PARAM_REDIRECT_URI,redirectUri);
       queryParams.put(PARAM_RESPONSE_TYPE,"code");

 URI accountUri=getAccountUri();


       
return
HttpUtils.buildUrl(
               schema,
               accountUri.getHost(),
               accountUri.getPort(),
               PATH_LOGIN,
               queryParams).toASCIIString();
   }


返回示例

http://30.42.82.42:32187/index?code=64a67ee15534defea7ad0d0535189b24&state=28135051

3.4 换取accessToken

授权类型

ANONYMOUS

协议

HTTP

请求方法

post

域名(环境变量中获取)

System.getenv(“iot.hosting.api.domain”)

路径

/user/oauth2/token/get

入参名称

数据类型

是否必须

入参描述

code

字符串

初始请求中获取的授权码

grant_type

字符串

根据OAuth 2.0标准, 取值为authorization_code

redirect_uri

字符型

初始authorization请求中设置的redirect_uri参数

client_id

字符型

应用的appkey

出参名称

数据类型

出参描述

code

整形

响应码, 200: 成功

message

字符串

错误消息

localizedMsg

字符串

本地语言错误消息

data

长整型

响应结果

/**
    * 根据code获取到token
    * @param appKey
    * @param oauthCode
    * @return
    */
   
public
StringgetAccessTokenByOauthCode(StringappKey,StringoauthCode){
       RequestBuilderbuilder=RequestBuilder.create(METHOD_GET);


       Map<String,String>queryParams=Maps.newHashMap();
       queryParams.put(PARAM_CODE,oauthCode);
       queryParams.put(PARAM_GRANT_TYPE,"authorization_code");
       queryParams.put(PARAM_CLIENT_ID,appKey);


       URI accountUri=getAccountUri();
builder.setUri(HttpUtils.buildUrl(accountUri.getScheme(),accountUri.getHost(),accountUri.getPort(),PATH_GET_ACCESS_TOKEN_BY_OAUTH_CODE,queryParams));


       IoTxResult<AccessTokenDTO>result=httpProxy.invoke(
               (HttpRequestBase)builder.build(),
               
new
TypeReference<IoTxResult<AccessTokenDTO>>(){
               }
       );


       PROXY_LOGGER.info("path={}; params={}; result={}",PATH_GET_ACCESS_TOKEN_BY_OAUTH_CODE,JSON.toJSONString(queryParams),JSON.toJSONString(result));


       Assert.assertSuccess(result);


       AccessTokenDTOaccessTokenDTO=result.getData();
       Assert.assertNotNull(accessTokenDTO,"get accessToken failed");
return
accessTokenDTO.getAccessToken();
  }

{
   "code":200,
   "data":{
       "access_token":"agasdfagdsafasdf",
       "expired_time":21232,
       "refresh_token":"asdgadgasfadsaf",
       "token_type":"Bearer",
       "open_id":"gasdfasdfasdf"
   },
   "id":"246da69e-40ad-4f44-955e-ac880f9867d7"
}

3.5 获取用户信息

授权类型

ANONYMOUS

协议

HTTP

请求方法

post

域名(环境变量中获取)

System.getenv(“iot.hosting.api.domain”)

路径

/user/oauth2/userinfo/get

入参名称

数据类型

是否必须

入参示例

入参描述

access_token

String

3123******wq

访问令牌

出参名称

数据类型

出参描述

code

整形

响应码, 200: 成功

message

字符串

错误消息

localizedMsg

字符串

本地语言错误消息

data

长整型

响应结果

 /**
    * 根据token获取用户信息
    * @param accessToken
    * @return
    */
   
public
UserInfoDTOgetUserInfoByAccessToken(StringaccessToken){
       RequestBuilderbuilder=RequestBuilder.create(METHOD_GET);


       Map<String,String>queryParams=Maps.newHashMap();
       queryParams.put(PARAM_ACCESS_TOKEN,accessToken);


       URI accountUri=getAccountUri();
       builder.setUri(HttpUtils.buildUrl(accountUri.getScheme(),accountUri.getHost(),accountUri.getPort(),PATH_GET_USER_INFO_BY_ACCESS_TOKEN,queryParams));

 IoTxResult<UserInfoDTO>result=httpProxy.invoke(
               (HttpRequestBase)builder.build(),
               
new
TypeReference<IoTxResult<UserInfoDTO>>(){
               }
       );


       PROXY_LOGGER.info("path={}; params={}; result={}",PATH_GET_USER_INFO_BY_ACCESS_TOKEN,JSON.toJSONString(queryParams),JSON.toJSONString(result));


       Assert.assertSuccess(result);

UserInfoDTOuserInfoDTO=result.getData();
       Assert.assertNotNull(userInfoDTO,"get userInfo failed");


       
return
userInfoDTO;
   }

"id":"246da69e-40ad-4f44-955e-ac880f9867d7",
   "code":200,
   "message":
null
,
   "localizedMsg":
null
,
   "data":{
       "open_id":"eaef***************0d58d1fd5",
       "name":"test",
       "phone":"***********",
       "tenant_open_id":"1c8c23f0***********372b781f0d",
       "tenant_name":"test"
   }

3.6 Token有效性判断

授权类型

ANONYMOUS

协议

HTTP

请求方法

post

域名(环境变量中获取)

System.getenv(“iot.hosting.api.domain”)

路径

/user/oauth2/accesstoken/check

入参名称

数据类型

是否必须

入参示例

入参描述

access_token

String

3123qwqrqwq

访问令牌

出参名称

数据类型

出参描述

code

整形

响应码, 200: 成功

message

字符串

错误消息

localizedMsg

字符串

本地语言错误消息

data

长整型

响应结果

 /**
    * token登录有效期检查
    * @param token
    * @return
    */
   
public
boolean
checkLogin(Stringtoken){
       RequestBuilderbuilder=RequestBuilder.create(METHOD_GET);


       Map<String,String>queryParams=Maps.newHashMap();
       queryParams.put(PARAM_ACCESS_TOKEN,token);


       URI accountUri=getAccountUri();
       builder.setUri(HttpUtils.buildUrl(accountUri.getScheme(),accountUri.getHost(),accountUri.getPort(),PATH_LOGINCHECK,queryParams));


       IoTxResult<Boolean>result=httpProxy.invoke(
               (HttpRequestBase)builder.build(),
               
new
TypeReference<IoTxResult<Boolean>>(){
               }
       );


       PROXY_LOGGER.info("path={}; params={}; result={}",PATH_LOGINCHECK,JSON.toJSONString(queryParams),JSON.toJSONString(result));


       Assert.assertSuccess(result);

return
result.getData();
   }

返回示例

{
   "code":200,
   "data":{
       "result":
true
   },
}