====== 認証クッキー取得の実装 ======
本稿では、[[study:java:sharepointonline:poc|POC of consuming Sharepoint online]]のPOC段階4の実装を紹介します。\\
{{keywords>Get authenticated cookie rtFa FedAuth Sharepoint online}}
====== Mainコード ======
実装Mainコードを以下に示します。
private static final String COOKIE_SITE_ENDPOINT = "https://xxxx.contoso.com/_forms/default.aspx?wa=wsignin1.0";
private static RestTemplateWithCookies restTemplateWithCookie = new RestTemplateWithCookies(); ★ポイント1
public void connnectSharePointSiteAndGetCookie(String binarySecurityToken) {
try {
//request entity
RequestEntity _requestEntity = RequestEntity
.post(new URI(COOKIE_SITE_ENDPOINT))
.body(binarySecurityToken); ★ポイント2
restTemplateWithCookie.setRequestFactory(buildProxyClientHttpRequestFactory());
ResponseEntity _responseEntity = _restTemplate.exchange(_requestEntity, String.class);
HttpStatus _status = _responseEntity.getStatusCode();
if (!HttpStatus.FOUND.equals(_status)) {
logger.error("HTTP status =" + _status);
}
} catch (Exception e) {
logger.error("failed to get SharePoint site cookie", e);
}
}//connnectSharePointSiteAndGetCookie
★ポイント1\\
Cookieを操作するために、RestTemplateクラスを拡張したクラスです。\\
詳細は次節を参照してください。
★ポイント2\\
Binary tokenをPOST送信するため、Bodyに追加します。
====== RestTemplateWithCookies ======
RestTemplate拡張クラスを以下に示します。
public class RestTemplateWithCookies extends RestTemplate {
private static final Logger logger = LoggerFactory.getLogger(RestTemplateWithCookies.class);
private final List cookies = new ArrayList<>();
private final String COOKIE_RT_FA = "rtFa";
private final String COOKIE_FED_AUTH = "FedAuth";
// ***** constructor *****
public RestTemplateWithCookies() { }
// ***** public method *****
public synchronized List getCookies() {
return cookies;
}
public synchronized void resetCookies() {
cookies.clear();
}
public boolean isAuthenticated() { ★ポイント1
int _count = 0;
for (HttpCookie _cookie : getCookies()) {
if ((COOKIE_RT_FA.equals(_cookie.getName()) ||
COOKIE_FED_AUTH.equals(_cookie.getName())) && !"".equals(_cookie.getValue()))
_count++;
}
return (_count == 2);
}
// ***** protected method *****
/* (non-Javadoc)
* @see org.springframework.web.client.RestTemplate#doExecute(java.net.URI, org.springframework.http.HttpMethod,
* org.springframework.web.client.RequestCallback, org.springframework.web.client.ResponseExtractor)
*/
@Override
protected T doExecute(URI url, HttpMethod method, final RequestCallback requestCallback,
final ResponseExtractor responseExtractor) throws RestClientException {
logger.info("RestTemplateWithCookies.doExecute() Called.");
final List _cookies = getCookies();
return super.doExecute(url, method, new RequestCallback() {
@Override
public void doWithRequest(ClientHttpRequest chr) throws IOException {
if (_cookies != null && _cookies.size() > 0) { ★ポイント2
StringBuilder _sb = new StringBuilder();
for (HttpCookie _cookie : _cookies) {
_sb.append(_cookie.getName()).append("=").append(_cookie.getValue()).append(";");
}//for
logger.debug("cookie is added to request: {}", _sb.toString());
chr.getHeaders().add(HttpHeaders.COOKIE, _sb.toString());
}//if
requestCallback.doWithRequest(chr);
}
}, new ResponseExtractor() {
@Override
public T extractData(ClientHttpResponse chr) throws IOException {
processHeaders(chr.getHeaders());
return responseExtractor.extractData(chr);
}
});
}//doExecute
// ***** private method *****
private void processHeaders(HttpHeaders headers) { ★ポイント3
final List _rawCookies = headers.get(HttpHeaders.SET_COOKIE);
if (_rawCookies != null && !_rawCookies.isEmpty()) {
for (String _rawCookie : _rawCookies) {
List _parsedCookies = HttpCookie.parse(_rawCookie);
for (HttpCookie _parsedCookie : _parsedCookies) {
HttpCookie _cookieExists = filterCookieByName(_parsedCookie.getName());
//if same named cookie is already exists, remove that cookie.
if (_cookieExists != null) {
cookies.remove(_cookieExists);
}
logger.debug("accepted cookie: {}", _parsedCookie);
cookies.add(_parsedCookie);
}//for
}//for
}//if
}//processHeaders
private HttpCookie filterCookieByName(String name) {
HttpCookie _result = null;
for (HttpCookie _cookie : cookies) {
if (_cookie.getName().equals(name)) {
_result = _cookie;
break;
}
}
return _result;
}//filterCookieByName
}
★ポイント1\\
cookiesリストにrtFaクッキー((このクッキーは、**「認証済みフォーム」を表す「Ready to Form authentication」の略です。Microsoft 365の認証基盤であるAzure Active Directory (Azure AD)**でユーザーが認証された際に発行されます。これは、ユーザーがシングルサインオン (SSO) セッションを確立したことを示します。))とFedAuthクッキー((このクッキーは、**「フェデレーション認証」**を表す「Federated Authentication」の略です。rtFaクッキーを使ってSharePoint Onlineにアクセスする際に、SharePoint Onlineが独自に発行するセッションクッキーです。このクッキーによって、ユーザーはSharePoint Onlineのサイトやファイルへのアクセス権を維持できます。))が存在するか確認するメソッドです。\\
既に認証済みの場合、処理を軽減させるために使われます。
★ポイント2\\
リクエストヘッダーCookieにrtFaクッキーとFedAuthクッキーを追加します。
★ポイント3\\
レスポンスヘッダーSet-CookieからrtFaクッキーとFedAuthクッキーを取り出して、cookiesリストに追加するメソッドです。
====== Reference ======
* [[https://stackoverflow.com/questions/22853321/resttemplate-client-with-cookies|RestTemplate client with cookies]]
~~DISCUSSION~~