【发布时间】:2014-09-16 20:01:26
【问题描述】:
我希望限制对我的 RESTful API 中某些方法的访问。为了简单起见,我试图通过产品来做到这一点,允许访问资源 /athletes*,但我没有看到任何更好的控制方式,即我希望只允许 GET 请求而不是 POST 和 DELETE。是否有在产品的自定义资源路径部分中表达这一点的语法,或者我是否需要通过条件流来处理它,例如检查产品名称以查看他们是否可以访问?
【问题讨论】:
标签: apigee
我希望限制对我的 RESTful API 中某些方法的访问。为了简单起见,我试图通过产品来做到这一点,允许访问资源 /athletes*,但我没有看到任何更好的控制方式,即我希望只允许 GET 请求而不是 POST 和 DELETE。是否有在产品的自定义资源路径部分中表达这一点的语法,或者我是否需要通过条件流来处理它,例如检查产品名称以查看他们是否可以访问?
【问题讨论】:
标签: apigee
我用 Scopes 来做这件事,但最后我不得不做一点小事。这假设您至少为 access_tokens 使用了 client_credentials 授权(VerifyAPIKey 策略不直接支持范围)。
首先为 /v1/content(基本路径 /v1,路径后缀 /content)创建一个 API 代理。然后创建两个资源。
<Flows>
<Flow name="Content Read">
<Description/>
<Request>
<Step>
<FaultRules/>
<Name>RegEx-Check-Scope-READ-Content</Name>
</Step>
</Request>
<Response />
<Condition>(proxy.pathsuffix MatchesPath "/content") and (request.verb = "GET")</Condition>
</Flow>
<Flow name="Content Create">
<Description/>
<Request>
<Step>
<FaultRules/>
<Name>RegEx-Check-Scope-POST-Content</Name>
</Step>
</Request>
<Response />
<Condition>(proxy.pathsuffix MatchesPath "/content") and (request.verb = "POST")</Condition>
</Flow>
然后创建一个具有 CONTENT-READ 和 CONTENT-WRITE 范围的产品,如下所示:
现在,您可以创建仅包含 CONTENT-READ 的第二个产品以将某些应用程序限制为只读,或者您可以生成具有如下范围的 access_token:
<OAuthV2 name="GenerateAccessTokenClient">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>3600000</ExpiresIn>
<SupportedGrantTypes>
<GrantType>client_credentials</GrantType>
</SupportedGrantTypes>
<GrantType>request.formparam.grant_type</GrantType>
<Scope>request.formparam.scope</Scope>
<GenerateResponse/>
</OAuthV2>
使用两个产品可能更容易实施应用级别,但传递范围也让用户是一个三足 Oauth 添加限制。无论如何,当您生成 access_token 时,策略将创建一个名为“范围”的 Apigee 变量,其中将包含您在生成 access_token 时包含的范围。如果您在生成 access_token 时未指定范围,您将从包含在范围变量中的产品中获取所有范围,如下所示:
scope: CONTENT-READ CONTENT-WRITE
它只是一个长字符串,用空格分隔。而且似乎没有一种简单的方法可以将其放入流的条件中,因此我添加了一个 RegEx 策略来检查允许的范围是否在范围变量中,如下所示:
<RegularExpressionProtection async="false" continueOnError="false" enabled="true" name="RegEx-Check-Scope-POST-Content">
<DisplayName>RegEx Check Scope POST-Content</DisplayName>
<FaultRules/>
<Properties/>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>>
<Variable name="scope">
<Pattern>^((?!CONTENT-WRITE).)*$</Pattern>
</Variable>
<Source>request</Source>
</RegularExpressionProtection>
如果 CONTENT-WRITE 不在范围字符串中,则正则表达式返回 true。如果正则表达式返回 true,那么它会引发错误并停止处理,因此应用程序不会进入 POST。
让我知道这是否有意义(只需几个步骤...)
【讨论】:
在 API 代理页面(不是产品页面)上,您可以添加资源。其中,您可以指明您允许的方法(或请求动词)。这与基于请求动词在流程上使用条件相同。例如,如果您将<Condition>(request.verb = &quot;POST&quot;)</Condition> 添加到您的捆绑包中的 API 流,这意味着 该 特定流将仅在您的请求动词为 POST 时执行。该包的基本路径的所有其他动词都将被忽略。
这样,您的 API 包只允许特定的请求动词。
【讨论】:
如果您尝试使用 API 产品对资源 + 动词进行精细控制,您可以将 API 代理代码中的变量 flow.resource.name 设置为:
"/" + request.verb + "/" + proxy.pathsuffix
这会给你留下像/GET/products/1234-567 这样的东西。变量 flow.resource.name 是在使用 VerifyAPIKey 策略时针对 API 产品配置的 API 资源路径进行验证的变量。
【讨论】: