OAuth2客戶端的配置參數(shù)非常多猜旬,雖然Id Server通過控制臺可視化解決了創(chuàng)建OAuth2客戶端的問題觉义。但是如何進(jìn)一步降低OAuth2的使用難度,把創(chuàng)建的OAuth2客戶端轉(zhuǎn)化為配置成為了剛需,從技術(shù)角度上感覺也并不是很難實現(xiàn)蹭沛。
我們先來看看效果赂韵,點擊配置生成按鈕即可直接生成Spring Security的客戶端yaml
配置:
這個效果是如何實現(xiàn)的呢?
highlightjs
主要依托于highlightjs這個代碼高亮庫嫌蚤,平常我們在各大技術(shù)社區(qū)看到的五顏六色的代碼塊很多就依賴的這個JS庫辐益,連我自己的技術(shù)博客felord.cn都用了這個類庫來做代碼片段美化。它使用起來很簡單:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet"
>
<script src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</head>
<body>
<pre >
<code class="yaml">
spring:
#
application:
name: id-server
</code>
</pre>
</body>
</html>
引入一個風(fēng)格樣式和highlight.js庫脱吱,再加一個初始化腳本就完成了智政。然后在<pre><code>
中編寫帶縮進(jìn)的代碼就可以了,注意code
標(biāo)簽要加上對應(yīng)語言或者腳本的class
類箱蝠,出來就是這樣的效果:
實現(xiàn)
到這里思路就很明確了续捂,把參數(shù)項的值動態(tài)化就可以了,我期望達(dá)到這樣的效果:
<pre >
<code class="yaml">
spring:
#
application:
name: ${appName}
</code>
</pre>
但事實上我大意了宦搬,我用了thymeleaf模板牙瓢,我沒有找到thymeleaf可以固化配置項到頁面的辦法,所以這個帶縮進(jìn)的格式得后端生成间校,然后按照thymeleaf的要求渲染矾克,于是我寫了一個非常復(fù)雜的方法:
@GetMapping("/system/client/yaml/{id}")
public String yaml(Model model, @PathVariable String id) {
OAuth2Client oauth2Client = clientRepository.findClientById(id);
String clientName = oauth2Client.getClientName();
String clientId = oauth2Client.getClientId();
Set<RedirectUri> redirectUris = oauth2Client.getRedirectUris();
String uris = redirectUris.stream()
.map(RedirectUri::getRedirectUri)
.collect(Collectors.joining(","));
Set<OAuth2GrantType> authorizationGrantTypes = oauth2Client.getAuthorizationGrantTypes();
String types = authorizationGrantTypes.stream()
.map(OAuth2GrantType::getGrantTypeName)
.collect(Collectors.joining(","));
String method = oauth2Client.getClientAuthenticationMethods().stream()
.map(ClientAuthMethod::getClientAuthenticationMethod)
.collect(Collectors.joining(","));
String scopes = Stream.concat(
oauth2Client.getScopes().stream()
.map(OAuth2Scope::getScope), Stream.of(OidcScopes.OPENID))
.collect(Collectors.joining(","));
LinkedHashMap<String, Object> client = new LinkedHashMap<>();
LinkedHashMap<String, Object> clientRegistration = new LinkedHashMap<>();
clientRegistration.put("client-id", clientId);
clientRegistration.put("client-secret", "請?zhí)顚懩愕腛Auth2客戶端密碼");
clientRegistration.put("redirect-uri", "請從" + uris + "指定一個");
clientRegistration.put("authorization-grant-type", "請從 " + types + " 指定一個");
clientRegistration.put("client-authentication-method", method);
clientRegistration.put("scope", scopes);
client.put("registration",
Collections.singletonMap(clientName, clientRegistration));
client.put("provider", Collections.singletonMap(clientName,
Collections.singletonMap("issuer-uri", "http://localhost:9000")));
Map<String, Object> spring =
Collections.singletonMap("spring",
Collections.singletonMap("security",
Collections.singletonMap("oauth2",
Collections.singletonMap("client", client))));
DumperOptions dumperOptions = new DumperOptions();
dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Yaml yaml = new Yaml(dumperOptions);
String dump = yaml.dump(spring);
model.addAttribute("yaml", dump);
return "/system/client/yaml";
}
效果自然是有的,但是非常差強(qiáng)人意憔足。
無法生成注釋胁附,而且換行不受控制,尤其套了9個Map讓我抓狂四瘫。
優(yōu)化
是不是我把問題想得太復(fù)雜了呢汉嗽?于是最終我把yaml
的格式模板這樣做了:
String yml = "spring:\n" +
" security:\n" +
" oauth2:\n" +
" client:\n" +
" registration:\n" +
" # 這里為客戶端名稱可自行更改\n" +
" " + clientName + ":\n" +
" client-id: " + clientId + "\n" +
" # 密碼為注冊客戶端時的密碼\n" +
" client-secret: 請?zhí)顚懩洃浀腛Auth2客戶端密碼\n" +
" # 只能選擇一個\n" +
" redirect-uri: 請從" + uris + "指定一個\n" +
" # 只能選擇一個\n" +
" authorization-grant-type: " + types + "三選一\n" +
" client-authentication-method: " + method + "\n" +
" scope: " + scopes + "\n" +
" provider:\n" +
" " + clientName + ":\n" +
" # 要保證授權(quán)服務(wù)器地址可以被客戶端訪問\n" +
" issuer-uri: http://localhost:9000";
model.addAttribute("yaml", yml);
當(dāng)然這是為了兼容Java8,如果換了Java17直接就用字符串模板了找蜜,甚至這里我還能寫注釋饼暑,最終的效果是這樣的:
效果比上一個方案好了很多,當(dāng)然或許你還有更好的方案,讓我們集思廣益弓叛。
關(guān)于Id Server
倉庫地址:https://github.com/NotFound403/id-server 歡迎star彰居。
Id Server是一個基于Spring Authorization Server的開源的授權(quán)服務(wù)器,大大降低OAuth2授權(quán)服務(wù)器的學(xué)習(xí)使用難度撰筷,提供UI控制臺陈惰,動態(tài)權(quán)限控制,方便OAuth2客戶端管理毕籽,可以一鍵生成Spring Security配置抬闯,開箱即用,少量配置修改就可部署关筒,代碼開源溶握,方便二次開發(fā),支持OAuth2四種客戶端認(rèn)證方式和三種授權(quán)模式蒸播。歡迎學(xué)習(xí)使用并參與代碼貢獻(xiàn)睡榆。
關(guān)注公眾號:碼農(nóng)小胖哥,獲取更多資訊