The configuration parameters of the OAuth2 client are very many, although the Id Server solves the problem of creating an OAuth2 client through the console visualization. However, how to further reduce the difficulty of using OAuth2 and convert the created OAuth2 client into configuration has become a rigid requirement, which is not difficult to achieve from a technical point of view.
Let's take a look at the effect first. Click the configuration generation button to directly generate the Spring Security client yaml
configuration:
How is this effect achieved?
highlightjs
Mainly relying on the code highlighting library highlightjs, we usually see a lot of colorful code blocks in the major technical communities rely on this JS library, even my own technology blog felord.cn uses this class library for code Fragment beautification. It's simple to use:
<!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>
Introduce a style and highlight.js library, plus an initialization script and you are done. Then write the indented code in <pre><code>
. Note that the code
tag should be added with the class
class corresponding to the language or script. Effect:
accomplish
At this point, the idea is very clear. It is enough to make the value of the parameter item dynamic. I expect to achieve this effect:
<pre >
<code class="yaml">
spring:
#
application:
name: ${appName}
</code>
</pre>
But in fact, I was careless. I used the thymeleaf template. I didn't find a way for thymeleaf to solidify the configuration items to the page, so this indented format was generated by the backend, and then rendered according to the requirements of thymeleaf , so I wrote a Very complicated method:
@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";
}
The effect is naturally there, but it is very unsatisfactory.
Unable to generate comments, and line wrapping is uncontrolled, especially with 9 Maps , it drives me crazy.
optimization
Am I overthinking the problem? So in the end I did this with the format template of 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);
Of course, this is for compatibility with Java8 . If you change to Java17 , you can directly use string templates. I can even write comments here. The final effect is as follows:
The effect is much better than the previous one. Of course, maybe you have a better solution, let us brainstorm.
About Id Server
Warehouse address: https://github.com/NotFound403/id-server welcome star.
Id Server is an open source authorization server based on Spring Authorization Server , which greatly reduces the difficulty of learning and using OAuth2 authorization server, provides UI console, dynamic permission control, and facilitates OAuth2 client management. It can generate Spring Security configuration with one click, out of the box It can be deployed with a small amount of configuration modification. The code is open source, which is convenient for secondary development. It supports four client authentication methods and three authorization modes of OAuth2 . Welcome to learn to use and participate in code contributions.
关注公众号:Felordcn 获取更多资讯
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。