認証クッキー取得の実装

本稿では、POC of consuming Sharepoint onlineのPOC段階4の実装を紹介します。

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<String> _requestEntity = RequestEntity
	.post(new URI(COOKIE_SITE_ENDPOINT))
        .body(binarySecurityToken);  ★ポイント2
 
    restTemplateWithCookie.setRequestFactory(buildProxyClientHttpRequestFactory());
 
    ResponseEntity<String> _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<HttpCookie> 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<HttpCookie> 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> T doExecute(URI url, HttpMethod method, final RequestCallback requestCallback,
	final ResponseExtractor<T> responseExtractor) throws RestClientException {
    logger.info("RestTemplateWithCookies.doExecute() Called.");
    final List<HttpCookie> _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<T>() {
	@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<String> _rawCookies = headers.get(HttpHeaders.SET_COOKIE);
    if (_rawCookies != null && !_rawCookies.isEmpty()) {
	for (String _rawCookie : _rawCookies) {
	  List<HttpCookie> _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クッキー1)とFedAuthクッキー2)が存在するか確認するメソッドです。
既に認証済みの場合、処理を軽減させるために使われます。

★ポイント2
リクエストヘッダーCookieにrtFaクッキーとFedAuthクッキーを追加します。

★ポイント3
レスポンスヘッダーSet-CookieからrtFaクッキーとFedAuthクッキーを取り出して、cookiesリストに追加するメソッドです。

Reference

1)
このクッキーは、「認証済みフォーム」を表す「Ready to Form authentication」の略です。Microsoft 365の認証基盤であるAzure Active Directory (Azure AD)でユーザーが認証された際に発行されます。これは、ユーザーがシングルサインオン (SSO) セッションを確立したことを示します。
2)
このクッキーは、「フェデレーション認証」を表す「Federated Authentication」の略です。rtFaクッキーを使ってSharePoint Onlineにアクセスする際に、SharePoint Onlineが独自に発行するセッションクッキーです。このクッキーによって、ユーザーはSharePoint Onlineのサイトやファイルへのアクセス権を維持できます。

コメント

コメントを入力. Wiki文法が有効です:
C X T V I
 

QR Code
QR Code study:java:sharepointonline:implement4 (generated for current page)