| <!doctype html> |
| <html lang="en" dir="ltr"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <meta name="generator" content="Docusaurus v2.0.0-beta.4"> |
| <link rel="alternate" type="application/rss+xml" href="/blog/rss.xml" title="Apache ShenYu Blog RSS Feed"> |
| <link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" title="Apache ShenYu Blog Atom Feed"> |
| <link rel="search" type="application/opensearchdescription+xml" title="Apache ShenYu" href="/opensearch.xml"> |
| <link rel="alternate" type="application/rss+xml" href="/news/rss.xml" title="Apache ShenYu Blog RSS Feed"> |
| <link rel="alternate" type="application/atom+xml" href="/news/atom.xml" title="Apache ShenYu Blog Atom Feed"><title data-react-helmet="true">Sign Plugin | Apache ShenYu</title><meta data-react-helmet="true" property="og:url" content="https://shenyu.apache.org//docs/2.5.0/plugin-center/security/sign-plugin"><meta data-react-helmet="true" name="docsearch:language" content="en"><meta data-react-helmet="true" name="docsearch:version" content="2.5.0"><meta data-react-helmet="true" name="docsearch:docusaurus_tag" content="docs-default-2.5.0"><meta data-react-helmet="true" property="og:title" content="Sign Plugin | Apache ShenYu"><meta data-react-helmet="true" name="description" content="sign plugin"><meta data-react-helmet="true" property="og:description" content="sign plugin"><meta data-react-helmet="true" name="keywords" content="sign"><link data-react-helmet="true" rel="shortcut icon" href="/img/favicon.svg"><link data-react-helmet="true" rel="canonical" href="https://shenyu.apache.org//docs/2.5.0/plugin-center/security/sign-plugin"><link data-react-helmet="true" rel="alternate" href="https://shenyu.apache.org//docs/2.5.0/plugin-center/security/sign-plugin" hreflang="en"><link data-react-helmet="true" rel="alternate" href="https://shenyu.apache.org//zh/docs/2.5.0/plugin-center/security/sign-plugin" hreflang="zh"><link data-react-helmet="true" rel="alternate" href="https://shenyu.apache.org//docs/2.5.0/plugin-center/security/sign-plugin" hreflang="x-default"><link data-react-helmet="true" rel="preconnect" href="https://BH4D9OD16A-dsn.algolia.net" crossorigin="anonymous"><link rel="stylesheet" href="/assets/css/styles.cc2d0c98.css"> |
| <link rel="preload" href="/assets/js/runtime~main.19526316.js" as="script"> |
| <link rel="preload" href="/assets/js/main.0feaae07.js" as="script"> |
| </head> |
| <body> |
| <script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus"> |
| <div><a href="#" class="skipToContent_OuoZ">Skip to main content</a></div><nav class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Navigation bar toggle" class="navbar__toggle clean-btn" type="button" tabindex="0"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><img src="/img/logo.svg" alt="Apache ShenYu Logo" class="themedImage_TMUO themedImage--light_4Vu1 navbar__logo"><img src="/img/logo-light.svg" alt="Apache ShenYu Logo" class="themedImage_TMUO themedImage--dark_uzRr navbar__logo"></a></div><div class="navbar__items navbar__items--right"><a class="navbar__item navbar__link" href="/download">Download</a><a class="navbar__item navbar__link" href="/document">Docs</a><a class="navbar__item navbar__link" href="/community/contributor-guide">Community</a><a class="navbar__item navbar__link" href="/team">Team</a><a class="navbar__item navbar__link" href="/event">Event</a><a class="navbar__item navbar__link" href="/news">News</a><a class="navbar__item navbar__link" href="/blog">Blog</a><a class="navbar__item navbar__link" href="/users">Users</a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a class="navbar__item navbar__link">ASF</a><ul class="dropdown__menu"><li><a href="https://www.apache.org/" target="_blank" rel="noopener noreferrer" class="dropdown__link">Foundation</a></li><li><a href="https://www.apache.org/licenses/" target="_blank" rel="noopener noreferrer" class="dropdown__link">License</a></li><li><a href="https://www.apache.org/events/current-event" target="_blank" rel="noopener noreferrer" class="dropdown__link">Events</a></li><li><a href="https://www.apache.org/security/" target="_blank" rel="noopener noreferrer" class="dropdown__link">Security</a></li><li><a href="https://www.apache.org/foundation/sponsorship.html" target="_blank" rel="noopener noreferrer" class="dropdown__link">Sponsorship</a></li><li><a href="https://www.apache.org/foundation/policies/privacy.html" target="_blank" rel="noopener noreferrer" class="dropdown__link">Privacy</a></li><li><a href="https://www.apache.org/foundation/thanks.html" target="_blank" rel="noopener noreferrer" class="dropdown__link">Thanks</a></li></ul></div><a href="https://github.com/apache/shenyu" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link"><span>GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_wgqa"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a href="#" class="navbar__item navbar__link"><span><svg t="1631348384596" class="icon" viewBox="0 0 1024 1024" version="1.1" style="vertical-align:text-bottom;margin-right:5px" p-id="557" width="20" height="20"><path d="M547.797333 638.208l-104.405333-103.168 1.237333-1.28a720.170667 720.170667 0 0 0 152.490667-268.373333h120.448V183.082667h-287.744V100.906667H347.605333v82.218666H59.818667V265.386667h459.178666a648.234667 648.234667 0 0 1-130.304 219.946666 643.242667 643.242667 0 0 1-94.976-137.728H211.541333a722.048 722.048 0 0 0 122.453334 187.434667l-209.194667 206.378667 58.368 58.368 205.525333-205.525334 127.872 127.829334 31.232-83.84m231.424-208.426667h-82.218666l-184.96 493.312h82.218666l46.037334-123.306667h195.242666l46.464 123.306667h82.218667l-185.002667-493.312m-107.690666 287.744l66.56-178.005333 66.602666 178.005333z" fill="currentColor" p-id="558"></path></svg><span>English</span></span></a><ul class="dropdown__menu"><li><a href="/docs/2.5.0/plugin-center/security/sign-plugin" target="_self" rel="noopener noreferrer" class="dropdown__link dropdown__link--active" style="text-transform:capitalize">English</a></li><li><a href="/zh/docs/2.5.0/plugin-center/security/sign-plugin" target="_self" rel="noopener noreferrer" class="dropdown__link" style="text-transform:capitalize">简体中文</a></li></ul></div><div class="react-toggle toggle_2i4l react-toggle--disabled"><div class="react-toggle-track" role="button" tabindex="-1"><div class="react-toggle-track-check"><span class="toggle_iYfV">🌜</span></div><div class="react-toggle-track-x"><span class="toggle_iYfV">🌞</span></div><div class="react-toggle-thumb"></div></div><input type="checkbox" class="react-toggle-screenreader-only" aria-label="Switch between dark and light mode"></div><div class="searchBox_Bc3W"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search (Command+K)"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div class="main-wrapper docs-wrapper doc-page"><div class="docPage_lDyR"><button class="clean-btn backToTopButton_i9tI" type="button" title="Scroll to top"><svg viewBox="0 0 24 24" width="28"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" fill="currentColor"></path></svg></button><aside class="docSidebarContainer_0YBq"><div class="sidebar_a3j0"><nav class="menu thin-scrollbar menu_cyFh menuWithAnnouncementBar_+O1J"><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" href="/docs/2.5.0/index">Overview</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">Design</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">Deployment</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">Quick Start</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">User Guide</a></li><li class="menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#">Plugin Center</a><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Http Process</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Proxy</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Fault Tolerance</a></li><li class="menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#" tabindex="0">Security</a><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/docs/2.5.0/plugin-center/security/cryptor-request-plugin">CryptorRequest plugin</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/docs/2.5.0/plugin-center/security/cryptor-response-plugin">CryptorResponse plugin</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/docs/2.5.0/plugin-center/security/jwt-plugin">JWT plugin</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/docs/2.5.0/plugin-center/security/oauth2-plugin">OAuth2 Plugin</a></li><li class="menu__list-item"><a aria-current="page" class="menu__link menu__link--active active" tabindex="0" href="/docs/2.5.0/plugin-center/security/sign-plugin">Sign Plugin</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/docs/2.5.0/plugin-center/security/waf-plugin">Waf Plugin</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Observability</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Common</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Cache</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#" tabindex="0">Mock</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">Developer</a></li></ul></nav></div></aside><main class="docMainContainer_r8cw"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_zHA2"><div class="alert alert--warning margin-bottom--md" role="alert"><div>This is documentation for Apache ShenYu <b>2.5.0</b>, which is no longer actively maintained.</div><div class="margin-top--md">For up-to-date documentation, see the <b><a href="/docs/plugin-center/security/sign-plugin">latest version</a></b> (2.7.0).</div></div><div class="docItemContainer_oiyr"><article><span class="badge badge--secondary">Version: 2.5.0</span><div class="tocCollapsible_aw-L tocMobile_Tx6Y"><button type="button" class="clean-btn tocCollapsibleButton_zr6a">On this page</button></div><div class="markdown"><header><h1 class="h1Heading_dC7a">1. Overview</h1></header><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="11-plugin-name"></a>1.1 Plugin Name<a class="hash-link" href="#11-plugin-name" title="Direct link to heading">#</a></h2><ul><li>Sign Plugin</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="12-appropriate-scenario"></a>1.2 Appropriate Scenario<a class="hash-link" href="#12-appropriate-scenario" title="Direct link to heading">#</a></h2><ul><li>Support http header to authorize</li><li>Support http header and request body to authorize</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="13-plugin-functionality"></a>1.3 Plugin functionality<a class="hash-link" href="#13-plugin-functionality" title="Direct link to heading">#</a></h2><ul><li>Process signature authentication of requests.</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="14-plugin-code"></a>1.4 Plugin code<a class="hash-link" href="#14-plugin-code" title="Direct link to heading">#</a></h2><ul><li><p>Core Module: <code>shenyu-plugin-sign</code></p></li><li><p>Core Class: <code>org.apache.shenyu.plugin.sign.SignPlugin</code></p></li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="15-added-since-which-shenyu-version"></a>1.5 Added Since Which shenyu version<a class="hash-link" href="#15-added-since-which-shenyu-version" title="Direct link to heading">#</a></h2><ul><li>Since ShenYu 2.4.0</li></ul><header><h1 class="h1Heading_dC7a">2. How to use plugin</h1></header><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="21-plugin-use-procedure-chart"></a>2.1 Plugin-use procedure chart<a class="hash-link" href="#21-plugin-use-procedure-chart" title="Direct link to heading">#</a></h2><p><img src="/assets/images/plugin_use_en-8b5661551cdf92fdabc9cb2e7947cffc.jpg"></p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="22-import-pom"></a>2.2 Import pom<a class="hash-link" href="#22-import-pom" title="Direct link to heading">#</a></h2><ul><li>Introducing <code>sign</code> dependency in the <code>pom.xml</code> file of the gateway</li></ul><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI xml"><pre tabindex="0" class="prism-code language-xml codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"><!-- apache shenyu sign plugin start--></span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34"><</span><span class="token tag" style="color:#00009f">dependency</span><span class="token tag punctuation" style="color:#393A34">></span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34"><</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">></span><span class="token plain">org.apache.shenyu</span><span class="token tag punctuation" style="color:#393A34"></</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">></span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34"><</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">></span><span class="token plain">shenyu-spring-boot-starter-plugin-sign</span><span class="token tag punctuation" style="color:#393A34"></</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">></span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34"><</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">></span><span class="token plain">${project.version}</span><span class="token tag punctuation" style="color:#393A34"></</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">></span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34"></</span><span class="token tag" style="color:#00009f">dependency</span><span class="token tag punctuation" style="color:#393A34">></span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"><!-- apache shenyu sign plugin end--></span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="23-enable-plugin"></a>2.3 Enable plugin<a class="hash-link" href="#23-enable-plugin" title="Direct link to heading">#</a></h2><ul><li>In <code>shenyu-admin</code>--> BasicConfig --> Plugin --> <code>sign</code> set to enable.</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="24-config-plugin-with-authorize"></a>2.4 Config Plugin With Authorize<a class="hash-link" href="#24-config-plugin-with-authorize" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="241-aksk-config"></a>2.4.1 AK/SK Config<a class="hash-link" href="#241-aksk-config" title="Direct link to heading">#</a></h3><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2411-explanation"></a>2.4.1.1 Explanation<a class="hash-link" href="#2411-explanation" title="Direct link to heading">#</a></h4><ul><li>Manage and control the permissions of requests passing through the Apache ShenYu gateway.</li><li>Generate <code>AK/SK</code> and use it with the <code>Sign</code> plugin to achieve precise authority control based on URI level.</li></ul><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2412-tutorial"></a>2.4.1.2 Tutorial<a class="hash-link" href="#2412-tutorial" title="Direct link to heading">#</a></h4><p>First, we can add a piece of authentication information in <code>BasicConfig</code> - <code>Authentication</code></p><img src="/img/shenyu/basicConfig/authorityManagement/auth_manages_add_en.jpg" width="100%" height="70%"><p>Then configure this authentication information</p><img src="/img/shenyu/basicConfig/authorityManagement/auth_param_en.jpg" width="50%" height="40%"><ul><li>AppName:The application name associated with this account, it can can fill in or choose (data comes from the application name configured in the Metadata).</li><li>TelPhone:Telphone information.</li><li>AppParams:When the requested context path is the same as the AppName,add this value to the header, the key is <code>appParam</code>.</li><li>UserId:Give the user a name, just as an information record.</li><li>ExpandInfo:Description of the account.</li><li>PathAuth:After opening, the account only allows access to the resource path configured below.</li><li>ResourcePath:Allow access to the resource path, support path matching,e.g. <code>/order/**</code> .</li></ul><p>After submit, a piece of authentication information is generated, which contains <code>AppKey</code> and <code>AppSecret</code>, which is the <code>AK/SK</code> in the <code>Sign</code> plugin.</p><p>Please refer to the detailed instructions of the <code>Sign</code> plugin: <a href="/docs/2.5.0/plugin-center/authority-and-certification/sign-plugin">Sign Plugin</a>.</p><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2413-pathoperation"></a>2.4.1.3 PathOperation<a class="hash-link" href="#2413-pathoperation" title="Direct link to heading">#</a></h4><p>For the created authentication information, you can click <code>PathOperation</code> at the end of a piece of authentication information.</p><img src="/img/shenyu/basicConfig/authorityManagement/auth_manage_modifyPath_en.jpg" width="90%" height="80%"><ul><li>On the left is a list of configurable paths, and on the right is a list of paths that allow the account to access.</li><li>Check the resource path, click the <code>></code> or <code><</code> in the middle to move the checked data to the corresponding list.</li><li>In the list of configurable paths on the left, click "Editor" at the end of the account information line, and add them in the "Resource Path" in the pop-up box.</li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="242-implementation-of-gateway-technology"></a>2.4.2 Implementation of Gateway Technology<a class="hash-link" href="#242-implementation-of-gateway-technology" title="Direct link to heading">#</a></h3><ul><li>Adopt <code>AK/SK</code> authentication technical scheme.</li><li>Adopt authentication plug-in and Chain of Responsibility Pattern to realize.</li><li>Take effect when the authentication plugin is enabled and all interfaces are configured for authentication.</li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="243-authentication-guide"></a>2.4.3 Authentication Guide<a class="hash-link" href="#243-authentication-guide" title="Direct link to heading">#</a></h3><ul><li><p>Step 1: <code>AK/SK</code> is assigned by the gateway. For example, the <code>AK</code> assigned to you is: <code>1TEST123456781</code> SK is: ` 506eeb535cf740d7a755cb49f4a1536'</p></li><li><p>Step 2: Decide the gateway path you want to access, such as <code>/api/service/abc</code></p></li><li><p>Step 3: Construct parameters (the following are general parameters)</p></li></ul><table><thead><tr><th>Field</th><th>Value</th><th align="center">Description</th></tr></thead><tbody><tr><td>timestamp</td><td>current timestamp(String)</td><td align="center">The number of milliseconds of the current time(gateway will filter requests the before 5 minutes)</td></tr><tr><td>path</td><td>/api/service/abc</td><td align="center">The path that you want to request(Modify by yourself according to your configuration of gateway)</td></tr><tr><td>version</td><td>1.0.0</td><td align="center"><code>1.0.0</code> is a fixed string value</td></tr></tbody></table><p>Sort the above three field natually according to the key, then splice fields and fields, finally splice SK. The following is a code example.</p><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2431-generate-sign-with-request-header"></a>2.4.3.1 Generate sign with request header<a class="hash-link" href="#2431-generate-sign-with-request-header" title="Direct link to heading">#</a></h4><p>Step 1: First, construct a Map.</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI java"><pre tabindex="0" class="prism-code language-java codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"> |
| </span></span><span class="token-line" style="color:#393A34"><span class="token plain"> Map<String, String> map = Maps.newHashMapWithExpectedSize(3);</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> //timestamp is string format of millisecond. String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli())</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("timestamp","1571711067186"); // Value should be string format of milliseconds</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("path", "/api/service/abc");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("version", "1.0.0");</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>Step 2: Sort the <code>Keys</code> naturally, then splice the key and values, and finally splice the <code>SK</code> assigned to you.</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI java"><pre tabindex="0" class="prism-code language-java codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token plain">List<String> storedKeys = Arrays.stream(map.keySet()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .toArray(new String[]{}))</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .sorted(Comparator.naturalOrder())</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .collect(Collectors.toList());</span></span><span class="token-line" style="color:#393A34"><span class="token plain">final String sign = storedKeys.stream()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .map(key -> String.join("", key, params.get(key)))</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .collect(Collectors.joining()).trim()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .concat("506EEB535CF740D7A755CB4B9F4A1536");</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><ul><li>The returned sign value should be:<code>path/api/service/abctimestamp1571711067186version1.0.0506EEB535CF740D7A755CB4B9F4A1536</code></li></ul><p>Step 3: Md5 encryption and then capitalization.</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI java"><pre tabindex="0" class="prism-code language-java codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token plain">DigestUtils.md5DigestAsHex(sign.getBytes()).toUpperCase()</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><ul><li>The final returned value is: <code>A021BF82BE342668B78CD9ADE593D683</code>.</li></ul><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2432-generate-sign-with-request-header-and-request-body"></a>2.4.3.2 Generate sign with request header and request body<a class="hash-link" href="#2432-generate-sign-with-request-header-and-request-body" title="Direct link to heading">#</a></h4><p>Step 1: First, construct a Map, and the map must save every request body parameters</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI java"><pre tabindex="0" class="prism-code language-java codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"> |
| </span></span><span class="token-line" style="color:#393A34"><span class="token plain"> Map<String, String> map = Maps.newHashMapWithExpectedSize(3);</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> //timestamp is string format of millisecond. String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli())</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("timestamp","1660659201000"); // Value should be string format of milliseconds</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("path", "/http/order/save");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("version", "1.0.0");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> // if your request body is:{"id":123,"name":"order"}</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("id", "1");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("name", "order")</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p>Step 2: Sort the <code>Keys</code> naturally, then splice the key and values, and finally splice the <code>SK</code> assigned to you.</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI java"><pre tabindex="0" class="prism-code language-java codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token plain">List<String> storedKeys = Arrays.stream(map.keySet()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .toArray(new String[]{}))</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .sorted(Comparator.naturalOrder())</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .collect(Collectors.toList());</span></span><span class="token-line" style="color:#393A34"><span class="token plain">final String sign = storedKeys.stream()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .map(key -> String.join("", key, params.get(key)))</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .collect(Collectors.joining()).trim()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .concat("2D47C325AE5B4A4C926C23FD4395C719");</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><ul><li>The returned sign value should be:<code>id123nameorderpath/http/order/savetimestamp1660659201000version1.0.02D47C325AE5B4A4C926C23FD4395C719</code></li></ul><p>Step 3: Md5 encryption and then capitalization.</p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI java"><pre tabindex="0" class="prism-code language-java codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token plain">DigestUtils.md5DigestAsHex(sign.getBytes()).toUpperCase()</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><ul><li>The final returned value is: <code>35FE61C21F73E9AAFC46954C14F299D7</code>.</li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="244-request-gateway"></a>2.4.4 Request GateWay<a class="hash-link" href="#244-request-gateway" title="Direct link to heading">#</a></h3><ul><li><p>If your visited path is:<code>/api/service/abc</code>.</p></li><li><p>Address: http: domain name of gateway <code>/api/service/abc</code>.</p></li><li><p>Set <code>header</code>,<code>header</code> Parameter:</p></li></ul><table><thead><tr><th>Field</th><th align="right">Value</th><th align="center">Description</th></tr></thead><tbody><tr><td>timestamp</td><td align="right"><code>1571711067186</code></td><td align="center">Timestamp when signing</td></tr><tr><td>appKey</td><td align="right"><code>1TEST123456781</code></td><td align="center">The AK value assigned to you</td></tr><tr><td>sign</td><td align="right"><code>A90E66763793BDBC817CF3B52AAAC041</code></td><td align="center">The signature obtained above</td></tr><tr><td>version</td><td align="right"><code>1.0.0</code></td><td align="center"><code>1.0.0</code> is a fixed value.</td></tr></tbody></table><ul><li><p>The signature plugin will filter requests before <code>5</code> minutes by default</p></li><li><p>If the authentication fails, will return code <code>401</code>, message may change.</p></li></ul><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI json"><pre tabindex="0" class="prism-code language-json codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token property" style="color:#36acaa">"code"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">401</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token property" style="color:#36acaa">"message"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"sign is not pass,Please check you sign algorithm!"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token property" style="color:#36acaa">"data"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null keyword" style="color:#00009f">null</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="245-plugin-config"></a>2.4.5 Plugin Config<a class="hash-link" href="#245-plugin-config" title="Direct link to heading">#</a></h3><p><img src="/assets/images/sign_open_en-7a1bcfbe89eec35490eec64c037a7103.jpg"></p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="246-selector-config"></a>2.4.6 Selector Config<a class="hash-link" href="#246-selector-config" title="Direct link to heading">#</a></h3><p><img src="/assets/images/selector-en-993bda66883505a34953d527663d7475.png"></p><ul><li><p>Only those matched requests can be authenticated by signature.</p></li><li><p>Selectors and rules, please refer to: <a href="/docs/2.5.0/user-guide/admin-usage/selector-and-rule">Selector And Rule Config</a></p></li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="247-rule-config"></a>2.4.7 Rule Config<a class="hash-link" href="#247-rule-config" title="Direct link to heading">#</a></h3><p><img src="/assets/images/rule-en-66585f6eca8f875a4a6e1fd5c65646d1.png"></p><ul><li>close(signRequestBody): generate signature with request header. </li><li>open(signRequestBody): generate signature with request header and request body.</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="25-examples"></a>2.5 Examples<a class="hash-link" href="#25-examples" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="251-verify-api-with-sign-plugin"></a>2.5.1 Verify api with sign plugin<a class="hash-link" href="#251-verify-api-with-sign-plugin" title="Direct link to heading">#</a></h3><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2511-plugin-config"></a>2.5.1.1 Plugin Config<a class="hash-link" href="#2511-plugin-config" title="Direct link to heading">#</a></h4><p><img src="/assets/images/sign_open_en-7a1bcfbe89eec35490eec64c037a7103.jpg"></p><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2512-selector-config"></a>2.5.1.2 Selector Config<a class="hash-link" href="#2512-selector-config" title="Direct link to heading">#</a></h4><p><img src="/assets/images/example-selector-en-5f344f0f789b9b37e2ddefe245149eaf.png"></p><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2513-rule-config"></a>2.5.1.3 Rule Config<a class="hash-link" href="#2513-rule-config" title="Direct link to heading">#</a></h4><p><img src="/assets/images/example-rule-en-503e8b5697e5aada40d67b999ce281c7.png"></p><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2515-add-appkeysecretkey"></a>2.5.1.5 Add AppKey/SecretKey<a class="hash-link" href="#2515-add-appkeysecretkey" title="Direct link to heading">#</a></h4><p><img src="/assets/images/example-sign-auth-en-7531558c55916cf987b149f58a336d16.png"></p><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_WiXH" id="2516-request-service-and-check-result"></a>2.5.1.6 Request Service and check result<a class="hash-link" href="#2516-request-service-and-check-result" title="Direct link to heading">#</a></h4><ul><li>build request params with <code>Authentication Guide</code>,</li></ul><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI java"><pre tabindex="0" class="prism-code language-java codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token plain">public class Test1 {</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> public static void main(String[] args) {</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> Map<String, String> map = Maps.newHashMapWithExpectedSize(3);</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> //timestamp为毫秒数的字符串形式 String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli())</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("timestamp","1660658725000"); //值应该为毫秒数的字符串形式</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("path", "/http/order/save");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("version", "1.0.0");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("id", "123");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("name", "order");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> // map.put("body", "{\"id\":123,\"name\":\"order\"}");</span></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"> |
| </span></span><span class="token-line" style="color:#393A34"><span class="token plain"> List<String> storedKeys = Arrays.stream(map.keySet()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .toArray(new String[]{}))</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .sorted(Comparator.naturalOrder())</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .collect(Collectors.toList());</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> final String sign = storedKeys.stream()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .map(key -> String.join("", key, map.get(key)))</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .collect(Collectors.joining()).trim()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .concat("2D47C325AE5B4A4C926C23FD4395C719");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> System.out.println(sign);</span></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"> |
| </span></span><span class="token-line" style="color:#393A34"><span class="token plain"> System.out.println(DigestUtils.md5DigestAsHex(sign.getBytes()).toUpperCase());</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><ul><li>signature without body: <code>path/http/order/savetimestamp1571711067186version1.0.02D47C325AE5B4A4C926C23FD4395C719</code></li><li>sign without body result is: <code>9696D3E549A6AEBE763CCC2C7952DDC1</code></li></ul><p><img src="/assets/images/result-1c40210c3da55750298242b3b037f289.png"></p><div class="codeBlockContainer_J+bg"><div class="codeBlockContent_csEI java"><pre tabindex="0" class="prism-code language-java codeBlock_rtdJ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_1zSZ"><span class="token-line" style="color:#393A34"><span class="token plain">public class Test2 {</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> public static void main(String[] args) {</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> Map<String, String> map = Maps.newHashMapWithExpectedSize(3);</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> //timestamp为毫秒数的字符串形式 String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli())</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("timestamp","1660659201000"); //值应该为毫秒数的字符串形式</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("path", "/http/order/save");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> map.put("version", "1.0.0");</span></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"> |
| </span></span><span class="token-line" style="color:#393A34"><span class="token plain"> List<String> storedKeys = Arrays.stream(map.keySet()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .toArray(new String[]{}))</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .sorted(Comparator.naturalOrder())</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .collect(Collectors.toList());</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> final String sign = storedKeys.stream()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .map(key -> String.join("", key, map.get(key)))</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .collect(Collectors.joining()).trim()</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> .concat("2D47C325AE5B4A4C926C23FD4395C719");</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> System.out.println(sign);</span></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"> |
| </span></span><span class="token-line" style="color:#393A34"><span class="token plain"> System.out.println(DigestUtils.md5DigestAsHex(sign.getBytes()).toUpperCase());</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_M3SB clean-btn">Copy</button></div></div><p><em>signature with body:<code>id123nameorderpath/http/order/savetimestamp1660659201000version1.0.02D47C325AE5B4A4C926C23FD4395C719</code></em>sign with body result is:<code>35FE61C21F73E9AAFC46954C14F299D7</code></p><p><img src="/assets/images/result-with-body-d430bbcc77fef2c8bdd89cace7d6e418.png"></p><header><h1 class="h1Heading_dC7a">3. How to disable plugin</h1></header><ul><li>In <code>shenyu-admin</code>--> BasicConfig --> Plugin --> <code>sign</code> set to disabled.</li></ul><header><h1 class="h1Heading_dC7a">4. Extension</h1></header><ul><li>Please refer to: <a href="/docs/2.5.0/developer/custom-sign-algorithm">dev-sign</a>.</li></ul></div><footer class="row docusaurus-mt-lg"><div class="col"><a href="https://github.com/apache/shenyu-website/edit/main/versioned_docs/version-2.5.0/plugin-center/security/sign-plugin.md" target="_blank" rel="noreferrer noopener"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_mS5F" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col lastUpdated_wj+Z"></div></footer></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/docs/2.5.0/plugin-center/security/oauth2-plugin"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« OAuth2 Plugin</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/docs/2.5.0/plugin-center/security/waf-plugin"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Waf Plugin »</div></a></div></nav></div></div><div class="col col--3"><div class="tableOfContents_vrFS thin-scrollbar"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#11-plugin-name" class="table-of-contents__link">1.1 Plugin Name</a></li><li><a href="#12-appropriate-scenario" class="table-of-contents__link">1.2 Appropriate Scenario</a></li><li><a href="#13-plugin-functionality" class="table-of-contents__link">1.3 Plugin functionality</a></li><li><a href="#14-plugin-code" class="table-of-contents__link">1.4 Plugin code</a></li><li><a href="#15-added-since-which-shenyu-version" class="table-of-contents__link">1.5 Added Since Which shenyu version</a></li><li><a href="#21-plugin-use-procedure-chart" class="table-of-contents__link">2.1 Plugin-use procedure chart</a></li><li><a href="#22-import-pom" class="table-of-contents__link">2.2 Import pom</a></li><li><a href="#23-enable-plugin" class="table-of-contents__link">2.3 Enable plugin</a></li><li><a href="#24-config-plugin-with-authorize" class="table-of-contents__link">2.4 Config Plugin With Authorize</a><ul><li><a href="#241-aksk-config" class="table-of-contents__link">2.4.1 AK/SK Config</a></li><li><a href="#242-implementation-of-gateway-technology" class="table-of-contents__link">2.4.2 Implementation of Gateway Technology</a></li><li><a href="#243-authentication-guide" class="table-of-contents__link">2.4.3 Authentication Guide</a></li><li><a href="#244-request-gateway" class="table-of-contents__link">2.4.4 Request GateWay</a></li><li><a href="#245-plugin-config" class="table-of-contents__link">2.4.5 Plugin Config</a></li><li><a href="#246-selector-config" class="table-of-contents__link">2.4.6 Selector Config</a></li><li><a href="#247-rule-config" class="table-of-contents__link">2.4.7 Rule Config</a></li></ul></li><li><a href="#25-examples" class="table-of-contents__link">2.5 Examples</a><ul><li><a href="#251-verify-api-with-sign-plugin" class="table-of-contents__link">2.5.1 Verify api with sign plugin</a></li></ul></li></ul></div></div></div></div></main></div></div></div> |
| <script src="/assets/js/runtime~main.19526316.js"></script> |
| <script src="/assets/js/main.0feaae07.js"></script> |
| </body> |
| </html> |