5.3.1. REST API 中的社交账号登录
社交账号登录的机制也可以在 REST API 中使用。完整的示例应用程序可以在 GitHub 上找到,同时在 社交登录 部分有详细描述,下面是使用 Facebook 帐户获取访问 token 的关键技术点。
-
在 web 模块的根包下创建
restapi
包,并在其中实现自定义 Spring MVC 控制器。该控制器应包含两个主要方法:get()
方法获取ResponseEntity
实例,login()
方法获取 OAuth token。@RequestMapping(method = RequestMethod.GET) public ResponseEntity get() { String loginUrl = getAsPrivilegedUser(() -> facebookService.getLoginUrl(getAppUrl(), OAuth2ResponseType.CODE_TOKEN) ); HttpHeaders headers = new HttpHeaders(); headers.set(HttpHeaders.LOCATION, loginUrl); return new ResponseEntity<>(headers, HttpStatus.FOUND); }
在这里,我们检查 Facebook code,获取 access code 并使用
OAuthTokenIssuer
发出 access token:@RequestMapping(method = RequestMethod.POST, value = "login") public ResponseEntity<OAuth2AccessToken> login(@RequestParam("code") String code) { User user = getAsPrivilegedUser(() -> { FacebookUserData userData = facebookService.getUserData(getAppUrl(), code); return socialRegistrationService.findOrRegisterUser( userData.getId(), userData.getEmail(), userData.getName()); }); OAuth2AccessTokenResult tokenResult = oAuthTokenIssuer.issueToken(user.getLogin(), messageTools.getDefaultLocale(), Collections.emptyMap()); HttpHeaders headers = new HttpHeaders(); headers.set(HttpHeaders.CACHE_CONTROL, "no-store"); headers.set(HttpHeaders.PRAGMA, "no-cache"); return new ResponseEntity<>(tokenResult.getAccessToken(), headers, HttpStatus.OK); }
-
从 web/core 模块扫描中排除
restapi
包:OAuthTokenIssuer
bean 仅在 REST API 上下文中可用,在应用程序上下文中对其进行扫描将导致错误。<context:component-scan base-package="com.company.demo"> <context:exclude-filter type="regex" expression="com\.company\.demo\.restapi\..*"/> </context:component-scan>
-
在项目的
modules/web/web/VAADIN
文件夹中创建facebook-login-demo.html
文件,包含在 HTML 页面上运行的 JavaScript 代码:<html> <head> <title>Facebook login demo with REST-API</title> <script src="jquery-3.2.1.min.js"></script> <style type="text/css"> #users { display: none; } </style> </head> <body> <h1>Facebook login demo with REST-API</h1> <script type="application/javascript"...> </script> <a id="fbLink" href="/app/rest/facebook">Login with Facebook</a> <div id="users"> You are logged in! <h1>Users</h1> <div id="usersList"> </div> </div> </body> </html>
以下脚本将尝试使用 Facebook 登录。首先,它将从 URL 中删除 code 参数,然后它将 code 传递给 REST API 以获取 OAuth access token,验证成功后,将能够正常加载和保存数据。
var oauth2Token = null; function tryToLoginWithFacebook() { var urlHash = window.location.hash; if (urlHash && urlHash.indexOf('&code=') >= 0) { console.log("Try to login to CUBA REST-API!"); var urlCode = urlHash.substring(urlHash.indexOf('&code=') + '&code='.length); console.log("Facebook code: " + urlCode); history.pushState("", document.title, window.location.pathname); $.post({ url: '/app/rest/facebook/login', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, dataType: 'json', data: {code: urlCode}, success: function (data) { oauth2Token = data.access_token; loadUsers(); } }) } } function loadUsers() { $.get({ url: '/app/rest/v2/entities/sec$User?view=_local', headers: { 'Authorization': 'Bearer ' + oauth2Token, 'Content-Type': 'application/x-www-form-urlencoded' }, success: function (data) { $('#fbLink').hide(); $('#users').show(); $.each(data, function (i, user) { $('#usersList').append("<li>" + user.name + " (" + user.email + ")</li>"); }); } }); } tryToLoginWithFacebook();
另一个示例或在 CUBA 应用程序中运行 JavaScript 代码,可以在 JavaScript 用法示例 部分找到。