本文主要讲解如何在 ORDS 中利用 OAuth2 认证保护 RESTful API,以及如何在 APEX 中使用 OAuth2 认证的 RESTful API。
创建演示用的 RESTful API 首先登录 Oracle APEX 工作台,在顶部菜单中选择 SQL Workshop -> RESTful Services ,如图所示:
创建 Modules 点击 Modules 节点,创建一个新模块,比如:lab.demo
创建 RESTful API 选中这个模块,点击 Create Template 按钮,创建一个新的 RESTful Service,比如:customers,并创建一个最简单的 GET 服务(Resource Handler),如图所示:
在浏览器中测试 RESTful API
将 RESTful API 保护起来 现在我们的 RESTful API 已经创建成功,但是任何人都可以访问,我们需要将这个 RESTful API 保护起来,只允许授权用户访问。
创建 Roles 选择 Roles 节点,新建一个角色(role) ,比如:oracle.dbtools.role.autorest.lab.customer
创建并配置 Privileges
再次在浏览器中打开 RESTful API,会看到如下信息,证明 RESTful API 已经被保护起来了。
创建 OAuth2 Client 为了能够访问受保护的 RESTful API,我们需要创建一个 OAuth2 Client,将这个 Client 与刚才创建的 Role 关联起来。
点击 SQL Workshop -> SQL Commands 菜单,打开 SQL Worksheet,执行如下 SQL 语句:
1 2 3 4 5 6 7 8 9 BEGIN oauth.create_client( p_name = > 'lab_client' , p_grant_type = > 'client_credentials' , p_description = > 'lab client demo' , p_support_email = > 'wfgdlut@gmail.com' , p_privilege_names = > 'oracle.dbtools.autorest.privilege.lab.customer' ); COMMIT ; END ;
Client 创建成功后,在 SQL Worksheet 中执行如下 SQL 语句,并将返回的 client_id 和 client_secret 记录下来,后面需要用来获取 access_token 。1 2 3 4 5 6 7 SELECT id, name, description, client_id, client_secret FROM user_ords_clients WHERE name = 'lab_client' ;
将 OAuth2 Client 与 Role 关联起来 继续在 SQL Worksheet 中执行如下 SQL 语句,将 OAuth2 Client 与 Role 关联起来:1 2 3 4 5 6 BEGIN oauth.grant_client_role( p_client_name = > 'lab_client' , p_role_name = > 'oracle.dbtools.role.autorest.lab.customer' ); COMMIT ; END ;
获取 access_token 打开命令行终端(或者使用 Postman),执行如下命令,获取 access_token :1 2 3 4 curl -X POST 'https://oracleapex.cn/ords/lab/oauth/token' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -u '<Client ID>:<Client Secret>' \ --data 'grant_type=client_credentials&scope=oracle.dbtools.role.autorest.lab.customer'
如果一切正常,就会得到 access_token,如图所示:
这里的 access_token 就是用来访问受保护的 RESTful API 的令牌,将它复制下来。
钢哥提醒:如果获取 access_token 失败,请先参考文末的避坑指南。
通过 curl 命令访问受保护的 RESTful API,如下所示:1 2 3 4 curl -i \ -X GET "https://oracleapex.cn/ords/lab/api/customers" \ -H "Authorization: Bearer <your_access_token>" \ -H "Accept: application/json"
如果一切正常,就会得到如下信息,证明 RESTful API 已经被成功访问了。
你也可以通过 Postman 或者 Hoppscotch 工具访问受保护的 RESTful API,原理是一样的,必须先通过 client_id 和 client_secret 获取 access_token,然后再通过 access_token 访问受保护的 RESTful API,如下图所示:
在 APEX 中使用 OAuth2 认证的 RESTful API 接下来就可以将这个 RESTful API 集成到 APEX 应用中了。进入到 APEX 工作台,点击 Shared Components -> REST Data Sources -> Create -> From scratch 菜单, 将刚刚创建的 RESTful API 注册到 APEX 中,如图所示:
钢哥提醒:这一步如果报错,请参考文末的避坑指南。
填写好 RESTful API 的相关信息,点击 Create 按钮,根据向导创建一个 REST Data Source,以下是基于我自己的 RESTful API 信息填写的,请参考并对应修改成你自己的。
我的 RESTful API 没有使用分页,所以跳过此步设置,下一步:
这一步很关键,需要填写 OAuth2 的相关信息,如下图所示:
上述信息填写完成后,点击 Discover 按钮,APEX 会自动获取 access_token 并试图解析 RESTful API 的返回结果,如果一切正常,会看到如下信息:
点击 Create REST Data Source 按钮进行保存。
在 APEX 中使用 OAuth2 认证的 RESTful 数据源 新建一个 APEX 页面,增加一个 Interactive Report 组件,数据源关联刚刚创建的 REST Data Source,如下图所示:
运行后的效果如下:
避坑指南 在获取 access_token 时可能会踩的坑 ORDS 获取 access_token 的 URL 是:https://oracleapex.cn/ords/lab/oauth/token , 其中 lab 是 ORDS 的 workspace 名称,如果你的 ORDS 的 workspace 名称不是 lab,需要将 lab 替换成你的 workspace 名称。后面的 /oauth/token 是固定写法,不要修改; 如果遇到 Token 获取失败:AUTH TOKEN_REQUEST_INVALID_RESPONSE 的错误,可能是由于 Nginx 或 tomcat 配置的问题。 检查 nginx.conf 文件,确保配置了如下信息: 1 2 3 4 5 proxy_set_header X-Forwarded-Proto $scheme ; proxy_set_header X-Forwarded-Host $host ;proxy_set_header X-Forwarded-Port $server_port ;proxy_set_header Host $host ;proxy_set_header Authorization $http_authorization ;
检查 tomcat 的 $CATALINA_BASE/conf/server.xml 文件,确保配置了如下信息: 1 2 3 4 5 6 <Connector port ="8080" protocol ="org.apache.coyote.http11.Http11NioProtocol" URIEncoding ="UTF-8" proxyPort ="443" proxyName ="oracleapex.cn" scheme ="https" secure ="true" />
重启 Nginx 和 tomcat,再次尝试获取 access_token。 解析 RESTful API 可能会踩的坑
如果在解析 RESTful API 时遇到 ORA-29024: Certificate validation failure 的错误,是由于 SSL 证书导致的。APEX(实质是数据库里的 UTL_HTTP)在发起 HTTPS 调用时无法验证对端证书链,所以抛出 ORA-29024: Certificate validation failure。本机 curl 能通,是因为你的客户端已经信任了 Let’s Encrypt/DigiCert 的根证书;数据库并不会自动信任系统根,必须给 Oracle Wallet 配好受信任根证书,并把 APEX 实例的 Wallet Path 指到它。
所以只需要将对应的证书(我使用的是 Let’s Encrypt/DigiCert 的根证书)放到 Wallet 中即可。不知道如何配置 Wallet 的,可以参考钢哥的这篇文章:《Oracle Wallet 钱包配置》
SSL 证书导入 Wallet 后,再次解析 RESTful API,就可以继续往下执行了。
总结 本文详细介绍了如何通过 ORDS 将 RESTful API 保护起来,以及如何在 APEX 中使用 OAuth2 认证的 REST 数据源。很多第三方的 API 都是遵循 OAuth2 协议的,掌握了如何在 APEX 中使用 OAuth2 认证的 REST 数据源,将让你的 APEX 应用与第三方 API 的集成变得更加简单和安全,欢迎大家留言讨论。