全部产品

OAuth对接实践 - Linux应用

更新时间:2019-12-31 11:14:18

本章结合Demo代码,介绍单租户托管型应用免登及用户信息获取的相关流程。开发之前,请务必参考详细的对接专题文档,以便对OAuth对接有全面的了解。
注:本Demo代码,基于Springboot框架开发,下载链接请参考文章底部的“示例Demo”。

1 获取oauthcode

根据环境变量获取到的appkey与请求头获取跳转地址拼接鉴权URL并访问该URL。示例代码如下:

  1. //-----要先进行部署上线获取到appkey和appSecret-------//
  2. private static Logger logger = LoggerFactory.getLogger(Oauth2Controller.class);
  3. /**
  4. * 注意: //-----要先进行部署上线获取到appkey和appSecret-------
  5. * //环境变量获取appkey和appSecret也可能为iot_hosting_appKey和iot_hosting_appSecret;需要和终端查看的保持一致
  6. */
  7. public static final String OAUTH_CLIENT_ID = System.getenv("iot.hosting.appKey");
  8. public static final String OAUTH_CLIENT_SECRET = System.getenv("iot.hosting.appSecret");
  9. private static String response_type = "code";
  10. private static String redirectUrlPage = "\"http://\" + request.getHeader(\"Host\")";//是跳转自己系统应用的访问入口,可通过请求头获取
  11. public static final String OAUTH_CLIENT_AUTHORIZE = System.getenv("iot.host.oauth.domain");
  12. public static final String REDIRECT_URL = System.getenv("iot.hosting.api.domain");
  13. /**
  14. * 第一次请求:返回为callback地址和code值
  15. * <p>
  16. * 拼接示例:https://account.iot.aliyun.com/oauth2/auth?&&redirect_uri=http://47.95.191.3:8***&client_id=2768****&response_type=code
  17. *
  18. * @throws Exception
  19. */
  20. @RequestMapping("/redirectToRequestAuthorizationCodeURL")
  21. public String redirectToRequestAuthorizationCodeURL(HttpServletRequest request) throws Exception {
  22. // accessTokenRequest 是用来描述请求对象的,描述了请求地址,和请求参数
  23. OAuthClientRequest accessTokenRequest = OAuthClientRequest.authorizationLocation(OAUTH_CLIENT_AUTHORIZE)
  24. .setResponseType(response_type).setClientId(OAUTH_CLIENT_ID).setRedirectURI(redirectUrlPage).buildQueryMessage();
  25. return "redirect:" + accessTokenRequest.getLocationUri();
  26. }

鉴权URL会连接到IoT平台进行相关验证,成功后会根据{ redirectUrl }中的地址进行跳转并携带code参数。该参数就是我们后续用到OAuthCode参数。示例代码如下:

  1. http://39.97.129.***:****/?code=b27baa5b367baf46d6625989cadc87e7

⚠️注意格式为:请求头(http)+外部暴露的端口IP+请求appkey后获取的返回code值。

端口

另外,一般我们的应用入口是登陆页面与OAuth免登中的回调跳转地址共用一个地址,所以可以通过是否有code参数判断是否是OAuth回调跳转,原有的登陆页面也应该保留。

  1. /**
  2. * 返回授权码
  3. *
  4. * @param request
  5. * @return
  6. * @throws Exception
  7. */
  8. @RequestMapping("/getAuthorizationCode")
  9. public Object getAuthorizationCode(HttpServletRequest request) throws Exception {
  10. OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);
  11. String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);
  12. String authorizationCode = oauthRequest.getParam(OAuth.OAUTH_CODE);
  13. //把 state 写到一个 重定向的响应
  14. OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_FOUND);
  15. builder.setCode(authorizationCode);
  16. OAuthResponse response = builder.location(redirectURI).buildQueryMessage();
  17. return "redirect:" + response.getLocationUri();
  18. }

2 获取access_token

在调用getAccessTokenByAuthCode接口获取access_token。示例代码如下:

  1. /**
  2. * 发送请求返回
  3. * 根据authcode来获取accesstoken
  4. * <p>
  5. * api: getAccessTokenByAuthCode
  6. *
  7. * @param request
  8. * @return
  9. * @throws Exception
  10. */
  11. @RequestMapping("/getAccessTokenByAuthCode")
  12. public Object getAccessTokenByAuthCode(HttpServletRequest request) throws Exception {
  13. String code = "835d5af7a835239a9566a1f9078d83a0";//测试使用 request.getHeader("code")
  14. IoTApiClientBuilderParams IoTApiClientBuilderParams =
  15. new IoTApiClientBuilderParams();
  16. IoTApiClientBuilderParams.setAppKey("2776****");
  17. IoTApiClientBuilderParams.setAppSecret("9ca6b2b12aa35b4549659b9****");
  18. SyncApiClient syncClient = new SyncApiClient(IoTApiClientBuilderParams);
  19. IoTApiRequest request1 = new IoTApiRequest();
  20. //设置api的版本
  21. request1.setApiVer("1.0.1");
  22. request1.putParam("code", code);
  23. request1.putParam("grant_type", "code");
  24. request1.putParam("redirect_uri", "http://39.97.129.***:****");
  25. request1.putParam("client_id", "2776****");
  26. //请求参数域名、path、request
  27. ApiResponse response = syncClient.postBody(REDIRECT_URL,
  28. "/user/oauth2/token/get", request1, true);
  29. System.out.println("response code = " + response.getCode()
  30. + " response = " + new String(response.getBody(), "UTF-8"));
  31. return "redirect:requestResourcePage?accessToken=" + response.getMessage();
  32. }

3 获取用户信息

在调用getUserInfoByAccessToken接口获取access_token。示例代码如下:

  1. /**
  2. * 发送请求返回
  3. * oauth2的授权,根据accesstoken获取用户信息
  4. * <p>
  5. * api: getUserInfoByAccessToken
  6. *
  7. * @param
  8. * @return
  9. * @throws Exception
  10. */
  11. @RequestMapping("/getUserInfoByAccessToken")
  12. public Object getUserInfoByAccessToken() throws Exception {
  13. String token = "e171cd3d7c71ed189afb8ef5950adb58";
  14. IoTApiClientBuilderParams IoTApiClientBuilderParams =
  15. new IoTApiClientBuilderParams();
  16. IoTApiClientBuilderParams.setAppKey("2776****");
  17. IoTApiClientBuilderParams.setAppSecret("9ca6b2b12aa35b4549659b9****");
  18. SyncApiClient syncClient = new SyncApiClient(IoTApiClientBuilderParams);
  19. IoTApiRequest request1 = new IoTApiRequest();
  20. //设置api的版本
  21. request1.setApiVer("1.0.2");
  22. request1.putParam("access_token", token);
  23. //请求参数域名、path、request
  24. ApiResponse response = syncClient.postBody(REDIRECT_URL,
  25. "/user/oauth2/userinfo/get", request1, true);
  26. System.out.println("response code = " + response.getCode()
  27. + " response = " + new String(response.getBody(), "UTF-8"));
  28. return "redirect:requestResourcePage?userInfo=" + response.getMessage();
  29. }

4 实现免登

按照上面操作完成后,系统会按照这个逻辑判断用户是否需要免登,我们拿到了IoT平台用户的相关信息,在系统应用中就可以判断该用户是否存在,是否是第一次登入系统等,来实现免登逻辑:
a、如果用户是首次登陆,则可以根据获取到的IoT用户信息在系统内创建账号密码与初始化账户相关的信息。
b、如果用户是首次登陆且需要收集用户额外的信息,比如所属企业信息,还可以展示一个收集信息的页面,收集信息后再创建用户账户信息。
c、如果用户是首次登陆,可以创建随机的,让用户登入系统后提示其再修改密码。也可以计算一个一段时间内有效的sign签名实现免登。

5 示例Demo

下载地址:OAuth Demo for Linux