Недавно возникла задача синхронизации существующих пользователей в Discourse с помощью SSO.
Поэтому я реализовал решение на Java, основываясь на официальном примере для PHP (Sync DiscourseConnect user data with the sync_sso route - developers - Discourse Meta).
Реализация довольно проста, но требует использования дополнительных библиотек, прежде всего Apache Commons Codec и OkHttp.
Apache Commons Codec используется для создания цифровой подписи, а OkHttp — для отправки HTTP POST-запросов.
Настройка параметров
Заранее необходимо получить 4 параметра.
Способ получения этих четырёх параметров описан в статье: Discourse 使用 DiscourseConnect 来进行用户数据同步
const apiKey = '4fe83002bb5fba8c9a61a65e5b4b0a3cf8233b0e4ccafc85ebd6607abab4651a';
const apiUser = 'system';
const connectSecret = 'jdhb19*Xh3!nu(#k';
Настройка параметров SSO
Настройка параметров аналогична параметрам GET-запроса в URL.
Наш код на Java выглядит следующим образом:
URIBuilder builder = new URIBuilder();
builder.addParameter("external_id", "1");
builder.addParameter("email", "info@isharkfly.com");
builder.addParameter("username", "info.visafn.sso");
builder.addParameter("add_groups", "bar");
builder.addParameter("require_activation", "false");
url = StringUtils.removeStart(builder.build().toString(),"?");
System.out.println(StringUtils.removeStart(url, "?"));
Base64 и цифровая подпись
После получения строки URL выше необходимо выполнить два следующих шага.
Первый шаг — преобразование полученного URL в формат Base64.
Второй шаг — создание цифровой подписи для полученной строки Base64 с использованием алгоритма HMAC_SHA_256.
При этом ключ, полученный на первом шаге, должен быть передан в качестве параметра для участия в вычислениях вместе с алгоритмом.
String sso= "admin/users/sync_sso";
String sig= new HmacUtils(HmacAlgorithms.HMAC_SHA_256, "55619458534897").hmacHex(ssoPayload);
После получения этих двух значений необходимо сформировать новую структуру данных в формате JSON.
Структура данных будет выглядеть примерно так, и она будет использоваться в качестве тела POST-запроса:
{
"sso": "P2V4dGVybmFsX2lkPTEmZW1haWw9aW5mbyU0MHZpc2Fmbi5jb20mdXNlcm5hbWU9aW5mby52aXNhZm4mcmVxdWlyZV9hY3RpdmF0aW9uPXRydWU=",
"sig": "403a205a004e37ffab2bf77cc12b2eac352d71820983706d86984eec9821a0c4"
}
Отправка POST-запроса
Можно использовать любой инструмент, поддерживающий HTTP.
Поскольку в Java чаще всего используется OkHttp, мы будем использовать его для отправки запроса.
private OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(
MediaType.parse("application/json"), objectMapper.writeValueAsString(syncSSO));
Response response = client.newCall(postRequest(path, body)).execute();
Метод postRequest, упомянутый выше, используется для формирования запроса с помощью имеющихся параметров.
Вот как он написан:
public Request postRequest(String path, RequestBody body) {
HttpUrl.Builder urlBuilder = HttpUrl.parse(site_url + path).newBuilder();
Request request = new Request.Builder().url(urlBuilder.build().toString())
.addHeader("api-username", api_username)
.addHeader("api-key", api_key)
.post(body)
.build();
return request;
}
Если всё настроено правильно, приведённый выше код позволит успешно выполнить синхронизацию данных SSO.