3.9.11.3.1. REST API 中的社交账号登录

社交账号登录的机制也可以在 REST API 中使用。完整的示例应用程序可以在 GitHub 上找到,同时在社交网站登录部分有详细描述,下面是使用 Facebook 帐户获取访问令牌的关键点。

  • web 模块的根包下创建 restapi 包,并在其中实现自定义 Spring MVC 控制器。该控制器应包含两个主要方法:get() 方法获取 ResponseEntity 实例,login() 方法获取 OAuth 令牌。

FacebookAuthenticationController.java

  1. @RequestMapping(method = RequestMethod.GET)
  2. public ResponseEntity get() {
  3. String loginUrl = getAsPrivilegedUser(() ->
  4. facebookService.getLoginUrl(getAppUrl(), OAuth2ResponseType.CODE_TOKEN)
  5. );
  6. HttpHeaders headers = new HttpHeaders();
  7. headers.set(HttpHeaders.LOCATION, loginUrl);
  8. return new ResponseEntity<>(headers, HttpStatus.FOUND);
  9. }

在这里,我们检查 Facebook code,获取访问代码并使用 OAuthTokenIssuer 发出访问令牌:

FacebookAuthenticationController.java

  1. @RequestMapping(method = RequestMethod.POST, value = "login")
  2. public ResponseEntity<OAuth2AccessToken> login(@RequestParam("code") String code) {
  3. User user = getAsPrivilegedUser(() -> {
  4. FacebookUserData userData = facebookService.getUserData(getAppUrl(), code);
  5. return socialRegistrationService.findOrRegisterUser(
  6. userData.getId(), userData.getEmail(), userData.getName());
  7. });
  8. OAuth2AccessTokenResult tokenResult = oAuthTokenIssuer.issueToken(user.getLogin(),
  9. messageTools.getDefaultLocale(), Collections.emptyMap());
  10. HttpHeaders headers = new HttpHeaders();
  11. headers.set(HttpHeaders.CACHE_CONTROL, "no-store");
  12. headers.set(HttpHeaders.PRAGMA, "no-cache");
  13. return new ResponseEntity<>(tokenResult.getAccessToken(), headers, HttpStatus.OK);
  14. }
  • web/core 模块扫描中排除 restapi 包:OAuthTokenIssuer bean 仅在 REST API 上下文中可用,在应用程序上下文中对其进行扫描将导致错误。
  1. <context:component-scan base-package="com.company.demo">
  2. <context:exclude-filter type="regex" expression="com\.company\.demo\.restapi\..*"/>
  3. </context:component-scan>
  • 在项目的 modules/web/web/VAADIN 文件夹中创建 facebook-login-demo.html 文件,包含在 HTML 页面上运行的 JavaScript 代码:

facebook-login-demo.html

  1. <html>
  2. <head>
  3. <title>Facebook login demo with REST-API</title>
  4. <script src="jquery-3.2.1.min.js"></script>
  5. <style type="text/css">
  6. #users { display: none; }
  7. </style>
  8. </head>
  9. <body>
  10. <h1>Facebook login demo with REST-API</h1>
  11. <script type="application/javascript"...>
  12. </script>
  13. <a id="fbLink" href="/app/rest/facebook">Login with Facebook</a>
  14. <div id="users">
  15. You are logged in!
  16. <h1>Users</h1>
  17. <div id="usersList">
  18. </div>
  19. </div>
  20. </body>
  21. </html>

以下脚本将尝试使用 Facebook 登录。首先,它将从 URL 中删除 code 参数,然后它将 code 传递给 REST API 以获取 OAuth 访问令牌,在成功验证的情况下,将能够正常加载和保存数据。

facebook-login-demo.html

  1. var oauth2Token = null;
  2. function tryToLoginWithFacebook() {
  3. var urlHash = window.location.hash;
  4. if (urlHash && urlHash.indexOf('&code=') >= 0) {
  5. console.log("Try to login to CUBA REST-API!");
  6. var urlCode = urlHash.substring(urlHash.indexOf('&code=') + '&code='.length);
  7. console.log("Facebook code: " + urlCode);
  8. history.pushState("", document.title, window.location.pathname);
  9. $.post({
  10. url: '/app/rest/facebook/login',
  11. headers: {
  12. 'Content-Type': 'application/x-www-form-urlencoded'
  13. },
  14. dataType: 'json',
  15. data: {code: urlCode},
  16. success: function (data) {
  17. oauth2Token = data.access_token;
  18. loadUsers();
  19. }
  20. })
  21. }
  22. }
  23. function loadUsers() {
  24. $.get({
  25. url: '/app/rest/v2/entities/sec$User?view=_local',
  26. headers: {
  27. 'Authorization': 'Bearer ' + oauth2Token,
  28. 'Content-Type': 'application/x-www-form-urlencoded'
  29. },
  30. success: function (data) {
  31. $('#fbLink').hide();
  32. $('#users').show();
  33. $.each(data, function (i, user) {
  34. $('#usersList').append("<li>" + user.name + " (" + user.email + ")</li>");
  35. });
  36. }
  37. });
  38. }
  39. tryToLoginWithFacebook();

另一个示例或在 CUBA 应用程序中运行 JavaScript 代码,可以在JavaScript 用法示例部分找到。