1. Overview
1.概述
In this tutorial, we’ll analyze how we can authenticate with REST Assured to test and validate a secured API properly.
在本教程中,我们将分析如何使用REST Assured进行验证,以正确测试和验证安全的API。
The tool provides support for several authentication schemes:
该工具提供对几种认证方案的支持。
- Basic Authentication
- Digest Authentication
- Form Authentication
- OAuth 1 and OAuth 2
And we’ll see examples for each one.
我们将看到每个人的例子。
2. Using Basic Authentication
2.使用基本认证
The basic authentication scheme requires the consumer to send user id and a password encoded in Base64.
基本认证方案要求消费者发送以Base64编码的用户ID和密码。
REST Assured provides an easy way to configure the credentials that the request requires:
REST Assured提供了一种简单的方法来配置请求所需的凭证。
given().auth()
.basic("user1", "user1Pass")
.when()
.get("http://localhost:8080/spring-security-rest-basic-auth/api/foos/1")
.then()
.assertThat()
.statusCode(HttpStatus.OK.value());
2.1. Preemptive Authentication
2.1.先发制人的认证
As we’ve seen on a previous post on Spring Security authentication, a server might use a challenge-response mechanism to indicate explicitly when the consumer needs authenticate to access the resource.
正如我们在上一篇关于Spring Security认证的文章中所看到的那样,服务器可能会使用挑战-响应机制来明确指示消费者何时需要进行认证以访问资源。
By default, REST Assured waits for the server to challenge before sending the credentials.
默认情况下,REST Assured在发送凭证之前会等待服务器提出挑战。
This can be troublesome in some cases, for example, where the server is configured to retrieve a login form instead of the challenge response.
这在某些情况下可能很麻烦,例如,服务器被配置为检索一个登录表格而不是挑战响应。
For this reason, the library provides the preemptive directive that we can use:
出于这个原因,该库提供了我们可以使用的preemptive指令。
given().auth()
.preemptive()
.basic("user1", "user1Pass")
.when()
// ...
With this in place, REST Assured will send the credentials without waiting for an Unauthorized response.
有了这一点,REST Assured将发送证书,而无需等待Unauthorized响应。
We hardly ever are interested in testing the server’s ability to challenge. Therefore, we can normally add this command to avoid complications and the overhead of making an additional request.
我们几乎没有对测试服务器的挑战能力感兴趣。因此,我们通常可以添加这个命令,以避免复杂化和发出额外请求的开销。
3. Using Digest Authentication
3.使用Digest认证
Even though this is also considered a “weak” authentication method, using Digest Authentication represents an advantage over the basic protocol.
尽管这也被认为是一种“弱 “认证方法,但使用加密认证比基本协议有优势。
This is due to the fact that this scheme avoids sending the password in cleartext.
这是由于该方案避免了以明文方式发送密码。
Despite this difference, implementing this form of authentication with REST Assured is very similar to the one we followed in the previous section:
尽管存在这种差异,但使用REST Assured实施这种形式的认证与我们在上一节中遵循的认证非常相似:。
given().auth()
.digest("user1", "user1Pass")
.when()
// ...
Note that, currently, the library supports only challenged authentication for this scheme, so we can’t use preemptive() as we did earlier.
请注意,目前,该库只支持这种方案的挑战式验证,所以我们不能像之前那样使用preemptive()。
4. Using Form Authentication
4.使用表格认证
Many services provide an HTML form for the user to authenticate by filling in the fields with their credentials.
许多服务提供了一个HTML表格,供用户通过在字段中填写他们的证书来进行认证。
When the user submits the form, the browser executes a POST request with the information.
当用户提交表格时,浏览器会执行一个带有信息的POST请求。
Normally, the form indicates the endpoint that it’ll call with its action attribute, and each input field corresponds with a form parameter sent in the request.
通常情况下,表单用其action属性指出它将调用的端点,而每个input字段都与请求中发送的表单参数相对应。
If the login form is simple enough and follows these rules, then we can rely on REST Assured to figure out these values for us:
如果登录表格足够简单并遵循这些规则,那么我们可以依靠REST Assured为我们算出这些值。
given().auth()
.form("user1", "user1Pass")
.when()
// ...
This is not an optimal approach, anyway, since REST Assured needs to perform an additional request and parse the HTML response to find the fields.
无论如何,这不是一个最佳的方法,因为REST Assured需要执行一个额外的请求并解析HTML响应以找到字段。
We also have to keep in mind that the process can still fail, for example, if the webpage is complex, or if the service is configured with a context path that is not included in the action attribute.
我们还必须记住,这个过程仍然可能失败,例如,如果网页很复杂,或者如果服务配置的上下文路径不包括在action属性中。
Therefore, a better solution is to provide the configuration ourselves, indicating explicitly the three required fields:
因此,更好的解决方案是由我们自己提供配置,明确指出三个必要的领域:。
given().auth()
.form(
"user1",
"user1Pass",
new FormAuthConfig("/perform_login", "username", "password"))
// ...
Apart from these basic configurations, REST Assured ships with functionality to:
除了这些基本配置外,REST Assured还具有以下功能。
- detect or indicate a CSRF token field in the webpage
- use additional form fields in the request
- log information about the authentication process
5. OAuth Support
5.支持OAuth
OAuth is technically an authorization framework, and it doesn’t define any mechanism for authenticating a user.
从技术上讲,OAuth是一个授权框架,它并没有定义任何认证用户的机制。
Still, it can be used as the basis for building an authentication and identity protocol, as is the case of OpenID Connect.
但是,它仍然可以被用作构建认证和身份协议的基础,正如OpenID Connect的情况一样。
5.1. OAuth 2.0
5.1.OAuth 2.0
REST Assured allows configuring the OAuth 2.0 access token to request a secured resource:
REST Assured允许配置OAuth 2.0访问令牌以请求安全资源:。
given().auth()
.oauth2(accessToken)
.when()
.// ...
The library doesn’t provide any help in obtaining the access token, so we’ll have to figure out how to do this ourselves.
库没有提供任何关于获取访问令牌的帮助,所以我们必须自己想办法来做这件事。
For the Client Credential and Password flows this is a simple task since the Token is obtained by just presenting the corresponding credentials.
对于客户凭证和密码流来说,这是一项简单的任务,因为只要出示相应的凭证就能获得令牌。
On the other hand, automating the Authorization Code flow might not be that easy, and we’ll probably need the help of other tools as well.
另一方面,授权码流程的自动化可能没有那么容易,我们可能还需要其他工具的帮助。
To understand correctly this flow and what it takes to obtain an Access Token, we can have a look at this great post on the subject.
为了正确理解这个流程,以及需要什么来获得一个访问令牌,我们可以看看这个关于这个主题的伟大帖子。
5.2. OAuth 1.0a
5.2.OAuth 1.0a
In the case of OAuth 1.0a, REST Assured supplies a method that receives a Consumer Key, Secret, Access Token and Token Secret to access a secured resource:
在OAuth 1.0a的情况下,REST Assured提供了一个接收消费者密钥、秘密、访问令牌和令牌秘密的方法,以访问安全资源。
given().accept(ContentType.JSON)
.auth()
.oauth(consumerKey, consumerSecret, accessToken, tokenSecret)
// ...
This protocol requires user input, therefore obtaining the last two fields won’t be a trivial task.
这个协议需要用户输入,因此,获得最后两个字段不会是一个微不足道的任务。
Note that we’ll need to add the scribejava-apis dependency in our project if we’re using OAuth 2.0 features with a version prior to 2.5.0, or if we’re making use of the OAuth 1.0a functionality.
请注意,如果我们使用2.5.0之前版本的OAuth 2.0功能,或者使用OAuth 1.0a功能,我们就需要在项目中添加scribejava-apis依赖项。
6. Conclusion
6.结论
In this tutorial, we’ve learned how we can authenticate to access secured APIs using REST Assured.
在本教程中,我们已经学会了如何使用REST Assured进行认证以访问安全的API。
The library simplifies the process of authentication for practically any scheme that we implemented.
该库简化了我们实施的几乎所有方案的认证过程。
As always, we can find working examples with instructions on our Github repo.
一如既往,我们可以在我们的Github repo上找到带有说明的工作实例。