openwhisk_在OpenWhisk应用程序中管理帐户批准

openwhisk

在许多情况下,例如企业对消费者的应用程序,最好让用户自己注册,然后让管理员批准或拒绝该帐户或特定帐户的权限。 在本教程中,我教您如何实现这样的系统。 这主要是防止黑客通过暴力手段进入系统的一种手段。

本教程中的应用程序基于IBM无服务器架构OpenWhisk。 与需要持续运行的进程的普通Node.js应用程序相比,无服务器架构仅在需要时才运行该进程,从而降低了成本。

构建应用程序所需的条件

运行应用程序 获取代码

本教程显示了一个非常简单的应用程序,该应用程序允许用户自己注册,然后让管理员批准或拒绝他们的请求。

步骤1. Cloudant数据库

OpenWhisk的设计假定应用程序所需的任何信息都存储在其他位置,例如,在Cloudant数据库中。 以下是创建新数据库的步骤:

  1. 登录到Bluemix控制台。
  2. 点击左上方的菜单图标,然后点击数据与分析
  3. 单击创建数据和分析服务
  4. 单击Cloudant NoSQL DB
  5. 将服务命名为“ Acct-approval-db ”,然后单击“ 创建”
  6. 转到服务。
  7. 单击服务凭据 ,然后单击新建凭据
  8. 点击添加
  9. 单击查看凭据,然后将URL值复制到文本文件中。 URL编码主机名,端口,用户ID和密码。
  10. 单击管理 ,然后单击启动
  11. 单击左侧的数据库 (如有必要,使用<->图标查看各个图标的含义)。
  12. 单击创建数据库并命名您的数据库帐户。

步骤2.自注册操作

大多数功能需要两个OpenWhisk操作。 第一个向用户提供要填写的表单,第二个向用户填写表单后做出响应。这是您的操作方式:

  1. 单击左上方的菜单图标,然后单击“ 功能”
  2. 单击开始创建
  3. 单击创建动作
  4. 单击创建新程序包
  5. 将软件包命名为“ Acct-approval ”,然后单击“ 创建”
  6. 将动作命名为“ self-reg-form ”,然后点击创建 。 不必担心将其作为网络操作启用; API定义将在以后执行。
  7. 将源代码替换为我的自我注册表单脚本中的代码。
  8. 单击左上方的管理以返回到操作管理页面。
  9. 单击创建动作
  10. 将新操作命名为“ self-reg-handler ”,选择包Acct-approval ,然后单击Create
  11. 将源代码替换为我的请求表单处理程序脚本中的代码。
  12. 单击左上方的管理以返回到操作管理页面。
  13. 点击左侧栏中的API ,然后点击创建托管API
  14. 将API命名为“ acct-approval ”。 您无需担心指定基本路径。
  15. 单击创建操作
  16. 创建以下两个操作:
    参数 第一次操作 第二次手术
    路径 / self_reg_form / self_reg_handler
    动词 得到 开机自检
    包含动作的包裹 认可 认可
    行动 自我调节形式 自我调节者
    响应内容类型 文字/ HTML 文字/ HTML
  17. 向下滚动并单击保存并公开
  18. 复制API的路由。
  19. 浏览到<您的URL> / self_reg_form。 (查看我的表格 。)

自我注册表格

自我注册表单JavaScript代码非常不言自明,尽管其中有两部分可能需要进行一些讨论:

  • 该操作将HTML参数发送给OpenWhisk一个参数(名为“ html ”)。 在这里,此参数是模板文字 (请参见下面的“相关主题”),它是一个以反引号(`)开头和结尾的字符串。 这种字符串可以包含多行,这使HTML更具可读性。
    return { html: `
    	    <html>
    		.
    		.
    		.
    	    </html>
    	` };
  • 该操作使用具有默认主题的Bootstrap 3.3外观。 本教程中的所有其他操作也都使用它。
    <link rel="stylesheet" 
    href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>

自我注册处理程序

表单处理程序更加复杂。 首先,它需要建立数据库连接。 您需要将cloudantUrl值替换为数据库的那个。

// Replace with your value
var cloudantUrl = "https://<<redacted>>-b18c-93f1b9986506-bluemix.cloudant.com";

最好将连接数据库的命令放在main功能之外。 执行动作后,OpenWhisk系统会将进程保持运行几分钟,直到需要资源为止。 如果在此期间有另一个调用来,OpenWhisk只会使用新参数重新运行main 。 您可以将连接作为全局变量并仅创建一次,而不必每次都创建与数据库的新连接。

var cloudant = require("cloudant")(cloudantUrl);
var mydb = cloudant.db.use("accounts");

main函数从参数params的表单接收值。 但是它不能立即响应,因为它需要与数据库通信,这是一个异步过程。 当OpenWhisk操作需要执行这样的异步过程时,它们将返回Promise对象 (请参见下面的“相关主题”)。

Promise对象的构造函数接收一个参数,一个函数。 该函数接收两个回调函数,一个回调函数成功调用,另一个调用失败。 该功能在某些时候由OpenWhisk系统异步执行。 在某些回调的结尾,它将调用success函数或failure函数,并且该操作将终止。

return new Promise(function(success, failure) {
.
.
.

    // Return the response             
    success({html: reqStatus(body.status, params.uid)});
  });   // mydb.get
});   // Promise object

Promise功能要做的第一件事是检查是否已经有该名称的帐户。 如果是这样,则回调返回适当的响应。

mydb.get(params.uid, function(err, body) {
.
.
.
            
// Return the response 
      success({html: reqStatus(body.status, params.uid)});
});    // mydb.get

适当的响应由reqStatus函数确定。 这是一个非常简单的函数,它使用statusResponse表确定要提供的响应。 此函数使用模板文字的另一个功能。 您可以在模板文字中使用语法${< expression >} ,并将其替换为表达式结果。

// Table of statuses and their messages
statusResponse = {
  "unapproved": "Your request is waiting, please have some patience",
  "approved": "Good news, we approved your request",
  "rejected": '<b style="color:red">Rejected </b>. ' + 
'We don\'t want your business',
  "submitted": "Your request has just been submitted," + 
" it is awaiting approval"
};

reqStatus = function(status, user) {
    return `
        <html>
.
.
.           <body>
                <p>Hello, ${user}. ${statusResponse[status]}</p>
            </body>
        </html>
    `;
}

mydb.get有两种可能的方式返回错误。 首先是如果没有这样的帐户,这就是您所期望的。 另一个是如果确实存在错误情况。 如果错误代码为404,则表明未找到用户。 在这种情况下,您将为新用户创建一个条目。 新条目的标识符是用户ID。 if语句以返回退出函数而结束(这是必需的,因为success调用在回调中)。

// No user yet, register the entry
if (err != null && err.statusCode == 404)  {
mydb.insert( {
     		_id: params.uid,
pwd: saltHashPassword(params.pwd),
           status: "unapproved"
},   // Data to insert
function() {
     		success({html: reqStatus("submitted", params.uid)})    
      });   // mydb.insert                
                return ;
}   // No user yet

存储未加密的密码是一种不好的做法。 此操作使用带有盐的哈希,这是行业标准。 您可以在“ 使用NodeJS crypto的Salt Hash密码 ”中阅读有关内容。

步骤3.批准动作

下一步是创建批准用户的操作。 使用Create 03_approval.js创建一个名为admin-approval-form的新操作。 创建一个名为“ /admin_approval_form ”的新API操作,该操作通过运行操作来响应GET请求。

您可以转到URL进行查看(请参阅我的版本 )。 您将看到一个UID列表,每个都有两个按钮:一个要批准,一个要拒绝。

它是如何工作的?

此功能只有一个操作和一个网页。 如果使用适当的参数调用,它将修改数据库条目以批准或拒绝请求。 无论哪种方式,它都会用新的请求表进行响应。

重要的是只有授权的管理员才能批准或拒绝请求。 为了简化软件,我在编写该应用程序时假设一次只有一个管理员处于活动状态,而他只需几分钟即可做出决定。 这样可以确保该表与接收决策的表来自同一应用程序运行。

有了这些假设,跟踪两个关键就足够了。 旧密钥是上次调用main密钥,它出现在任何授权请求中。 新密钥是您要返回给用户的网页上的密钥,因此它出现在对下一个呼叫的授权请求中。

var oldKey, newKey = genRandomString(15);


function main(params) {
    oldKey = newKey;
    newKey = genRandomString(15);
.
.
.
}

可以在Promise对象中使用此功能。 它返回带有新用户列表的网页。

var responseFunc = function(success, failure) {

.find方法使您可以对Cloudant数据库进行查询。 在这种情况下,请选择状态字段等于unapproved文档。 请参阅Bluemix Docs网站上的Cloudant Query部分,以获取有关构建更复杂查询的帮助。

mydb.find({
     		"selector": {
                "status": "unapproved"
           }
     },

回调函数接收两个参数,错误条件(如果有的话)和与选择器匹配的条目列表。 用户标识符是列表中的结构_id(这是Cloudant中文档标识符的保留名称)中的参数之一。 map方法(请参见下面的“相关主题”)在每个条目上运行一个函数。 第一次调用从mydb.find提供的数据中创建用户标识符列表。 第二个将用户标识符列表转换为HTML表格行列表,并带有必要的按钮来批准和拒绝请求。

function(err, data) {
           var userList = data.docs.map(function(item) {
return item["_id"]
});
           var rowsList = userList.map(function(user) {
               return `
                    <tr>
                        <td>${user}</td>

这些按钮实际上是指向同一页面的链接,但带有用于批准或拒绝请求的参数。 有三个参数:

  1. key :现在是新密钥(当收到请求时将是旧密钥)。
  2. action :操作( approvereject )。
  3. uid :用户标识符。 该值来自用户,因此可能包括代码注入。 为确保您没有任何此类恶意用户,请使用querystring模块的querystring.escape(str))函数。 (请参阅下面的“相关主题”。)
<td>
<a href="admin_approval_form?key=${newKey}&action=approve&uid=${qs.escape(user)}">
<button class="btn btn-success">Approve</button>
</a>
</td>
<td>
<a href="admin_approval_form?key=${newKey}&action=reject&uid=${qs.escape(user)}">
<button class="btn btn-danger">Deny</button>
</a>
</td>
</tr> `
});

最后,检查是否有任何行。 如果不是,则返回一条消息。 如果存在,则使用reduce方法将它们串联。 (请参阅下面的“相关主题”。)

var rows;
            
// No data is a special case
if (rowsList.length > 0) 
rows = rowsList.reduce(function(a, b) {return a+b;});
else
rows = '<tr><th colspan="3">No users to approve</th></tr>';

现在,所有行都作为一个字符串,您可以将该字符串嵌入到HTML文档中,并在调用success函数时将其作为html参数发送。 所有这些都发生在responseFunc定义内的mydb.find函数的回调中。

var html = `<html>
.
.
.
    <table class="table">
        <tr>
            <th>User Name</th>
            <td colspan="2"></td>
        </tr>
	    ${rows}
    </table>
.
.
.
   </html> `;            
            
    success({html: html});
	});   // mydb.find

};   // responseFunc

如果没有密钥,或者该密钥不是正确的旧密钥,则没有请求进行处理。 在这种情况下,您刚定义的请求函数是Promise对象的正确函数。

// If we are not authenticated, then there is no action to take
if (params.key != oldKey)
return new Promise(responseFunc);

如果您超过了这一点,则说明密钥是正确的。 在这种情况下,有必要满足该请求。 为此,返回一个Promise对象,该对象的函数首先修改状态,然后运行响应函数,该函数返回带有未决请求和用于处理请求的按钮的表。

if (params.action == "approve")
return new Promise(function(success, failure) {
     		modifyStatus(params.uid, "approved", function() {
           	responseFunc(success, failure);
});   // modify status
      });   // return new Promise

modifyStatus函数检索uid的完整条目,修改状态,写入新条目,并在写入新状态后的callback中调用调用responseFunccallback函数。

var modifyStatus = function(uid, newStatus, callback) {
    mydb.get(uid, function(err, body) {
        body.status = newStatus;

        mydb.insert(body, function(err, data) {
            callback();
        });   // mydb.insert
    });   // mydb.get
};

步骤4.登录操作

使用类似于请求的两个动作(表单和处理程序)来实现登录。 创建这两个:

动作名称 动作码 API路径 API动词
登录表单 这里 /登录 得到
登录表单处理程序 这里 / login_handler 开机自检

登录表单仅返回固定HTML,因此不言自明。 登录表单处理程序更为复杂,但是大多数使用与其他操作相同的构造。 唯一的新内容是检查密码,这在“ 使用NodeJS crypto的Salt Hash密码”中进行了说明。

结论

本教程显示了一个非常简单的应用程序,该应用程序允许用户自己注册,然后让管理员批准或拒绝他们的请求。 在现实生活中的应用程序中,将要求用户在注册之前要求其提供其他信息,并且其中的某些信息可能会先经过验证,然后再由管理员查看。 获得允许重设密码的其他信息尤其重要。


翻译自: https://www.ibm.com/developerworks/security/library/se-manage-account-approval-openwhisk-application/index.html

openwhisk

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值