Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

@KeitaMoromizato

現場のSails.js #4 セキュリティ関連

概要

弊社では一部の社内プロジェクトでSails.jsを利用しています。その中で得られたベストプラクティスやらバッドプラクティスをまとめていこうと思います。
第4回はセキュリティに関する設定を色々と。

動作環境

node.js v0.12.7
Sails.js v0.11.2
sails-mysql v0.11.0

blueprintの無効化

Sails.jsにはblueprintという便利な機能があり、例えばControllerに何も書かなくてもでGET /hogeというリクエストで自動的にHogeモデルの一覧をGETすることが出来たり、/api/controllers/HogeController.js#findというメソッドに自動的にルーティングしてくれたりします。
blueprintはプロトタイプを作成するときには非常に便利なのですが、実際の運用を考えると意図しないAPIを公開する可能性があり、セキュリティリスクが高まります。そのため、サービスの公開前にはOFFにすることをオススメします。

js/config/blueprint.js
module.exports.blueprints = {
  actions: false,
  rest: false,
};

そして/config/routes.jsに必要なルーティングを全て記述します。

js/config/routes.js
module.exports.routes = {
  /***************************************************************************
   *  Views
   ***************************************************************************/
  'GET /': 'ArticleController.top',

  /***************************************************************************
   *  API
   ***************************************************************************/
  'POST /api/article/:article/favorite': 'api/ArticleController.favorite',
};

policyの設定

Sails.jsはpolicyという機能でControllerのメソッドへのアクセスを制限出来るようになっているため、ログインを伴うアプリの場合は積極的に活用しましょう。

/config/policies.js
module.exports.policies = {
  '*': true,

  /***************************************************************************
   *  Views
   ***************************************************************************/
  'ArticleController': {
    '*': true,
    'favorite': 'sessionAuthView'
  },

  /***************************************************************************
   *  APIs
   ***************************************************************************/
  'api/ArticleController': {
    '*': false,
    'favorite': 'sessionAuthApi',
  }
};

API/ViewControllerで未ログイン時に行いたい処理が違うので、以下のようにsessionAuthView/sessionAuthApiという2つのpolicyファイルを使用します。

api/policies/sessionAuthView.js
module.exports = function(req, res, next) {

  // User is allowed, proceed to the next policy,
  // or if this is the last policy, the controller
  if (req.user) {
    return next();
  }

  // User is not allowed
  // Viewへのアクセスの場合はリダイレクト
  sails.log.warn('Unauthorized user access denied, ' + req.originalUrl);
  return res.redirect('/');
};
api/policies/sessionAuthApi.js
module.exports = function(req, res, next) {

  // User is allowed, proceed to the next policy,
  // or if this is the last policy, the controller
  if (req.user) {
    return next();
  }

  // User is not allowed
  // APIの場合は403を返す
  return res.send(403);
};

Waterline#create, #update

セキュリティとは若干違いますが、システムの品質のためにService層で気をつけている箇所があります。Sails.jsのO/R Mapper、Waterlineはcreateupdateに渡したObjectを、再帰的に作成・更新する機能があります。
例えば、チャットサービスでRoomMessageという2つのモデルが存在する場合に以下のコードを実行できます。

Room.create({
  name: 'hoge',
  messages: [
    { text: 'Hello' }
  ]
}).exec();

// リレーションのあるレコードもまとめて生成される
// => Room: {id: 1, name: 'hoge'}、Message: {id: 1, room: 1, text: 'Hello'}

実際のシステムでも活用している機能ですが、コードのバグにより意図しないレコードを生成してしまう可能性があります。そのため、O/R MapperへのアクセスはService層で隠蔽し、Serviceに渡されたパラメータをフィルタしてWaterlineに渡すようにしています。

ArticleService.ts
class ArticleService {
  create(params: Object): Promise<any> {
    return new Promise((resolve, reject) => {
      Article.create(_.pick(params, ['title', 'body]).then(resolve, reject);
    });
  }
}

export = new SELECK.Services.ArticleService();

まとめ

Sails.jsのようなフルスタックのフレームワークは便利機能がたくさんあります。ただし、あまり考えずにシステムが作れてしまう分、よく理解していないと思わぬセキュリティホールやバグを埋め込んでしまう可能性があります。しっかりとフレームワークを理解し、大事な部分では「便利機能を使わない」という選択肢も検討しましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?