1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

使用Oracle自治数据库(ADB)的REST数据服务(ORDS)快速创建博客应用的REST API

Last updated at Posted at 2019-08-07

文章在微信公众号[雷克斯碎碎念]同步发布, 欢迎扫码关注~

image.png

背景

大约一个月前,Oracle自治数据库(Oracle Autonomous Database)开始正式支持ORDS(Oracle REST Data Services),这意味着当我们开发和部署Oracle Autonomous Database的REST Service的时候, 将可以获得ORDS的原生支持.

我们已经清楚Oracle Autonomous Database是相当易用的, 只需要点击几个按钮, 在几分钟之内即可获得一台功能齐全, 健壮而且高性能的数据库. 那Oracle Autonomous Database上的ORDS(Oracle REST Data Service)是否也同样易用呢? 让我们构建一个经典的博客程序(REST API)来试试看吧.

准备开始(环境准备)

创建一个ATP实例

正如我上面提到的,创建ADB实例非常简单,只需几次点击我们即可获得一个ATP实例。 不要忘记,如果您的业务增长非常快,您可以随时扩展计算(CPU)和存储资源,而无需停机! 无需停机!

image.png

现在我们得到一个ATP实例。

image.png

创建应用程序用户并启用REST服务

单击[DB Connection]按钮并下载认证(Wallet)文件。

image.png

下载认证(Wallet)文件后,在SQL Developer中使用默认用户(admin)创建新连接.

image.png

在Worksheet中,创建数据库用户(ORDSBLOG)并授予必要的权限。 此用户将用于我们的博客应用程序。


-- Create DB user
CREATE USER ORDSBLOG IDENTIFIED BY <PASSWORD>;

-- Grant privileges
GRANT CREATE SESSION TO ORDSBLOG;
GRANT DWROLE TO ORDSBLOG;
GRANT UNLIMITED TABLESPACE TO ORDSBLOG;

创建用户后,在SQL Developer中为该用户创建新连接。

image.png

右键单击新连接名称,然后单击“Enable REST Services...”。

image.png

选中“Enable schema”复选框。

image.png

单击“Next”和“Finish”以完成操作。

在刚刚创建的ORDSBLOG用户的连接中, 执行以下SQL命令来创建blog程序中的表(users, blogs)

-- Create tables 
CREATE TABLE ORDSBLOG.USERS (
    ID      NUMBER GENERATED ALWAYS AS IDENTITY,
    NAME    VARCHAR2(200)  NOT NULL,
    CONSTRAINT USER_ID_PK PRIMARY KEY (ID)
);

CREATE TABLE ORDSBLOG.BLOGS (
    ID          NUMBER GENERATED ALWAYS AS IDENTITY,
    AUTHOR_ID   NUMBER  NOT NULL CONSTRAINT USER_ID_FK
                REFERENCES USERS(ID),
    TITLE       VARCHAR2(200),
    CONTENT     VARCHAR2(32767),
    CONSTRAINT BLOG_ID_PK PRIMARY KEY (ID)
);

至此, 我们结束了所有的准备工作, 下一步将开始ORDS之旅.

在ADB中开始使用ORDS的最简单方法(不推荐)

在Oracle Autonomous Database上使用ORDS的最建档方式就是直接在需要的表上启用REST Service. 然后即可直接使用REST API来访问表中的数据.

但我强烈建议您使用“REST Data Services”来创建Module/template/handler,以便更好地对REST Service进行精细控制。 我们稍后将详细讨论如何使用“REST Data Services”。 现在让我们通过REST API快速查看表内容。

image.png

简单起见,在当前的例子中我们不需要授权验证。取消选中“Authorization required”复选框。

image.png

查看我们要创建的内容,然后单击“完成”。

image.png

现在,表Users的REST API已准备好了。 但我们应该使用什么URI Endpoint来访问该API呢? 要获取REST API的Endpoint我们可以从刚刚创建的ATP实例的Service Console中获取此信息。

访问OCI Web Console并进入ATP实例页面,单击Service Console.

image.png

然后单击Development并右键单击SQL Developer Web并复制它的链接。

image.png
image.png

我们应该得到如下链接。 将admin / _sdw /?nav = worksheet部分替换为您创建的Schema名称以及刚刚启用REST服务的表名称。

旧: https://<DB_NAME>.adb.<REGION>.oraclecloudapps.com/ords/admin/_sdw/?nav=worksheet
新: https://<DB_NAME>.adb.<REGION>.oraclecloudapps.com/ords/ordsblog/users/

由于我们在启用REST服务时未启用授权验证,因此我们应该能够访问新链接(REST API Endpoint)并直接获取JSON格式的响应返回,如下面的截图所示。

我们使REST API测试工具postman测试我们的REST API。 您也可以使用CURL或任何其他工具来执行此操作。

表users中还没有任何记录,因此items为[]

image.png

我们甚至可以单击“describeby”链接来检查表users的元数据。

image.png
image.png

如您所见,只要我们有一个ADB实例,我们只需要启用REST服务,然后我们就可以对表进行REST API的访问。
非常容易,不是吗?

在ADB中使用ORDS的更好方法(精细分级控制)

上面介绍的方法简单易行,但我们无法精细控制对各个资源的访问。 为了对资源(表)进行精细控制,我建议使用Connection Navigator中列出的REST Data Services下的“Modules”和“Templates”。

image.png

在我们继续前进之前,让我们先关闭我们刚刚在表users上启用的REST服务。 没有人希望自己的数据在没有控制的情况下暴露出去。

取消选中“启用对象”复选框就可以了。

image.png

一旦表users的REST服务被关闭,当我们访问之前的REST API Endpoint时,我们将得到“404 Not Found”错误。 这正是我们所期待的结果.

image.png

用于检索用户的module/template/handler

右键单击REST Data Services下的Modules,然后单击New Module以创建新模块。

image.png

输入模块名称和URI前缀,选中“Publish – Make this RESTful Service available for use”复选框。 这正是我们想要的。

image.png

单击“Next”并指定Template。 我们将使用此URI来提供新用户的注册功能。

image.png

查看摘要,然后单击“Finish”。

image.png

现在,我们应该看到一个名为users的模块,同时还有一个名为new的模板。

image.png

这意味着我们刚刚创建了一个如下的REST API Endpoint。

https://<DB_NAME>.adb.<REGION>.oraclecloudapps.com/ords/ordsblog/users/new

如果您尝试访问此链接,您仍会收到“404 Not Found”错误,因为我们尚未为此端点添加任何处理程序(handler)。

虽然我们计划使用此端点来提供注册功能,但出于测试目的,为简单起见, 我们现在为此Endpoint添加GET处理程序。
image.png

在处理程序Worksheet中我们使用一个简单的查询“select * from users”并保存,来验证Endpoint是否可以正常工作.
image.png
然后尝试再次访问REST API Endpoint。

https://<DB_NAME>.adb.<REGION>.oraclecloudapps.com/ords/ordsblog/users/new

很棒! 一切正常!
image.png

注册新用户(POST)

我们的目标是使用此端点来注册新用户,所以让我们添加一个POST处理程序。

右键单击模板new并添加新的POST处理程序。

image.png

单击“Apply”

image.png

要处理POST请求略微有点复杂,我们需要处理从客户端传来的参数并处理输出响应内容。 我们使用一个存储过程(procedure)来处理新用户的创建,如下所示。

image.png

create or replace PROCEDURE ADD_USER (
    P_USER_NAME    IN  USERS.name%TYPE,
    P_OUT_ID      OUT USERS.id%TYPE,
    P_OUT_TOTAL   OUT INTEGER
)
AS
BEGIN
    INSERT INTO USERS (name)
    VALUES (P_USER_NAME)
    RETURN id INTO P_OUT_ID;

    SELECT COUNT(id) INTO P_OUT_TOTAL FROM USERS;

EXCEPTION
    WHEN OTHERS
    THEN HTP.print(SQLERRM);
END;

在POST处理程序中,我们调用刚刚创建的存储过程并传入我们从客户端请求中获取的参数。

image.png

BEGIN
    ADD_USER(P_USER_NAME   => :USER_NAME,
            P_OUT_ID       => :NEW_USER_ID,
            P_OUT_TOTAL    => :TOTAL);
commit;
END;

对于要返回的响应,我们希望返回新创建的用户ID,以便客户端可以决定下一步做什么,同时我们还返回所有用户的总数。参数设置如下所示。
image.png

现在,我们的POST处理程序已准备就绪。 我们将接收JSON格式的用户信息以创建新用户。 请注意,JSON文件中的键必须与处理程序中的定义相同。

在postman客户端中,选择请求方法为POST,输入REST API Endpoint URI,并在Body / Raw部分中以JSON格式输入用户信息。(您也可以使用json文件并选择binary而不是raw)

image.png

{
    "USER_NAME":"user01"
}

由于我们传输的是JSON格式文件, 我们还需要在Headers中将“Content-Type”设置为“application / json”。
image.png

单击“Send”按钮后,我们将看到响应状态为200 OK, 并在响应内容中看到JSON格式的新用户ID和用户总数。

image.png

在SQL Developer中,我们也可以验证新创建的用户记录。

image.png

还记得我们有一个GET处理程序来检索所有用户吗? 为何不试一试呢。

image.png

很酷不是吗? 虽然只有一个用户, 但这无疑是一个很好的开始.

查看用户信息(GET)

用户注册之后,显然我们应该提供显示用户的个人资料的功能。
让我们创建一个show endpoint来做到这一点。

image.png

添加GET处理程序以提供用户信息。

image.png
image.png

处理程序中的查询非常简单,我们只需要提供用户id作为查询参数即可完成查询。如下图所示.

image.png

启动如下REST API查询,我们将得到所期待的用户信息。

https://<DB_NAME>.adb.<REGION>.oraclecloudapps.com/ords/ordsblog/users/show?id=6

image.png

处理博客

您已经看到了, 为表users启用REST数据服务是多么容易。 让我们继续前进,通过REST API将所有CRUD行为添加到表blogs。

发布第一篇博客(POST)

我相信你已经熟悉了这部分,和新用户处理程序类似。 创建一个存储过程来处理数据插入并在POST处理程序中调用该存储过程。

image.png

相信你不会遇到任何问题, 一定可以看到预期的响应。;)

image.png

列出我的博客(GET)

这仍然是一个GET请求,唯一的区别是传入用户id,以便SQL查询可以检索属于该用户的博客。

image.png
image.png

更新博客(PUT)

如果我们想更新之前发布的博客怎么办? 使用PUT方法。

创建update模板

image.png

添加PUT处理程序来执行更新任务,虽然POST也可以,但是根据REST API最佳实践,我们应该使用PUT来明确表示我们的意图.

image.png

处理博客更新的存储过程与创建博客的类似。

image.png

在PUT处理程序中调用更新博客的存储过程。

image.png

在postman客户端中,将请求方法设置为PUT,在Body部分中输入新的博客信息。

image.png

验证更新后的博客内容。

image.png

什么? 你没有show blog endpoint? 走到这里, 实现这样的GET处理程序还是问题吗?

删除博客 (DELETE)

如果您博客中的某些内容已过期且您不想再保留它,则可以通过DELETE处理程序以随时删除该博客。

添加delete 模板

image.png

创建DELETE处理程序

image.png

不要忘记传入要删除的博客ID。

image.png

在postman客户端中,选择请求方法作为DELETE并发送请求到刚刚实现的API Endpoint。

image.png

现在应该只能看到id为2的博客了。

image.png

保护我们的资源

Basic Auth

到目前为止,任何人都可以对我们的资源(用户,博客)做任何事情。 显然,我们必须保护数据库中的资源,通过利用ORDS中的权限(privileges)我们可以轻松实现这一目标。

image.png

右键单击REST Data Services下的Peivileges并创建新权限。 输入名称,标题和说明。
为简单起见,我们仅使用一个权限保护所有资源。将所有模块(users, blogs)添加到“Protected Modules”部分。

image.png

我们可以看到新创建的Privilege(Demo)。

image.png

如果我们再次尝试请求某个用户的信息,我们将收到401 Unauthorized错误,如下所示。

image.png

如果您使用Web浏览器测试REST API,则可以通过输入数据库用户认证信息来通过验证。

在postman客户端的“Authorization”选项卡下,选择“TYPE”为“Basic Auth”,然后输入数据库用户认证信息。发送请求您将获得用户信息。

image.png

注册OAuth客户端应用程序

我们构建此REST API的目标是为前端或任何其他获得授权的第三方应用程序提供数据访问功能,Basic Auth显然不是正确的方法。

OAuth 2.0是一种标准的互联网协议,它为HTTP服务器提供了一种方法,可以提供REST API,以代表最终用户对第三方应用程序进行有限的访问。

  • 第三方应用程序的作者必须注册该应用程序以获取客户端凭据。
  • 使用客户端凭据,第三方应用程序启动Web认证流程,提示最终用户批准访问。

如上所述,通过使用OAuth,客户端应用程序可以通过注册和获得批准来访问REST API。 幸运的是,此流程默认内置于ORDS中。

要注册客户端应用程序,我们需要访问以下URL:

https://<DB_NAME>.adb.<REGION>.oraclecloudapps.com/ords/ordsblog/oauth/clients/

image.png

使用数据库用户认证登录后,我们可以看到尚未有任何客户端注册。

image.png

单击“New Client”,输入必要信息,然后单击“Create New Client”。

image.png

客户已注册但尚未批准。 单击“Edit”图标以显示此注册客户端的详细信息。

image.png

我们可以看到生成的Client identifier,Unique Value和Authorization URI。

image.png

单击Authorization URI并使用数据库用户凭据登录。 您将看到客户端批准页面。 单击“Approve”按钮以批准此请求。 当然你也可以选择Deny, 如果心情不好的话.

image.png

一旦您批准了该请求,页面将被重定向到您在注册客户端时指定的URL。关键点是重定向后URL中的下面这些信息。

http://example.org/redirect#token_type=bearer&access_token=XErqh-jlHNSoXGe9JX5m7Q&expires_in=3600&state=f084f3c8-d567-e1c8-fb83-81aabacc9b54

  • Token_type: bearer
  • Access_token: XErqh-jlHNSoXGe9JX5m7Q
  • Expires_in: 3600
  • State:f084f3c8-d567-e1c8-fb83-81aabacc9b54

Token_type和access_token是客户端应用程序访问REST API时的关键信息。 您需要将它们包含在每一个REST API的请求中。

image.png

现在我们拥有了访问受保护REST API所需的一切,让我们尝试使用access token来获取某个用户的信息。

在postman客户端中,选择Authorization Type为Bearer Token并输入access token。 然后发送您的请求,您不应再看到401 Unauthorized错误。

image.png

不仅是GET处理程序,只要您提供正确的访问令牌,您就可以访问所有处理程序(handlers),比如说更新博客(PUT)。

image.png
image.png

相反,如果客户端应用程序无法提供正确的访问令牌,则它将被阻止在我们的资源之外。

image.png

现在我们为博客应用程序提供了一个安全且功能齐全的(示例)REST API。 我相信你已经熟悉了自治数据库中ORDS的基本用法。 如果您想了解有关ORDS和Oracle自治数据库的更多信息,请参阅下面的参考资料。

参考

其他语言版本

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?