Maison  >  Article  >  développement back-end  >  Renforcer les mesures de sécurité pour les startups : un guide

Renforcer les mesures de sécurité pour les startups : un guide

WBOY
WBOYoriginal
2023-09-03 10:45:021354parcourir

Renforcer les mesures de sécurité pour les startups : un guide

Ce tutoriel fait partie de la série « Construisez votre startup avec PHP » sur Envato Tuts+. Dans cette série, je vais vous guider tout au long du lancement d'une startup, du concept à la réalité, en utilisant mon application de planification de réunions comme exemple concret. À chaque étape du processus, je publierai le code de Meeting Planner comme exemple open source dont vous pourrez tirer des leçons. J'aborderai également les problèmes commerciaux liés aux startups qui se posent.

Dans le dernier épisode, j'ai principalement présenté la sécurité des serveurs Web et le contrôle d'accès. Dans l'émission d'aujourd'hui, je discuterai des protections supplémentaires que j'ai ajoutées à Meeting Planner. Étant donné que tout le code a été écrit dans le framework PHP Yii2, j'ai pu exploiter le framework pour de nombreuses fortifications. Si vous souhaitez en savoir plus sur Yii2, consultez notre série parallèle « Programmation avec Yii2 ».

Vous pouvez essayer le planificateur de réunions dès maintenant en planifiant votre première réunion. N'hésitez pas à poster des commentaires sur votre expérience dans les commentaires ci-dessous. Je suis également ouvert aux idées de nouvelles fonctionnalités et aux suggestions de sujets pour les futurs didacticiels.

Sécurité renforcée

La mise en œuvre de différents niveaux de sécurité pour Meeting Planner prend plusieurs heures. Maintenant que le serveur est configuré de manière plus robuste, je souhaite vous guider à travers d'autres domaines de sécurité de votre code d'application.

Protéger les clés et les codes

Évidemment, il est important de garder vos clés d’authentification à l’abri des pirates, mais il est également facile de les publier sur GitHub. Des rapports font état de fichiers archivés accidentellement à l'aide de mots de passe de service ou de clés API.

Pour éviter que cela ne se produise dans Yii, je conserve un fichier .ini externe en dehors de l'arborescence des codes. Celui-ci sera chargé en haut de /frontend/config/main.php et utilisé pour toute configuration de composant nécessaire :

<?php
$config = parse_ini_file('/var/secure/meetme.ini', true);

$params = array_merge(
    require(__DIR__ . '/../../common/config/params.php'),
    require(__DIR__ . '/../../common/config/params-local.php'),
    require(__DIR__ . '/params.php'),
    require(__DIR__ . '/params-local.php')
);

return [
    'id' => 'mp-frontend',
    'name' => 'Meeting Planner',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'controllerNamespace' => 'frontend\controllers',
    'components' => [
      'authClientCollection' => [
              'class' => 'yii\authclient\Collection',
              'clients' => [
                  'facebook' => [
                      'class' => 'yii\authclient\clients\Facebook',
                      'clientId' => $config['oauth_fb_id'],
                      'clientSecret' => $config['oauth_fb_secret'],
                  ],

Dans l'exemple ci-dessus, vous pouvez voir le secret de l'API Facebook chargé à partir du fichier d'initialisation.

Le format du fichier d'initialisation est assez simple :

mysql_host="localhost"
mysql_un="xxxxxxxxxxxxxxxxxxx"
mysql_db="xxxxxxxxxxxxxxxxxxx"
mysql_pwd="xxxxxxxxxxxxxxxxxxx"
mailgun_user = "xxxxxxxxxxxxxxxxxxx@meetingplanner.io"
mailgun_pwd = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
mailgun_api_key="key-9p-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
mailgun_api_url="https://api.mailgun.net/v2"
mailgun_public_key="pubkey-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
oauth_fb_id="1xxxxxxxxxxxxxxxxxxx3"
oauth_fb_secret="bcxxxxxxxxxxxxxxxxxxxda"

Yii2 vous encourage à mettre certains de ces paramètres dans le répertoire /environments, surtout si les paramètres diffèrent entre le développement et la production.

Il est donc important que votre fichier .gitignore exclue les versions locales de ces fichiers :

#local environment files
/environments/prod/common/config/main-local.php
/environments/prod/frontend/config/main-local.php
/frontend/config/params-local.php
/frontend/config/main-local.php

Voici un exemple d'un de mes fichiers de paramètres locaux, /frontend/config/params-local.php :

<?php
return [
  'ga' => 'UA-xxxxxxxxxx-12',
  'urlPrefix' => '',
  'google_maps_key' => 'AIzzzzzz1111222222xxxxxxQ',
];

Je pourrais probablement passer plus de temps à mieux les organiser.

Bloquer les mauvaises inscriptions

Renforcer les mesures de sécurité pour les startups : un guide

Pour la version Alpha, j'ai envoyé la mise à jour par lots. De plus, au début de Meeting Planner, il y avait plus de mauvais e-mails que prévu. Mailgun facilite l'identification des rebonds et des échecs :

$badEmails=[ '', 'test2@gmail.com', '1111@gmail.com', 'qwerty@gmail.com',
 'amjadiqbalkhanniazi@gmail.com', 'admin@admin.com', 'rhizalpatra@fellow.lpkia.ac.id', 'tm@archi.com',
 'test@test.com', 'web@yahoo.fr', 'a@a. a', 'ailaa@aa.com', 'be@yahoo.fr', 'vico@gmail.com',
 'nobu@gmail.com', 'a@gmail.com', 'ct@gmail.com', 'sanjaydk@projectdemo. biz', 'trial@gmail.com',
 'varlog255q@hotmail.com', 'baah@baah.com', 'minhvnn1@gmail.com', 'test@gmail.com',
 'test@mediabite.co.uk', 'ddd@c. hu', 'ddd@ymail.com', 'a. chetan@saisoftex.com', 'user02@local.com',
 'Imrky4@gmail.com', 'robomadybu@hotmail.com', 'mike@mike. mike', 'abcd@gmail.com',
 'azazaz@azazaza.com', 'mama@mama.mn', 'qweqwe@qwe. qwe', 'testere@wp.pl', 'kaze@hotmail.com',
 'test@usertest.fr', 'demodemo@demo.com', 'qqq@dd.gh', 'gnfbb@h. vo', 'admin@admin123.com',
 'testsir@testsir.com', 'oi. hd@yeah1.vn', 'loi. hd@yeah1.vn', 'test@email.com', 'salom@salom.com',
 'ar@yahoo.com', 'lex@gmail.com', 'Tester1234@gmail.com', 'mantaf@mail.com', 'aaa@aaa.com',
 'oeui@gmail.com', 'risitesh. biswal14@yahoo.com', 'ttt@wp.pl', 'nnn@nnn.net', 'nnn2@nnn.net',
 'ana@gmail.com', 'asdf@yahoo.com', 'noom@gmail.com', 'jomon@example.com', 'asdfasdf@yahoo.com',
 'admin@yahoo.com', 'abinubli@mail.com', 'tes@tes.com', 'asdasdr@asd.com', 'something@some.com',
 'ademin@example.com', 'd@dd.com', 'robo@gmail.com', 'toto@titi.com', 'fesfe@fseff. fes',
 'master@wpthemeslist.com', 'teste@teste.com', 'barny182@hotmail.com', 'test@admin.com',
 'billtian@test.com', 'Test@goggle.ca', 'jm@gmail.com', 'john-panin@qip.ru', 'loslos@loslos.com',
 'ghfhf@jhgjgjk.com', 'lol@lol.com', 'tester1@gmail.com', 'g0952180828@gmail.com', 'testim@testim.com',
 'mnml.name@gmail.com', 'endri. azizi. 92@gmail.com', '123123@gmail.com', 'myfriend@gmai.com',
 'geraldo_1989@hotmail.com', 'rob. test. 999@gmail.com', 'j@c. com', 'Agung. andika@mhs.uinjkt.ac.id',
 'W3test@ya.ru', 'user@ya.ru', 'ed@ed. fl', 'ed@ed.es', ];

La majeure partie de cela s'est probablement produite lorsque l'organisateur de réunions était inactif lors de sa première sortie – pendant mon traitement pour une tumeur au cerveau et mon opération chirurgicale.

Récemment, j'ai rendu très simple l'inscription à Meeting Planner en ajoutant la connexion sociale, mais l'enregistrement anti-spam est toujours possible. Je veux qu'il soit plus difficile pour les gens de s'inscrire avec un mauvais e-mail.

Heureusement, Yii fournit certaines fonctionnalités pour prendre en charge cette fonctionnalité.

Code de vérification

Yii2 fournit désormais des codes de vérification intégrés. Par conséquent, toute personne s’inscrivant en utilisant l’ancienne méthode d’e-mail et de mot de passe devra saisir un code de vérification. Vous pouvez voir les captcha champs ci-dessous :

<p>Or, fill out the following fields to register manually:</p>
        <div class="col-lg-5">
            <?php $form = ActiveForm::begin(['id' => 'form-signup']); ?>
                <?= $form->field($model, 'username') ?>
                <?=
                $form->field($model, 'email', ['errorOptions' => ['class' => 'help-block' ,'encode' => false]])->textInput() ?>
                <?= $form->field($model, 'password')->passwordInput() ?>
                <?= $form->field($model, 'captcha')->widget(\yii\captcha\Captcha::classname(), [
                      // configure additional widget properties here
                  ]) ?>
                <div class="form-group">
                    <?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
                </div>
            <?php ActiveForm::end(); ?>
        </div>

Ensuite, ajoutez la conformité CAPTCHA comme règle pour le modèle SignupForm :

<?php
namespace frontend\models;

use common\models\User;
use yii\base\Model;
use Yii;
use yii\helpers\Html;
use yii\validators\EmailValidator;

/**
 * Signup form
 */
class SignupForm extends Model
{
    public $username;
    public $email;
    public $password;
    public $captcha;

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            ['username', 'filter', 'filter' => 'trim'],
            ['username', 'required'],
            ['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
            ['username', 'string', 'min' => 2, 'max' => 255],
            ['email', 'filter', 'filter' => 'trim'],
            ['email', 'required'],
            ['email', 'email', 'checkDNS'=>true, 'enableIDN'=>true],
            ['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken. '.Html::a('Looking for your password?', ['site/request-password-reset'])],
            ['password', 'required'],
            ['password', 'string', 'min' => 6],
            ['captcha', 'required'],
            ['captcha', 'captcha'],
        ];
    }

Si les gens ne saisissent pas la bonne réponse captcha, ils ne peuvent pas s’inscrire. Cela rend difficile pour les spammeurs d’automatiser les inscriptions.

Vérifiez DNS

Je souhaite également minimiser l'utilisation de fausses adresses e-mail pour m'inscrire. La validation checkDNS de Yii recherche en fait un enregistrement MX valide en fonction du domaine de l'adresse e-mail :

['email', 'email', 'checkDNS'=>true, 'enableIDN'=>true],

Par exemple, si je tape par erreur gmail.com comme gmal.com, checkDNS 将返回 false renverra false. gmal.com n'a aucun enregistrement MX enregistré. De même, spambotolympics9922.com ne le fait pas.

En fin de compte, la sécurité est un processus itératif. Il y a toujours plus à faire.

Limiter les abus

Ensuite, je souhaite ajouter des limites communes au nombre d'actions que les gens peuvent effectuer pour limiter les abus et empêcher l'application de devenir lourde.

Création de réunions

Pour éviter que les gens créent beaucoup de réunions vides, j'ai créé un findEmptyMeeting qui recherche les réunions vides et les réutilise chaque fois que quelqu'un essaie d'en créer une nouvelle :

public function actionCreate()
    {
        // prevent creation of numerous empty meetings
        $meeting_id = Meeting::findEmptyMeeting(Yii::$app->user->getId());
        //echo $meeting_id;exit;
        if ($meeting_id===false) {
        // otherwise, create a new meeting
          $model = new Meeting();
          $model->owner_id= Yii::$app->user->getId();
          $model->sequence_id = 0;
          $model->meeting_type = 0;
          $model->save();
          $model->initializeMeetingSetting($model->id,$model->owner_id);
          $meeting_id = $model->id;
        }
        $this->redirect(['view', 'id' => $meeting_id]);
    }

En d'autres termes, si un utilisateur crée une nouvelle réunion 1 700 fois, il verra toujours la première réunion vide qu'il crée.

Fréquence de fonctionnement limite

J'ai également créé une withinLimit méthode d'une structure commune à réutiliser autour de l'application, cela évite que trop d'opérations soient effectuées dans un court laps de temps. L'exemple suivant vérifie si le nombre de réunions créées au cours de la dernière heure et du dernier jour ne dépasse pas n :

public static function withinLimit($user_id,$minutes_ago = 180) {
      // how many meetings created by this user in past $minutes_ago
      $cnt = Meeting::find()
        ->where(['owner_id'=>$user_id])
        ->andWhere('created_at>'.(time()-($minutes_ago*60)))
        ->count();
      if ($cnt >= Meeting::NEAR_LIMIT ) {
        return false;
      }
      // check in last DAY_LIMIT
      $cnt = Meeting::find()
        ->where(['owner_id'=>$user_id])
        ->andWhere('created_at>'.(time()-(24*3600)))
        ->count();
      if ($cnt >= Meeting::DAY_LIMIT ) {
          return false;
      }
      return true;        
    }

每当有人尝试创建会议时,我们都会检查 withinLimit 以查看他们是否可以。如果没有,我们会显示 flash 错误消息:

public function actionCreate()
    {
        if (!Meeting::withinLimit(Yii::$app->user->getId())) {
          Yii::$app->getSession()->setFlash('error', Yii::t('frontend','Sorry, there are limits on how quickly you can create meetings. Visit support if you need assistance.'));
          return $this->redirect(['index']);
        }
    

限制操作数量

我还想限制操作的总数。例如,每个会议参与者只能为每次会议添加七个会议日期时间。在 MeetingTime.php 中,我设置了 MEETING_LIMIT,以便稍后可以更改:

  const MEETING_LIMIT = 7;

然后,MeetingTime::withinLimit() 检查以确保任何用户的建议次数不超过七次:

public static function withinLimit($meeting_id) {
      // how many meetingtimes added to this meeting
      $cnt = MeetingTime::find()
        ->where(['meeting_id'=>$meeting_id])
        ->count();
        // per user limit option: ->where(['suggested_by'=>$user_id])
      if ($cnt >= MeetingTime::MEETING_LIMIT ) {
        return false;
      }
      return true;
    }

当他们去创建 MeetingTime 时,控制器创建方法会检查限制:

public function actionCreate($meeting_id)
    {
      if (!MeetingTime::withinLimit($meeting_id)) {
        Yii::$app->getSession()->setFlash('error', Yii::t('frontend','Sorry, you have reached the maximum number of date times per meeting. Contact support if you need additional help or want to offer feedback.'));
        return $this->redirect(['/meeting/view', 'id' => $meeting_id]);
      }
    

保护 CRON 作业

今天最后,我想确保对远程 cron 作业的访问安全。互联网上描述了一些有趣的方法。目前,我正在检查 $_SERVER['REMOTE_ADDR'](请求 IP 地址)是否与托管 $_SERVER['SERVER_ADDR' 是同一服务器],本地IP地址。 $_SERVER['REMOTE_ADDR'] 可以安全使用,换句话说,我已经了解到它无法被欺骗。

  // only cron jobs and admins can run this controller's actions
    public function beforeAction($action)
    {
      // your custom code here, if you want the code to run before action filters,
      // which are triggered on the [[EVENT_BEFORE_ACTION]] event, e.g. PageCache or AccessControl
      if (!parent::beforeAction($action)) {
          return false;
      }
      // other custom code here
      if (( $_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR'] ) ||
          (!\Yii::$app->user->isGuest && \common\models\User::findOne(Yii::$app->user->getId())->isAdmin()))
       {
         return true;
       }
      return false; // or false to not run the action
    }

对于我自己的测试,我还允许登录的管理员运行 cron 作业。

最终,我还可以为我的 cron 作业添加密码,并将它们移至命令行操作。

展望未来

在过去的两集中,我已经完成了许多安全改进,但仍有更多工作要做。我的候选清单上包括对访问安全性的更深入审查,特别是通过 AJAX、IP 地址跟踪和阻止,以及仔细过滤所有用户输入。

再说一遍,你还在等什么?安排您的第一次会议,并在评论中分享您的反馈。我也非常感谢您对安全问题的评论。

与往常一样,您可以观看“使用 PHP 构建您的初创公司”系列中即将推出的教程,或关注我 @reifman。还有更多重要功能即将推出。

相关链接

  • 会议策划
  • 关注会议策划者的资金概况
  • 建立您的初创公司:基本安全性 (Envato Tuts+)
  • 使用 Yii2 编程:安全性 (Envato Tuts+)
  • Yii2 开发者交流会

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn