概要
SpringアプリケーションからTwitterやFacebookなどのSNSサービスを手軽に利用するためのライブラリ。
Spring Socialを使うメリット
おことわり
この記事では、接続するSNSとしてTwitterを例として話します。
Spring Socialのreferenceをもとに話します。
Spring Social Reference
build.gradle
compile("org.springframework.boot:spring-boot-starter-social-twitter")
SNSアカウントでアプリにログインする機能がほしい場合はさらにspring-social-security
が必要。
compile("org.springframework.social:spring-social-security:1.1.0.RELEASE")
用語説明
provider
OAuth認可フローにおける、tokenの発行者。
consumer
OAuth認可フローにおける、tokenの受取者。
つまりSNSを利用するアプリがconsumerで、利用するSNSがproviderとなる。
SNSのAPIを呼び出す単純なアプリ(connecting to providers)
SNSとのOAuth認証部分が全てspring-social側で実装されているので、開発者が書くコードは驚くほど少ない。
ConnectController
org.springframework.social.connect.web
内で実装されているController
下記エンドポイントが自動的に利用できるようになる。
GET /connect
すべてのproviderについて、アカウント接続状況を一覧で表示する
GET /connect/{providerId}
指定したproviderのアカウント接続状況を表示する。
POST /connect/{providerId}
指定したproviderへの接続処理を開始する。
GET /connect/{providerId}?oauth_token={request token}&oauth_verifier={verifier}
Receives the authorization callback from the provider, accepting a verification code. Exchanges this verification code along with the request token for an access token and completes the connection. The oauth_verifier parameter is optional and is only used for providers implementing OAuth 1.0a.
(※リファレンス引用)
DELETE /connect/{providerId}
指定したproviderへの接続情報を削除する。
DELETE /connect/{providerId}/{providerUserId}
ユーザのproviderUserIdに基づいて、指定したproviderへの特定の接続のみ削除する。
{providerId}
はTwitterであればtwitter
、Facebookならfacebook
のような文字列。
viewはデフォルトで未定義なので、別途用意する必要がある。
サンプルアプリではtemplates.connect
フォルダ以下にthymeleafのテンプレートファイルが作られている。
twitterConnect.html
Twitterに未接続の場合表示されるview
twitterConnected.html
Twitterに接続済みの場合表示されるview
SNS接続済みかをチェックする
connectionRepository.findPrimaryConnection(Twitter.class)
で判別できる。
すでに認証できていれば Connection<Twitter>
クラスのコネクションが返ってくるし、未接続ならnull
が返る。
Connection<A>
はspring-socialの根幹をなすinterface。
public interface Connection<A> extends Serializable {
ConnectionKey getKey();
String getDisplayName();
String getProfileUrl();
String getImageUrl();
void sync();
boolean test();
boolean hasExpired();
void refresh();
UserProfile fetchUserProfile();
void updateStatus(String message);
A getApi();
ConnectionData createData();
}
認証情報の永続化
OAuth認証に必要な情報は以下の4つ。
- アプリのconsumer ID
- アプリのconsumer secret
- ユーザのaccess token
- ユーザのaccess token secret
上2つはSNSでアプリ登録するとアプリ1つにつき1つ付与されるので、それをPropertiesファイルなどに記載すればよい。
下2つはユーザごとに異なるので、ユーザごとにconnectionから取得し、DBなどに永続化することになる。
access tokenとaccess token secretはそれぞれconnectionから以下のメソッドで取得できる。
connection.createData().getAccessToken()
connection.createData().getSecret()
providerのAPIコール
REST APIコールをラップするクラスが用意されている。
ConnectionインタフェースのgetApi()
メソッドでラッパーのインスタンスを取得できる。型はprovider名と同じ。(TwitterならTwitter
クラス)
@Controller
@RequestMapping("/")
public class HelloController {
private Twitter twitter;
private ConnectionRepository connectionRepository;
@Inject
public HelloController(Twitter twitter, ConnectionRepository connectionRepository) {
this.twitter = twitter;
this.connectionRepository = connectionRepository;
}
@RequestMapping(method=RequestMethod.GET)
public String helloTwitter(Model model) {
if (connectionRepository.findPrimaryConnection(Twitter.class) == null) {
return "redirect:/connect/twitter";
}
model.addAttribute(twitter.userOperations().getUserProfile());
CursoredList<TwitterProfile> friends = twitter.friendOperations().getFriends();
model.addAttribute("friends", friends);
return "hello";
}
}
上記のコードでは、OAuth認証後にはtwitter
インスタンスを用いてTwitterの各種API呼び出しができるようになっている。
例えばtwitter.friendOperations().getFriends()
でログインユーザのフォローしている人の情報を取得できる。
SNSアカウントでログインするアプリ(signing in with provider account)
いわゆるソーシャルログイン。
利用例
単純なアプリ例との違い
- ユーザが同じブラウザでTwitterにログイン中で
- そのアプリのアクセスをすでに許可している
と、認証を要求されずスムーズにログインできる。
(authorizeせず、authenticateだけ行われる)
先ほどの単純なアプリの場合、上記条件を満たしていても、いちいち「(アプリ名)があなたのアカウントを利用することを許可しますか?」というTwitterの画面にリダイレクトされる。
- 単純なアプリでエンドポイントを提供する
ConnectControler
- SNSアカウントでログインするアプリでエンドポイントを提供する
ProviderSignInController
どちらのControllerにも定義されているConnectSupport
クラスのフィールドにboolean useAuthenticateUrl
という値があり、これがいちいちSNSのアプリ認証画面を出すかどうか左右している。
実装方法は2種類ある
SocialAuthenticationFilterを使う方法と
ProviderSignInControllerを使う方法がある。
どのように両者を使い分けるかはSpring Social Referenceに記載があり
Although both options will work with Spring Security, we recommend using SocialAuthenticationFilter in applications where Spring Security is in play.
とあるように、Spring Securityを利用しているアプリケーションでは、SocialAuthenticationFilterを使う方法が推奨される。
一方で、
ProviderSignInController, on the other hand, is agnostic to the security mechanism your application employs and can be used in applications that aren’t using Spring Security.
とあるように、ProviderSignInControllerはSpring Securityと独立して(agnostic to security mechanism)動作するので、Spring Securityを利用しないアプリケーションでもProviderSingInControllerを使えば、ソーシャルログイン機能を実装することが可能になる。
SocialAuthenticationFilter
Spring Securityのconfigurationに.apply(new SpringSocialConfigurer())
を追加する。
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/signin")
.loginProcessingUrl("/signin/authenticate")
.failureUrl("/signin?param.error=bad_credentials")
.and()
.logout()
.logoutUrl("/signout")
.deleteCookies("JSESSIONID")
.and()
.authorizeRequests()
.antMatchers("/admin/**", "/favicon.ico", ...).permitAll()
.antMatchers("/**").authenticated()
.and()
.rememberMe()
.and()
.apply(new SpringSocialConfigurer());
}
ProviderSignInController
SNSのアカウントによるログイン機能をSpringアプリに追加するにはProviderSignInController
をbeanとして設定する。
@Bean
public ProviderSignInController providerSignInController(
ConnectionFactoryLocator connectionFactoryLocator,
UsersConnectionRepository usersConnectionRepository) {
return new ProviderSignInController(
connectionFactoryLocator,
usersConnectionRepository,
new SimpleSignInAdapter(new HttpSessionRequestCache()));
}
参考情報