JWT策略执行、IP白名单和速率限制:使用Mulesoft、API安全和Cloudhub 2.0
本教程全面介绍了如何在API Manager中使用基于RAML的示例项目实施JWT策略执行。这在通过Anypoint平台的API Manager应用策略时特别有用。在此过程中,您还将学习如何使用第三方认证提供商(如Auth0)保护特定的API端点。
在本项目中,应用了以下策略以增强API安全性和流量控制:
先决条件
- Anypoint Studio 7.21(默认兼容Java 17)
- Java 17
- Anypoint Platform账户
- SOAPUI + POSTMAN
- Maven
观看视频教程以全面了解概念。
参考下图理解JWT(JSON Web Token)认证过程的工作原理。
- 客户端首先调用认证提供商,通过发送客户端ID、客户端密钥和grant_type获取令牌。
- 一旦收到令牌,客户端使用它调用实际的资源服务器端点。
- 资源服务器通过调用认证提供商来验证令牌。
- 如果令牌有效,向客户端返回200 OK响应。
- 如果令牌无效,返回错误响应。
下面包含了相关的RAML文件详情供参考。
安全方案RAML文件
jwt-token.raml
此文件定义了基于JWT的安全方案,指定了应如何传递和验证令牌。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#%RAML 1.0 SecurityScheme
type: x-jwt
description: |
This API uses JWT for authentication. Pass the token in the Authorization header as "Bearer {token}".
describedBy:
headers:
Authorization:
description: |
JWT access token in the format "Bearer {token}".
type: string
required: true
example: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
responses:
401:
description: |
Unauthorized. JWT is missing, invalid, or expired.
|
oauth2.raml
此文件定义了OAuth 2.0安全方案,客户端必须获取访问令牌并在Authorization头中以"Bearer {token}“格式包含它。它支持常见的授权类型,如authorization_code和client_credentials,以及范围访问控制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#%RAML 1.0 SecurityScheme
type: OAuth 2.0
description: |
This API is secured using OAuth 2.0. Obtain an access token and include it in the Authorization header as "Bearer {token".
describedBy:
headers:
Authorization:
description: |
Used to send the OAuth 2.0 access token. Format: "Bearer {token}".
type: string
required: true
example: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
responses:
401:
description: |
Unauthorized. Access token is missing, invalid, or expired.
403:
description: |
Forbidden. The access token does not have the required scopes or permissions.
settings:
authorizationUri: https://auth.example.com/oauth2/authorize
accessTokenUri: https://auth.example.com/oauth2/token
authorizationGrants: [ authorization_code, client_credentials ]
scopes: [ read, write, admin ]
|
basic-auth-details.raml
此文件定义了基本认证方案,使用在Authorization头中传递的标准用户名和密码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#%RAML 1.0 SecurityScheme
type: Basic Authentication
description: |
Basic Authentication using username and password.
describedBy:
headers:
Authorization:
description: |
Standard HTTP Basic Authentication header. Value must be "Basic base64(username:password)".
type: string
required: true
responses:
401:
description: Unauthorized. Invalid or missing credentials.
|
特征文件
特征文件定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#%RAML 1.0 Trait
usage: Apply to collection GET endpoints to support pagination.
queryParameters:
page:
type: integer
required: false
minimum: 1
default: 1
description: The page number to retrieve (starting from 1).
example: 2
pageSize:
type: integer
required: false
minimum: 1
maximum: 100
default: 20
description: The number of items per page.
example: 10
responses:
200:
headers:
X-Total-Count:
type: integer
description: Total number of items available.
example: 57
X-Total-Pages:
type: integer
description: Total number of pages available.
example: 6
X-Current-Page:
type: integer
description: The current page number.
example: 2
X-Page-Size:
type: integer
description: The number of items per page in this response.
example: 10
|
类型RAML文件
以下RAML文件定义了API中使用的数据类型:
Booking.raml
定义Booking数据类型,包括id、hotelId、guestName、checkInDate、checkOutDate、rooms和status等字段。它代表一个完整的酒店预订,包含验证和示例数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
#%RAML 1.0 DataType
type: object
properties:
id:
type: integer
description: Unique booking identifier
example: 1001
hotelId:
type: integer
description: ID of the booked hotel
example: 101
guestName:
type: string
required: true
description: Name of the guest
example: "Alice Smith"
checkInDate:
type: date-only
required: true
description: Check-in date
example: 2024-07-01
checkOutDate:
type: date-only
required: true
description: Check-out date
example: 2024-07-05
rooms:
type: integer
required: true
minimum: 1
description: Number of rooms booked
example: 2
status:
type: string
enum: [ confirmed, cancelled, pending ]
description: Booking status
example: confirmed
example:
id: 1001
hotelId: 101
guestName: "Alice Smith"
checkInDate: 2024-07-01
checkOutDate: 2024-07-05
rooms: 2
status: confirmed
|
概述了提交酒店预订请求所需的数据格式。它包括hotelId、guestName、checkInDate、checkOutDate和rooms等必填字段,每个字段都有验证规则。此文件排除了通常由系统设置的字段,如id和status。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#%RAML 1.0 DataType
type: object
properties:
hotelId:
type: integer
required: true
guestName:
type: string
required: true
checkInDate:
type: date-only
required: true
checkOutDate:
type: date-only
required: true
rooms:
type: integer
required: true
minimum: 1
example:
hotelId: 101
guestName: "Alice Smith"
checkInDate: 2024-07-01
checkOutDate: 2024-07-05
rooms: 2
|
ErrorResponse.raml
定义了一个标准的错误响应对象,包含一个必需的属性:message。此消息提供有关遇到的错误的详细信息,例如缺少资源、无效输入或认证失败。
1
2
3
4
5
6
7
8
9
|
#%RAML 1.0 DataType
type: object
properties:
message:
type: string
required: true
description: Error message
example:
message: "Resource not found."
|
Hotel.raml
表示API响应中使用的完整Hotel数据类型。它包括以下属性:
- id: 酒店的唯一标识符
- name: 酒店名称(必需)
- address: 酒店地址(必需)
- rating: 可选的浮点值(1-5),表示酒店的评分
- amenities: 可用功能的可选列表(例如"wifi”、“pool”)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#%RAML 1.0 DataType
type: object
description: Data type for hotel
properties:
id:
type: integer
description: Unique hotel identifier
example: 101
name:
type: string
required: true
description: Name of the hotel
example: "Grand Plaza"
address:
type: string
required: true
description: Address of the hotel
example: "123 Main St, Cityville"
rating?:
type: number
format: float
minimum: 1
maximum: 5
description: Hotel rating (1-5 stars)
example: 4.5
amenities?:
type: array
items: string
description: List of amenities
example: [ "wifi", "pool", "gym" ]
example:
id: 101
name: "Grand Plaza"
address: "123 Main St, Cityville"
rating: 4.5
amenities: [ "wifi", "pool", "gym" ]
additionalProperties: false
|
指定提交新酒店预订的格式和必需详细信息。它包括:
- name(字符串,必需):酒店名称
- address(字符串,必需):酒店地址
- rating(数字,可选):酒店评分,从1到5(浮点数)
- amenities(字符串数组,可选):酒店设施列表,如"wifi"、“pool”、“gym”
此类型在POST或PUT请求中发送酒店详细信息时使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#%RAML 1.0 DataType
type: object
properties:
name:
type: string
required: true
address:
type: string
required: true
rating?:
type: number
format: float
minimum: 1
maximum: 5
amenities?:
type: array
items: string
example:
name: "Grand Plaza"
address: "123 Main St, Cityville"
rating: 4.5
amenities: [ "wifi", "pool", "gym" ]
additionalProperties: false
|
order-api-security.raml
此RAML文件定义了包含安全和数据类型的酒店预订API:
- 标题:order-api-security
- 描述:用于酒店预订管理的API
- 媒体类型:application/json
- 协议:HTTP
- 版本:v1
- 基础URI:http://api.example.com/hotel-booking/v1
安全方案:
特征:
包含的数据类型:
- Hotel
- HotelInput
- Booking
- BookingInput
- ErrorResponse
端点:
- /hotels 用于列出和创建酒店(GET支持分页)
- /hotels/{hotelId} 用于检索、更新和删除特定酒店
API由basicAuth、oAuth2和jwtToken方案保护。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#%RAML 1.0
title: order-api-security
description: "This api contain the hotel booking details"
mediaType:
- application/json
protocols:
- HTTP
version: v1
baseUri: http://api.example.com/hotel-booking/v1
securitySchemes:
basicAuth: !include AUTH/basic-auth-details.raml
oAuth2: !include AUTH/oauth2.raml
jwtToken: !include AUTH/jwt-token.raml
traits:
paginated: !include TRAIT/trait.raml
types:
Hotel: !include TYPE/Hotel.raml
HotelInput: !include TYPE/HotelInput.raml
Booking: !include TYPE/Booking.raml
BookingInput: !include TYPE/BookingInput.raml
ErrorResponse: !include TYPE/ErrorResponse.raml
securedBy: [ basicAuth, oAuth2,jwtToken]
/hotels:
get:
description: Get a paginated list of hotels.
is: [ paginated ]
responses:
200:
description: Successful response with a list of hotels.
body:
application/json:
type: Hotel[]
example:
- id: 101
name: "Grand Plaza"
address: "123 Main St, Cityville"
rating: 4.5
amenities: [ "wifi", "pool", "gym" ]
- id: 102
name: "Ocean View"
address: "456 Beach Rd, Seaside"
rating: 4.0
amenities: [ "wifi", "spa" ]
post:
description: Create a new hotel.
body:
application/json:
type: HotelInput
example:
name: "Grand Plaza"
address: "123 Main St, Cityville"
rating: 4.5
amenities: [ "wifi", "pool", "gym" ]
responses:
201:
description: Hotel created successfully.
body:
application/json:
type: Hotel
example:
id: 103
name: "Mountain Retreat"
address: "789 Hilltop Ave, Mountainview"
rating: 5
amenities: [ "wifi", "sauna" ]
/hotels/{hotelId}:
uriParameters:
hotelId:
type: integer
required: true
description: Unique hotel identifier
example: 101
get:
description: Get details of a specific hotel.
responses:
200:
description: Successful response with hotel details.
body:
application/json:
type: Hotel
example:
id: 101
name: "Grand Plaza"
address: "123 Main St, Cityville"
rating: 4.5
amenities: [ "wifi", "pool", "gym" ]
put:
description: Update details of a specific hotel
body:
application/json:
type: HotelInput
example:
name: "Grand Plaza Updated"
address: "123 Main St, Cityville"
rating: 4.7
amenities: [ "wifi", "pool", "gym", "spa" ]
responses:
200:
description: Hotel updated successfully.
body:
application/json:
type: Hotel
example:
id: 101
name: "Grand Plaza Updated"
address: "123 Main St, Cityville"
rating: 4.7
amenities: [ "wifi", "pool", "gym", "spa" ]
delete:
description: Delete a specific hotel.
responses:
204:
description: Hotel deleted successfully. No content.
|
现在,将您的API发布到Exchange。
要在本地实施项目,请选择如下所示的脚手架选项。
对于实施和自动发现,我假设您已经熟悉,因此这里不涵盖详细信息。
一切就绪后,将项目部署到CloudHub 2.0,它应该显示为正在运行。
现在,登录或注册Auth0提供商以获取JWKS URL。
导航至Auth0 > 我的配置文件 > 应用程序 > 设置 > 端点。
复制JWKS URL并将其粘贴到API Manager中的JWT策略配置中,如下所示。
下一步是获取令牌。您需要以下四条信息来请求它。(注意:此处显示的客户端密钥已修改以确保安全。)
1
2
3
4
5
6
|
{
"client_id":"j5WYzDUApVpIT9QbXQ6IHHXDcAHYrvP1",
"client_secret":"hnQmxxsxsxsxsxsoL73qxqOmX1fDV37SN4wYjEMhhkj05d-xlR4oeKExY8PFDYm39iL",
"audience":"https://dev-0qcnlhjb6rx4ckcw.us.auth0.com/api/v2/",
"grant_type":"client_credentials"
}
|
接下来,使用令牌调用实际的API。如果令牌有效,您将收到预期的响应。
如果令牌无效,您将收到401 Unauthorized响应。
IP允许列表策略和速率限制很简单——请参考视频获取详细解释。
如果您觉得本教程有帮助,请点赞并随时提出任何问题!