资讯专栏INFORMATION COLUMN

翻译 Meteor React 制作 Todos - 11 - 发布订阅

用户83 / 2966人阅读

摘要:通过发布订阅模式过滤数据现在我们已经把应用中比较敏感的代码放到了一些方法里面,我们还需要学习安全故事的另一半内容了。当在客户端被调用时传入发布器名称,客户端将会从发布器订阅所有的数据。这个按钮应该只是给任务的所有者来显示。

通过发布订阅模式过滤数据

现在我们已经把应用中比较敏感的代码放到了一些方法里面,我们还需要学习Meteor安全故事的另一半内容了。
到现在为止,我们一直是假设整个整个数据库到客户端上,这意味着我们调用Tasks.find()方法我们将会得到集合中所有的数据。如果我们应用程序的用户想要保存私密敏感信息的话,这样做并不好。我们需要一种可以控制数据的方法,使Meteor发送所需数据到客户端数据库

就想上一步骤的insecure一样,所有新的Meteor应用都在开始时带着autopublish包的。这个包可以自动的同步所有数据库的数据到客户端上,先来移除这个包,然后看看会发生什么

meteor remove autopublish

当应用程序刷新,任务列表将会变成空的。没有autopublish包,我们就必须明确的指定服务端发送什么到客户端。这个在Meteor的函数是通过Meteor.publishMeteor.subscribe来做这些的。

现在来添加他们把

    passwordSignupFields: "USERNAME_ONLY"
  });
    
    // 添加这一行
  Meteor.subscribe("tasks");
 
  Meteor.startup(function () {
    // 在页面准备好之后使用Meteor.startup来渲染组件
    React.render(, document.getElementById("render-target"));
  });
}

// 添加开始
if (Meteor.isServer) {
  Meteor.publish("tasks", function () {
    return Tasks.find();
  });
}
// 添加结束
 
Meteor.methods({
  addTask(text) {

一旦你添加了这些代码,所有的任务将会再次出现

在服务端调用Meteor.publish注册一个名为tasks的发布器。当Meteor.subscribe在客户端被调用时(传入发布器名称),客户端将会从发布器订阅所有的数据。这些数据是在数据库中所有在这方面的任务。为了真实的感受发布订阅模式的力量,让我们来实现这样的特性吧,他允许用户将任务定义为私有状态,这样其他的用户就不能再看到这些东西了

添加一个按钮使任务私有化

来给任务添加一个“私有”属性和一个给用户将任务私有化的按钮。
这个按钮应该只是给任务的所有者来显示。我们想要一个标签来表示当前的状态:公有或私有

首先,我们要添加一个新的方法,这个方法可以被我们调用并将任务设置为私有状态

    // simple-todos-react.jsx文件

  setChecked(taskId, setChecked) {
    Tasks.update(taskId, { $set: { checked: setChecked} });
  },

    // 添加开始
  setPrivate(taskId, setToPrivate) {
    const task = Tasks.findOne(taskId);
 
    // 确保只有任务所有者可以将任务设置为私有状态
    if (task.owner !== Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }
 
    Tasks.update(taskId, { $set: { private: setToPrivate } });
    // 添加结束

  }
});

现在我们需要传一个新的属性给Task,使其决定我们是否想要展示这个私有按钮。
这个按钮应该只有在当前登录的用户是任务的所有者时才会被展示

// App.jsx文件

renderTasks() {
  // 从this.data.tasks中获取任务列表
  return this.data.tasks.map((task) => {
  
      // 添加开始
    const currentUserId = this.data.currentUser && this.data.currentUser._id;
    const showPrivateButton = task.owner === currentUserId;

    return ;
      // 添加结束

  });
},
// Task.jsx文件
// Task组件,表示单个的任务
Task = React.createClass({
  propTypes: {

      // 添加开始
    task: React.PropTypes.object.isRequired,
    showPrivateButton: React.PropTypes.bool.isRequired
    // 添加结束

  },
 
  toggleChecked() {

添加一个按钮,使其新的属性去决定它是否应该被显示

// Task.jsx文件

  checked={this.props.task.checked}
  onClick={this.toggleChecked} />

// 添加开始
{ this.props.showPrivateButton ? (
  
) : ""}
// 添加结束


  {this.props.task.username}: {this.props.task.text}

我们要为这个按钮定义事件监听

// Task.jsx 文件

  Meteor.call("removeTask", this.props.task._id);
},

// 添加开始
togglePrivate() {
  Meteor.call("setPrivate", this.props.task._id, ! this.props.task.private);
},
// 添加结束

render() {

最后一件事,来给Task组件的li元素更新class, 来反映私有状态

render() {
  // 当它们被关闭时给一个不同的className,
  // 这样我们就可以通过CSS来设置好看的样式了

  // 添加开始
  // 当我们需要的时候可以给“确认框”添加”私有“样式
  const taskClassName = (this.props.task.checked ? "checked" : "") + " " +
    (this.props.task.private ? "private" : "");
    // 添加结束

  return (
    
  • 基于私有状态有选择地推送数据

    现在我们有了设置任务私有的方式,那么我们就要修改我们的发布函数使其只发送已登陆用户的任务

    // simple-todos-react.jsx 文件
    
    }
     
    if (Meteor.isServer) {
      // 只发布公有的或者是属于当前用户的任务
      Meteor.publish("tasks", function () {
    
          // 添加开始
        return Tasks.find({
          $or: [
            { private: {$ne: true} },
            { owner: this.userId }
          ]
        });
        // 添加结束
        
      });
    }

    要测试这个功能是否能用,我们可以使用浏览器的“隐私浏览”模式作为一个不同的用户登录。把两个窗口拍两边,然后标记一个私有任务,看看另一个用户是否能够看到。现在把它再设置成公有状态,它就又会出现了!

    额外的方法安全

    为了完成我们私有任务的特性,我们需要给deleteTasksetChecked方法一些核实的特性,用来确保只有任务的拥有者可以删除和完成一个私有任务

    // simple-todos-react.jsx
    removeTask(taskId) {
    
        // 添加开始
      const task = Tasks.findOne(taskId);
      if (task.private && task.owner !== Meteor.userId()) {
        // 如果任务是私有状态,确保只有拥有者可以删除
        throw new Meteor.Error("not-authorized");
      }
        // 添加结束
    
      Tasks.remove(taskId);
    
    },
    
    setChecked(taskId, setChecked) {
    
        // 添加开始
      const task = Tasks.findOne(taskId);
      if (task.private && task.owner !== Meteor.userId()) {
        // 如果任务是私有的,确保只有任务拥有者可以完成此项任务
        throw new Meteor.Error("not-authorized");
      }
      // 添加结束
    
      Tasks.update(taskId, { $set: { checked: setChecked} });
    },

    注意:这个代码允许任何人删除任意公有任务。你应该当尽力做一些小的改变:只有任务拥有者可以删除他们的任务

    我们已经完成了私有任务的特性了!当攻击者试着去看或者修改某个私有任务时,我们的应用也是安全的了!

    文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/91554.html

    相关文章

    • 翻译 Meteor React 制作 Todos - 12 - 下一步

      摘要:下一步干什么恭喜你刚刚成功编写了你的应用,别忘了再部署一遍,这样你的朋友们就可以使用这些新特性了你的应用在一个单个的任务清单中是支持合作的。检查一下例子待办事项。更多的可以控制分享多个列表的已完成应用。 下一步干什么? 恭喜你刚刚成功编写了你的Meteor应用,别忘了再部署一遍,这样你的朋友们就可以使用这些新特性了! 你的应用在一个单个的任务清单中是支持合作的。试试怎么样添加更多的功能...

      anRui 评论0 收藏0
    • 翻译 Meteor React 制作 Todos - 06 - 部署应用

      摘要:添加,删除,确认完成这些操作,你将会看到你的应用的界面响应非常的快。。这是因为并不会在更新用户界面之前等着服务端的响应数据。 部署你的应用 现在你有了一个可以运行的待办事宜的应用,你可以分享给你的朋友们!Meteor使得发布你的应用到其他人可以使用的互联网变得非常的简单。 同样是在你的应用文件夹的命令行中输入: meteor deploy my_app_name.meteor.com ...

      xiaochao 评论0 收藏0
    • 翻译 Meteor React 制作 Todos - 01 - 创建应用

      摘要:闲扯在翻译之前我还是要简要介绍一下,这是一款跨时代的框架。后来开始使用动态的脚本语言,比如后来以此构成了框架。最为出名的自然是。通过来传递数据,在本地起这种事情使得开发进入了新的阶段。如果你觉得我翻译的很烂,来给我说吧邮件地址 闲扯 在翻译之前我还是要简要介绍一下Meteor,这是一款跨时代的框架。真的,完全没有骗你。 一开始的网站是纯静态页面搭建的。 后来开始使用动态的脚本语言,比如...

      VishKozus 评论0 收藏0
    • 翻译 Meteor React 制作 Todos - 09 - 添加用户账户

      摘要:为了开启这套账户系统和界面,我们需要去添加相关的包。使用,而不是在文件加入开始这段代码只会在客户端执行加入结束添加用户关联功能现在你已经可以创建账户并登录你的应用程序了。例如包含了已登陆用户的用户名。 添加多用户账户 Meteor带来了一套账户系统然后顺便还带了用户界面来让你可以在几分钟之内在你的应用中添加多用户功能 目前,这套UI组件使用Blaze作为默认的UI引擎,在未来,可能会以...

      levius 评论0 收藏0
    • 翻译 Meteor React 制作 Todos - 03 - 集合

      摘要:数据存储集合是存储持久化数据的方式。中的集合比较特殊的是,它可以从服务端,包括客户端接收数据。它也可以自动的自我更新,因此一个视图组件受到一个集合的支持,他可以自动的展示最新的数据。 数据存储 集合(Collection)是Meteor存储持久化数据的方式。Meteor 中的集合比较特殊的是,它可以从服务端,包括客户端接收数据。这使得编写视图逻辑变得更加简单 -- 不用去写太多的服务端...

      Scott 评论0 收藏0

    发表评论

    0条评论

    用户83

    |高级讲师

    TA的文章

    阅读更多
    最新活动
    阅读需要支付1元查看
    <