onvno / pokerface

日常技术文章阅读整理
3 stars 0 forks source link

20190508 - Session && JWT &&CSRF #24

Open onvno opened 5 years ago

onvno commented 5 years ago

那么,一个恶意攻击者可以在另一个网站上放置如下代码:

如果有账户名为Alice的用户访问了恶意站点,而她之前刚访问过银行不久,登录信息尚未过期,那么她就会损失1000资金。

这种恶意的网址可以有很多种形式,藏身于网页中的许多地方。此外,攻击者也不需要控制放置恶意网址的网站。例如他可以将这种地址藏在论坛,博客等任何用户生成内容的网站中。这意味着如果服务端没有合适的防御措施的话,用户即使访问熟悉的可信网站也有受攻击的危险。

透过例子能够看出,攻击者并不能通过CSRF攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义运行操作。

JWT特点 (1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。

(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。



* [从koa-session中间件学习cookie与session](https://github.com/zyl1314/blog/issues/3)
基本上是写的最好的介绍`koa-session`的源码分析文章了
![5](https://user-images.githubusercontent.com/11772494/57424077-f7ac8080-7248-11e9-9a7a-f72e839e1155.png)

补充一篇,主要介绍session接入服务的源码分析[koa-session学习笔记](https://segmentfault.com/a/1190000013039187)
onvno commented 5 years ago

Node.js中使用redis数据库的正确姿势

var session = require('koa-generic-session');
var redisStore = require('koa-redis');
var koa = require('koa');
var redis = require('redis');
// 注意: client默认是异步callback方式调用;
// store.client是经过了co-redis包装,返回Promise, 在koa里面用yield异步编程比较方便
var client = redis.createClient(6379, "172.19.65.240");

var app = koa();
app.keys = ['keys', 'keykeys'];
// var option={host: "172.19.65.240", db:1};
var options = {client: client, db: 1};

var store = redisStore(options);
app.use(session({
  store: store
}));

app.use(function *() {
  switch (this.path) {
    case '/get':
      get.call(this);
      break;

    case '/testKV':
      // 保存key value
      if (this.query.adminId) {
        yield store.client.set("test1", this.query.adminId);
      }
      //同步读取key value
      this.body = yield store.client.get("test1");
      break;

    case '/testHM':
      //操作hashmap
      var result = yield store.client.hmset("hosts", "mjr", "123", "another", "23", "home", "1234");
      console.log(result);

      var obj = yield store.client.hgetall("hosts")
      console.dir(obj);
      //获取hashmap key的值
      this.body = yield store.client.hget("hosts", "home");

      //保存hashmap,使用默认的callback方式
      // client.hset("hash key", "hashtest 1", "some value", redis.print);
      // client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
      // client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234");
      // client.hmset(["key", "test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {
      //   console.log(res);
      // });

      break;
    case '/testSet':
      //保存set
      var key = "key1";
      store.client.sadd("key1", "v1");
      store.client.sadd("key1", "v2");
      store.client.sadd("key1", "v3");

      //读取set
      store.client.multi()
        .sismember(key, 'v1')
        .smembers(key)
        .exec(function (err, replies) {
          console.log("MULTI got " + replies.length + " replies");
          replies.forEach(function (reply, index) {
            console.log("Reply " + index + ": " + reply.toString());
          });
        });

      //读取set
      this.body = yield store.client.smembers("key1");
      break;
    case '/testList':
      //保存list
      store.client.rpush("mylist", "bbb")
      store.client.rpush("mylist", "ccc")
      store.client.lpush("mylist", "aaa")

      this.body = yield store.client.rpop("mylist");
      break;
    case '/remove':
      remove.call(this);
      break;
    case '/regenerate':
      yield regenerate.call(this);
      break;
  }
});

function get() {
  var session = this.session;
  session.count = session.count || 0;
  session.count++;
  var test = store.client.get("test");
  console.log(test);
  this.body = session.count;
}

function remove() {
  this.session = null;
  this.body = 0;
}