Firebase:允许根据时差(服务器端时间)进行访问

时间:2018-07-26 19:02:35

标签: android firebase firebase-realtime-database timestamp

所以我有一个看起来像这样的数据库:

Posts
|
|
|----post_id_1
     |
     |---post_title = "...."
     |---post_body = "...."
     |---post_time = "ServerValue.TIME_STAMP"
|
|----post_id_2
     |.......
     |.......

我想做什么:

我要防止用户阅读帖子发布日期后大于等于一个月的帖子吗?

我尝试过的事情:

我试图通过android使用此方法:

//current time of device
long current_time = System.currentTimeMillis();
//month in millisecond
long month = .....;

if(curent_time - post_time >= month){

//this post was there for a month from the time that it was posted.

}

问题:

如果我使用上述方法,那么如果用户足够聪明,他/她将更改设备输入帖子的时间(不应该)。

问题:

有什么稳定的方法吗?

谢谢。

注意:没有从服务器获取时间戳。

2 个答案:

答案 0 :(得分:1)

我将TIME_STAMP存储为UTC并从服务器获取时间,而不是从设备获取时间。

在这种情况下,用户无法更改设备上的时间来修改数据库的输出。

我建议始终将所有日期存储为UTC,并在用户查看日期时将其转换为用户时区。

答案 1 :(得分:1)

我也遇到过同样的问题,我是如何解决这个问题的,现在是对Google进行一次ping操作,然后将该时间存储在Firebase中,这样我就可以比较用户上次执行某项操作的时间,而该时间就是服务器时间并且无法更改。

因此,在我的情况下,每次我的应用程序以onStoponDestroy方法输入时,我都会上载该服务器时间,但是您可以在需要保存到数据库的任何地方使用它。

以下是获取服务器时间的代码段,我使用asyncTask来获取服务器时间,然后将其发布到我的参考中。只需致电asyncTask,即可在其中使用服务器时间更新某些内容。

public class getGoogleTime extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... voids) {
        try {

            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(new HttpGet("https://google.com/"));
            StatusLine statusLine = response.getStatusLine();
            if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
                DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.ENGLISH);
                dateStr = response.getFirstHeader("Date").getValue();
                Date startDate = df.parse(dateStr);
                dateStr = String.valueOf(startDate.getTime() / 1000);
                long actualTime = java.lang.Long.parseLong(dateStr);
                //Here I do something with the Date String

            } else {
                //Closes the connection.
                response.getEntity().getContent().close();
                throw new IOException(statusLine.getReasonPhrase());
            }
        } catch (IOException e) {
            Log.d("SAF_GTG_Response", e.getMessage());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    // can use UI thread here
    protected void onPostExecute(final Void unused) {

        mDatabase.child("Posts").child(post_id_1).child("currentTime").setValue(dateStr, new DatabaseReference.CompletionListener() {
            @Override
            public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {

                Log.d("SAF_GTG_TAG", "Success");

            }
        });


    }
}

要使用Firebase,您可以执行以下操作:

 ref = FirebaseDatabase.getInstance().getReference();    

    ref.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot snapshot) {
            Long timestamp = (Long) snapshot.getValue();
            System.out.println(timestamp);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

    ref.setValue(ServerValue.TIMESTAMP);

注意:此方法仅返回UTC时间,您可以将其转换为想要向每个用户显示的时间。

如果您担心网络使用情况,只需ping Google并查看正在使用多少字节和数据包即可。

Pinging google.com [172.217.162.14] with 32 bytes of data:
Reply from 172.217.162.14: bytes=32 time=17ms TTL=53
Reply from 172.217.162.14: bytes=32 time=17ms TTL=53
Reply from 172.217.162.14: bytes=32 time=17ms TTL=53
Reply from 172.217.162.14: bytes=32 time=16ms TTL=53

Ping statistics for 172.217.162.14:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 16ms, Maximum = 17ms, Average = 16ms

从文档中

  

一个简单的ping命令的带宽消耗,运行一次   每秒,比较小。可能的最小ping数据包   (包括以太网帧标头和IP + ICMP标头,以及   ICMP有效负载的最小32个字节)需要74个字节

约0,074千字节。