How to make data unreadable once the time indicated on its time stamp has passed?

人走茶凉 提交于 2020-01-29 20:35:33

问题


Let’s say for instance a user writes about an event to the Firebase database, what the user writes has a time stamp attached to it and other users are able to read what was written in a list view using the FirebaseListAdapter. Is there a way to make the data written by the user unreadable once the time on the time stamp has passed?


回答1:


There's a big difference here between whether you have a single item, or a list of items.

Securing access to a single node

If you have a single node like this in your database:

"content": {
  "expiresAt": 1565275079920,
  "content": "This content is only readable until Thu Aug 08 2019 07:37:59 GMT-0700"
}

You can ensure this node is only readable until its expiry timestamp with these rules:

{
  "rules": {
    "content": {
      ".read": "data.child('expiresAt').val() < now"
    }
  }
}

When somebody attaches a listener to /content up until the expiry timestamp it will be allowed, after that any new listeners will be rejected.


Securing access to a list of nodes

But things get more complicated when you have a list of data as:

  1. You can only read/query data if you have read access to all that data.
  2. Once you have read access to a node, you have read access to all data under that node.

Combined these two fact mean that security rules cannot be used to filter data.

So if you have a list of these nodes above:

"content": {
  "-Ldshdh13...": {
    "expiresAt": 1565275079920,
    "content": "This content is only readable until Thu Aug 08 2019 07:37:59 GMT-0700"
  },
  "-Ldshdh13...": {
    "expiresAt": 1565277079920,
    "content": "This content is only readable until Thu Aug 08 2019 08:11:19 GMT-0700"
  },
  ...
}

In order to be able to query this data, the user must have read permission on /content. And as soon as they have full read permission on /content, you can't keep them from reading certain nodes under there.

The only way to make this scenario work is to use a combination of a query and a security rule that validates this query.

Step 1: query for only the data that you're allowed to read

So if you should only be able to read data that expires in the future:

var ref = firebase.database().ref('content');
ref.orderByChild('expiresAt').startAt(Date.now()).once('value',...

Step 2: use security rules to only allow reads with this query

The security rules will now check whether the user is passing the correct orderBy and value in to their query so that they're only accessing non-expired data:

{
  "rules": {
    "content": {
      ".read": "query.orderByChild == 'expiresAt' &&
                query.startAt >= now"
    }
  }
}

A few things still to note:

  • The security are applied when the listener is attached. So the value of now is only checked at that moment, it doesn't get modified in any way after that. This is usually not a security problem, but means you will need to remove outdated data in the application code too after attaching the listener.
  • You may need to tweak the rule a bit, as the Date.now() in the client and the now in the rules may not be exactly the same. Adding a few seconds in the security rule may be a good idea.

For further reading, I highly recommend:

  • documentation on the fact that permissions cascade
  • documentation on rules-are-not-filters
  • previous questions on rules are not filters. Note that many of these probably predate the introduction of query-based security rules.
  • documentation on query based security rules


来源:https://stackoverflow.com/questions/57393551/how-to-make-data-unreadable-once-the-time-indicated-on-its-time-stamp-has-passed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!