為了因應即將上線的新建帳號平臺,需要配合MERGE縣市端程式以及撰寫accountdatasource的SPI函式庫
新的管理介面多出可勾選OIDC或OAUTH流程
為了要讓部裡主機可以透過OAUTH2流程,呼叫縣市已建置的同步反查用的SYNCDATA API,所以,oauth的flow要改成client_credentials
除了帳號管理平臺之外,原本的教育部認證主機也要改成支援client_credentials
先git pull /authserver/cncaccountdatasource/master主程式
再到git 建立 /authserver/cncaccountdatasource縣市的分支後,修改程式以對應各縣市syncdata回傳的資料型態(如以縣市帳號或GUID反查)
cncaccountdatasource這個程式它會利用httpclient走oauth2的流程,先取TOKEN再問SYNCDATA的API
縣市端開給部裡主機(帳號管理以及OIDC)會去讀資料庫中存的clientid和clientsecret
以上是概念,以下紀錄實作步驟
一、先更新縣市端認證程式的函式庫:cnclibs 1.0.12, EduDataType 1.0.5.6
我測試過,雖然CncResource專案的POM是1.0.11但似乎有狀況,編譯時會去找edudatatype 1.0.5.4找不到就出錯了
所以我試出來的方法就是先更新POM到cnclibs 1.0.12, EduDataType 1.0.5.6 確定這二個dependency都有下載完成了再做MERGE 的動作
二、 pull latest tc-idp-wicket8 codes and merge into current branch
再來拉回最新的程式後,進行合併到自己縣市的分支程式
cncauthserver: tc-idp-wicket8
CncResource: tc_resource_wicket8
這二個專案都必須進行函式庫更新及合併分支的動作
如果函式庫都正常加入了,那麼cncauthserver及CncResource這二個專案就沒有需要另外修改的地方,再檢查POM是否與剛才更新的縣市端專案的函式庫版本相同
若沒狀況,到此就完成合併的作業,編譯通過後重新發佈更新後的專案程式war檔
三、修改cncaccountdatasource
3-1 pull master branch
3-2 先在git上建立分支,名稱像是xxdatasource
3-3 修改POM的artifactId及version
<artifactId>xxaccountdatasource</artifactId> <version>0.0.1</version>
3-4 修改CNCAccountSource程式
位置在cncaccountdatasource專案下->src->main->java->account
在 implement之後,新增一個方法,以讀取設定檔
private static final Settings settings = new Settings() {
@Override
protected String getDefaultPropertiesFileName() {
return "xxsyncdata.properties";
}
};
return "xxsyncda.properties"名稱是要給本部程式辨認的所以修改為縣市代號如新竹市就hcsyncdata.properties
這個設定檔是給本部帳號管理程式讀取的,只要在這支程式裡改名就可以了
再到下面第三個建構式這邊修改為各縣市回傳的資料型態,多種型態可用switch判斷
/** * @param identity 真實要送入的資料 * @param iUniqueIDType 帳號型式,有GUID、ID、NAME以及USERNAME * @return */
@Override public Optional<List<ExchangeDataModel>> getAccountData(String identity, IUniqueIDType iUniqueIDType) { Optional<List<ExchangeDataModel>> models = Optional.empty(); //新竹市支援帳號ACCOUT反查 switch (iUniqueIDType) { case ACCOUNT: case PERSONID: final Map<IUniqueIDType, String> iUniqueIDTypeStringMap = Collections.synchronizedMap(new HashMap<>()); iUniqueIDTypeStringMap.put(iUniqueIDType, identity); DataRequest dataRequest = new DataRequest(settings, //這邊直接傳入在本機測試用的設定檔路徑,自建一個client.properties檔案,內容為帳號管理平台的clientid & secrets "../client.properties",//需指定本機測試用的檔案路徑 iUniqueIDTypeStringMap); logger.info("Map : {}", dataRequest.getiUniqueIDTypeStringMap()); Future<Optional<List<ExchangeDataModel>>> future = executorService.submit(dataRequest); try { models = future.get(); } catch (InterruptedException | ExecutionException e) { logger.error("Cannot fetch ExchangeDataModel\n{}", e.getMessage()); e.printStackTrace(); } break; default: throw new UnsupportedOperationException(); } return models; }
client.properties檔案內容如下:就是開給帳號管理平台用的
###############################
clientid=要寫入帳號管理平台的id
clientsecret=要寫入帳號管理平台的secret
tokenuri=https://xx.sso.edu.tw/cncresource/api/v1/oauth2/token
syncdatauri=https://xx.sso.edu.tw/cncresource/api/v1/oauth2/syncdata
###############################
xx.sso.edu.tw要改成縣市端的主機網域
最後修改指定帳號來源的方法,回傳縣市端的代碼物件
/**
* 指定帳號來源
*
* @return
*/
@Override
public AccountSource getAccountSource() {
//TODO 指定資料來源
return AccountSource.XXX;//縣市端代碼,例如:AccountSource.HC
}
3-5 修改LocalExecution程式,在本機跑測試用
程式位置在src->main->java->execution->LocalExecution.java
在大約第46行的地方,改成要判斷的syncdata回傳資料型態
iUniqueIDTypeStringMap.put(IUniqueIDType.ACCOUNT, "test");
像新竹市可用帳號判斷,IUniqueIDType改用ACCOUNT,並直接帶入測試用的帳號名稱
下一行取設定檔的路徑也要修改
DataRequest dataRequest = new DataRequest(settings, "../client.properties", iUniqueIDTypeStringMap);
再下一行可以換不同的IUniqueIDType以測試是否可用其他資料型態如PERSONID反查
3-6 修改 test package下面的測試程式
位置在src->test->java->RequestTest.java
修改方式同上,改成要判斷的syncdata回傳資料型態IUniqueIDType
四、上傳並更新cncauthserver及CncResource程式
重新發佈二個程式後,到縣市IDP本地管理頁面,使用管理帳號登入修正應用程式的flow及scpoe選項,如下圖
如果前面步驟合併分支成功,scope選項會多出一個syncdata可勾選, oauth flow會多出token及client_credentials可勾選
帳號管理平台
本部認證程式
五、編譯專案後,執行測試程式(右鍵run)
簡單執行流程如下:
新建帳號平臺選完學校,輸完個資,按下一步,會呼叫SPI
SPI的執行會先產生ExecutorService(Wildfly自動產生),然後把呼叫遠端SYNCDATA API的工作交給另一個執行緒執行
該執行緒會去取得TOKEN,並且以非同步(另一個執行緒)來問SYNCDATA REST API
如果成功,就會在終端機畫面看到回傳的資料了,長得像這樣
08 Aug 2019 16:06:32,210 execution.DataRequest execution.DataRequest.fetchAccessToken(DataRequest.java:120)
Bearer Access Token : {"access_token":"E8gpzjEUfU12hIPMJoq_Kd1nZHzI9mHuCg0KibG1vIo","scope":"syncdata","token_type":"Bearer","expires_in":3600}
08 Aug 2019 16:06:32,376 assets.tools.CNCUtils assets.tools.CNCUtils.getISODateTime(CNCUtils.java:775)
ISO DateTime -> 2019-08-08T08:06:32.355Z
08 Aug 2019 16:06:32,390 assets.tools.CNCUtils assets.tools.CNCUtils.addExpireDT(CNCUtils.java:567)
Expire DateTime -> 2019-08-08T09:06:32.355Z
08 Aug 2019 16:06:32,390 RequestTest RequestTest.doTest(RequestTest.java:31)
Map : {縣市帳號=test}
08 Aug 2019 16:06:32,394 assets.tools.CNCUtils assets.tools.CNCUtils.getISODateTime(CNCUtils.java:775)
ISO DateTime -> 2019-08-08T08:06:32.394Z
08 Aug 2019 16:06:32,696 execution.DataRequest execution.DataRequest.fetchSyncData(DataRequest.java:149)
Map : {縣市帳號=testc}
08 Aug 2019 16:06:33,207 execution.DataRequest execution.DataRequest.fetchSyncData(DataRequest.java:160)
Json : {"ACCOUNT":"testc"}
08 Aug 2019 16:06:34,097 execution.DataRequest execution.DataRequest.fetchSyncData(DataRequest.java:166)
Data : [{"username":"test","fullname":"測試","email":"hcstudy@hc.edu.tw","schoolid":"183306","titles":[{"schoolid":"189999","titles":["教師","教學設備組組長"]},{"schoolid":"183306","titles":["教師","教學設備組組長"]}],"classinfo":[{"year":null,"semester":null,"schoolid":"189999","grade":"","classno":"","classtitle":"年班"},{"year":null,"semester":null,"schoolid":"183306","grade":"","classno":"","classtitle":"年班"}],"educloudroles":{"usage":"教育雲","roles":[{"appname":"edumail","schoolid":"189999","titles":["教師","教學設備組組長"]},{"appname":"edumail","schoolid":"183306","titles":["教師","教學設備組組長"]}]},"guid":"c48b8904faf5f9c47c747516c8737690cb68244f934bd40c29ad7734e7","pid":"C123456789","openid":"https://openid.edu.tw/user/test"}]