社群網路已經成為目前人們生活中不可或缺的一部分。流行的社交網站,如 Facebook、LinkedIn、Twitter 和新浪微博等都聚集了非常高的人氣,成為許多人每天必上的網站。大量的資訊被分享到社交網路中。對於一個應用程式來說,提供對社群網路的支援是很有必要的。應用可以透過與社交網路的整合來迅速累積人氣。與社交網路的整合主要有兩個方面的功能:第一個是比較簡單的用戶登入集成,即允許用戶使用社交網路網站上的已有帳戶來登入應用程式。這樣做的好處是可以省去要用戶重新註冊的流程,同時也可以與用戶已有的社交網絡建立連接;第二個是深度的整合方式,即允許用戶把應用中的相關內容分享到社交網絡中。這樣做的好處是可以保持用戶的黏性,同時推廣應用程式本身。
在應用程式中整合社交網路並不是一件複雜的工作。很多社交網路服務都提供開放 API 允許第三方應用程式來進行整合。只需要參考相關的文件就可以完成。不過整合本身需要一定的工作量。所需要整合的網站越多,對應的工作量越大。 Spring Social 作為 Spring 框架元件家族中的一部分,提供了對社交網路服務的抽象,並提供了相關的 API 來進行操作。
使用 Spring Social 的最大好處在於它已經提供了對主流社交網站的支持,只需要簡單配置即可。對於一些不太常用的社交網站,也可以從社區中找到相應的組件。本文以一個範例應用來說明 Spring Social 的用法。
範例應用程式
此範例允許使用者登入社交網站查看他們的好友資訊。這是一個使用 Spring MVC 框架建構的 Web 應用。該應用程式使用嵌入式的 H2 資料庫來儲存資料。前端使用 JSP、JSTL 和 Spring 提供的標籤庫,利用 Apache Tiles 進行頁面佈局。使用 Spring Security 管理使用者認證。頁面的樣式使用 Twitter Bootstrap 函式庫。項目使用 Gradle 進行建置。前端庫透過 Bower 進行管理。
範例所提供的功能比較簡單,主要包括登入和註冊頁面,以及使用者的首頁。登入時,使用者可以選擇使用第三方社群網路的帳號。登入之後可以查看社群網路的好友資訊。
使用社群網路已有帳號登入
與社群網路整合的最基本的功能是允許使用者使用現有的帳號進行登入。用戶除了註冊新的帳號之外,還可以使用現有的其他網站的帳號登入。這種方式通常稱為連接第三方網站。對於用戶來說,通常的場景是在註冊或登入頁面,選擇第三方社交網路來進行連接。然後跳到第三方網站進行登入和授權。完成上述步驟之後,新的使用者會被建立。在連接過程中,應用程式可以從第三方社交網站獲取到用戶的概要信息,來完成新用戶的創建。當新使用者建立完成之後,下次使用者可以直接使用第三方社群網路的帳號登入。
基本配置
Spring Social 提供了處理第三方網站使用者登入和註冊的Spring MVC 控制器(Controller)的實現,可以自動完成使用社交網路帳號登入和註冊的功能。在使用這些控制器之前,需要進行一些基本的配置。 Spring Social 的配置是透過實作 org.springframework.social.config.annotation.SocialConfigurer 介面來完成的。給出了實作 SocialConfigurer 介面的 SocialConfig 類別的部分內容。註解「@EnableSocial」用來啟用 Spring Social 的相關功能。註解「@Configuration」表示該類別也同樣包含 Spring 框架的相關配置資訊。 SocialConfigurer 介面有 3 個方法需要實現:
addConnectionFactories:此回呼方法用來允許應用程式新增需要支援的社交網路對應的連接工廠的實作。
getUserIdSource:此回呼方法傳回一個 org.springframework.social.UserIdSource 介面的實作對象,用來惟一標識目前使用者。
getUsersConnectionRepository:此回呼方法傳回一個 org.springframework.social.connect.UsersConnectionRepository 介面的實作對象,用來管理使用者與社群網路服務提供者之間的對應關係。
具體到範例應用程式來說,addConnectionFactories 方法的實作中加入了由 org.springframework.social.linkedin.connect.LinkedInConnectionFactory 類別表示的 LinkedIn 的連結工廠實作。 getUserIdSource 方法的實作中透過 Spring Security 來取得目前登入使用者的資訊。 getUsersConnectionRepository 方法中建立了一個基於資料庫的 JdbcUsersConnectionRepository 類別的實作物件。 LinkedInConnectionFactory 類別的創建方式反映了 Spring Social 的強大之處。只需要提供在 LinkedIn 申請的 API 金鑰,就可以直接使用 LinkedIn 所提供的功能。與 OAuth 相關的細節都被 Spring Social 所封裝。
1.使用Spring Social 的基本配置
@Configuration@EnableSocialpublic class SocialConfig implements SocialConfigurer { @Inject private DataSource dataSource; @Override public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) { cfConfig.addConnectionFactory(new LinkedInConnectionFactory(env.getProperty("linkedin.consumerKey"), env.getProperty("linkedin.consumerSecret"))); } @Override public UserIdSource getUserIdSource() { return new UserIdSource() { @Override public String getUserId() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in"); } return authentication.getName(); } }; } @Override public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) { return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText()); } }
登入控制器
配置了Spring Social 的下一步是建立對應的Spring MVC 控制器來處理使用者的註冊和登入。 Spring Social 已經提供對應的控制器實現,只需要建立介面來發出請求即可。首先要建立的是透過第三方社群網路登入的控制器。如所示,只需要建立一個 Spring Bean 就可以建立所需的控制器。此控制器預設綁定在「/signin」的 URL 上面。每個第三方服務提供者都有一個對應的標識符,如 LinkedIn 的標識符是「linkedin」。服務提供者的識別碼通常作為不同控制器 URL 的一部分。例如當使用者需要透過 LinkedIn 帳號登入時,對應的 URL 就是「/signin/linkedin」。如果透過 Twitter 帳號登入,則對應的 URL 是「/signin/twitter」。
2. 透過第三方社交網路進行登入的控制器
@Beanpublic ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) { return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SimpleSignInAdapter(new HttpSessionRequestCache())); }
在上面的中,SimpleSignInAdapter 類別實現了org.springframework.social.connect.web.SignInAdapter 接口,其作用是ProviderSignInController 類別和應用程式本身的登入邏輯之間的橋樑。當使用者完成第三方網站的登入之後,透過 SignInAdapter 介面來讓該使用者自動登入應用程式中。 SimpleSignInAdapter 類別的實作如圖所示。
3. SimpleSignInAdapter 類別的實作
public class SimpleSignInAdapter implements SignInAdapter { private final RequestCache requestCache; @Inject public SimpleSignInAdapter(RequestCache requestCache) { this.requestCache = requestCache; } @Override public String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) { SignInUtils.signin(localUserId); return extractOriginalUrl(request); } private String extractOriginalUrl(NativeWebRequest request) { HttpServletRequest nativeReq = request.getNativeRequest(HttpServletRequest.class); HttpServletResponse nativeRes = request.getNativeResponse(HttpServletResponse.class); SavedRequest saved = requestCache.getRequest(nativeReq, nativeRes); if (saved == null) { return null; } requestCache.removeRequest(nativeReq, nativeRes); removeAutheticationAttributes(nativeReq.getSession(false)); return saved.getRedirectUrl(); } private void removeAutheticationAttributes(HttpSession session) { if (session == null) { return; } session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); } }
在程式碼清單3中,SimpleSignInAdapter 類別的signIn 方法呼叫SignInUtils 類別的signin 方法來登入,其實作見程式碼清單4。 signIn 方法的回傳值是登入成功之後的跳轉 URL。
4. SignInUtils 類別的signIn 方法的實作
public class SignInUtils { public static void signin(String userId) { SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(userId, null, null)); } }
前端頁面
#只需要透過頁面向登入控制器的URL 發出一個POST 請求,就可以啟動透過LinkedIn進行登入的過程。如中,透過表單提交就可以啟動登入程序。使用者會被先前往 LinkedIn 網站的授權頁面給應用程式授權,授權完成之後就可以進行註冊。
5. 登入頁面
<form id="linkedin-signin-form" action="signin/linkedin" method="POST" class="form-signin" role="form"> <h2 class="form-signin-heading">Or Connect by</h2> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <button type="submit" class="btn btn-primary">LinkedIn</button> </form>
預設情況下,當第三方網站授權完成之後,使用者會被轉到 URL「/signup」對應的頁面。在這個頁面,使用者可以補充一些相關的註冊資訊。同時,從第三方網站獲取的用戶概要信息,如用戶的姓名等,可以被預先填充好。該頁面在表單提交之後的操作,由所示的控制器來處理。
6. 使用者註冊控制器的實作
@RequestMapping(value="/signup", method=RequestMethod.POST) public String signup(@Valid @ModelAttribute("signup") SignupForm form, BindingResult formBinding, WebRequest request) { if (formBinding.hasErrors()) { return null; } Account account = createAccount(form, formBinding); if (account != null) { SignInUtils.signin(account.getUsername()); ProviderSignInUtils.handlePostSignUp(account.getUsername(), request); return "redirect:/"; } return null; }
當使用者提交註冊表單之後,根據使用者填寫的資訊建立對應的帳號,然後登入新註冊的帳號並跳轉回首頁。
使用 API
Spring Social 的另外一个重要的作用在于提供了很多社交网络服务的 API 的封装。当用户通过社交网络的账号登录之后,可以通过相应的 API 获取到相关的信息,或执行一些操作。比如获取到用户的好友信息,或是根据用户的要求发布新的消息。一般来说,很多社交网络服务提供商都有自己的 API 来提供给开发人员使用。不过一般只提供 REST API,并没有 Java 封装。Spring Social 的一个目标是为主流的社交网络提供相应的 Java 封装的 API。对于社区已经有良好的 Java 库的社交网络,如 Twitter,Spring Social 会进行整合与封装;而对于暂时没有 Java 实现的,Spring Social 的组件会提供相应的支持。如示例应用中使用的 LinkedIn 的 Java API 是由 Spring Social 开发的。
在使用 LinkedIn 的 Java API 之前,首先要创建相应的 Spring Bean,如所示。
7. 创建 LinkedIn API 对应的 Bean
@Bean@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)public LinkedIn linkedin(ConnectionRepository repository) { Connection<LinkedIn> connection = repository.findPrimaryConnection(LinkedIn.class); return connection != null ? connection.getApi() : null; }
LinkedIn Java API 的核心接口是 org.springframework.social.linkedin.api.LinkedIn。如果当前用户已经连接了 LinkedIn 的账号,就可以通过 ConnectionRepository 接口找到该用户对应的连接的信息,并创建出 API 接口的实现。是展示 LinkedIn 上好友信息的控制器的实现。
8. 展示 LinkedIn 上好友信息的控制器的实现
@Controllerpublic class LinkedInConnectionsController { private LinkedIn linkedIn; @Inject public LinkedInConnectionsController(LinkedIn linkedIn) { this.linkedIn = linkedIn; } @RequestMapping(value="/connections", method= RequestMethod.GET) public String connections(Model model) { model.addAttribute("connections", linkedIn.connectionOperations().getConnections()); return "connections"; } }
通过 LinkedIn 接口的 connectionOperations 方法可以获取到 org.springframework.social.linkedin.api.ConnectionOperations 接口的实现,然后就可以再通过 getConnections 方法获取到包含好友信息的 org.springframework.social.linkedin.api.LinkedInProfile 类的对象列表。然后就可以在网页上展示,如所示。
9. 展示 LinkedIn 好友信息的页面
<ul class="media-list"> <c:forEach items="${connections}" var="connection"> <li class="media"> <a href="" class="pull-left"> <img class="lazy-load" data-original="${connection.profilePictureUrl}" alt="" class="media-object"> </a> <div class="media-body"> <h4 class="media-heading">${connection.firstName} ${connection.lastName}</h4> <p><c:out value="${connection.headline}" /></p> </div> </li> </c:forEach> </ul>
结束语
在社交网络日益流行的今天,Web 应用都应该考虑增加对社交网络的支持。这样既方便了用户,让他们省去了重新注册的麻烦,又可以增加用户粘性,同时可以通过社交网络进行推广。虽然很多社交网站都提供了开放 API 来让应用使用其服务,但是集成所需的工作量是不小的。Spring Social 作为 Spring 框架中的一部分,为在 Web 应用中集成社交网络提供了良好支持。本文详细介绍了如何通过 Spring Social 来实现通过社交网络账号进行登录以及使用社交网络提供的 API。
以上是怎麼使用使用 Spring Social 連結社群網絡的詳細內容。更多資訊請關注PHP中文網其他相關文章!