关于java:OAuth2授权服务器Id-Server一键生成配置原理

33次阅读

共计 3903 个字符,预计需要花费 10 分钟才能阅读完成。

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/NotFound40… 欢送 star。

Id Server 是一个基于 Spring Authorization Server 的开源的受权服务器,大大降低 OAuth2 受权服务器的学习应用难度,提供 UI 控制台,动静权限管制,不便 OAuth2 客户端治理,能够一键生成 Spring Security 配置,开箱即用,大量配置批改就可部署,代码开源,不便二次开发,反对 OAuth2 四种客户端认证形式和三种受权模式。欢送学习应用并参加代码奉献。

关注公众号:Felordcn 获取更多资讯

集体博客:https://felord.cn

正文完
 0