OAuth2客戶端的配置參數非常多,雖然Id Server通過控制台可視化解決了創建OAuth2客戶端的問題。但是如何進一步降低OAuth2的使用難度,把創建的OAuth2客戶端轉化為配置成為了剛需,從技術角度上感覺也並不是很難實現。 我們先來看看效果,點擊配置生成按鈕即可直接生成Spring Se ...
OAuth2客戶端的配置參數非常多,雖然Id Server通過控制台可視化解決了創建OAuth2客戶端的問題。但是如何進一步降低OAuth2的使用難度,把創建的OAuth2客戶端轉化為配置成為了剛需,從技術角度上感覺也並不是很難實現。
我們先來看看效果,點擊配置生成按鈕即可直接生成Spring Security的客戶端yaml
配置:
這個效果是如何實現的呢?
highlightjs
主要依托於highlightjs這個代碼高亮庫,平常我們在各大技術社區看到的五顏六色的代碼塊很多就依賴的這個JS庫,連我自己的技術博客felord.cn都用了這個類庫來做代碼片段美化。它使用起來很簡單:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet"
href="https://felord.cn/css/gruvbox-dark.min.css">
<script src="//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>
引入一個風格樣式和highlight.js庫,再加一個初始化腳本就完成了。然後在<pre><code>
中編寫帶縮進的代碼就可以了,註意code
標簽要加上對應語言或者腳本的class
類,出來就是這樣的效果:
實現
到這裡思路就很明確了,把參數項的值動態化就可以了,我期望達到這樣的效果:
<pre >
<code class="yaml">
spring:
#
application:
name: ${appName}
</code>
</pre>
但事實上我大意了,我用了thymeleaf模板,我沒有找到thymeleaf可以固化配置項到頁面的辦法,所以這個帶縮進的格式得後端生成,然後按照thymeleaf的要求渲染,於是我寫了一個非常複雜的方法:
@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", "請填寫你的OAuth2客戶端密碼");
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";
}
效果自然是有的,但是非常差強人意。
無法生成註釋,而且換行不受控制,尤其套了9個Map讓我抓狂。
優化
是不是我把問題想得太複雜了呢?於是最終我把yaml
的格式模板這樣做了:
String yml = "spring:\n" +
" security:\n" +
" oauth2:\n" +
" client:\n" +
" registration:\n" +
" # 這裡為客戶端名稱可自行更改\n" +
" " + clientName + ":\n" +
" client-id: " + clientId + "\n" +
" # 密碼為註冊客戶端時的密碼\n" +
" client-secret: 請填寫您記憶的OAuth2客戶端密碼\n" +
" # 只能選擇一個\n" +
" redirect-uri: 請從" + uris + "指定一個\n" +
" # 只能選擇一個\n" +
" authorization-grant-type: " + types + "三選一\n" +
" client-authentication-method: " + method + "\n" +
" scope: " + scopes + "\n" +
" provider:\n" +
" " + clientName + ":\n" +
" # 要保證授權伺服器地址可以被客戶端訪問\n" +
" issuer-uri: http://localhost:9000";
model.addAttribute("yaml", yml);
當然這是為了相容Java8,如果換了Java17直接就用字元串模板了,甚至這裡我還能寫註釋,最終的效果是這樣的:
效果比上一個方案好了很多,當然或許你還有更好的方案,讓我們集思廣益。
關於Id Server
倉庫地址:https://github.com/NotFound403/id-server 歡迎star。
Id Server是一個基於Spring Authorization Server的開源的授權伺服器,大大降低OAuth2授權伺服器的學習使用難度,提供UI控制台,動態許可權控制,方便OAuth2客戶端管理,可以一鍵生成Spring Security配置,開箱即用,少量配置修改就可部署,代碼開源,方便二次開發,支持OAuth2四種客戶端認證方式和三種授權模式。歡迎學習使用並參與代碼貢獻。
關註公眾號:Felordcn 獲取更多資訊
博主:碼農小胖哥 出處:felord.cn 本文版權歸原作者所有,不可商用,轉載需要聲明出處,否則保留追究法律責任的權利。如果文中有什麼錯誤,歡迎指出。以免更多的人被誤導。 |