web-dev-qa-db-ja.com

JavaScriptでSESSIONを確認する方法

私はコンポーネントを開発していて、フロントエンドでいくつかのタスクを実行するためにajax呼び出しを使用しています。セッションの有効期限が切れたときに問題が発生し、キープアライブを使用して解決したくありません。

フロントエンドにはリストビューがあります。また、ajaxリクエストを使用してタスクを実行するボタンがいくつかあります。

例えば ​​:

_$('#resetData').on('click', function (e) {
  e.preventDefault();
  var token = jQuery("#token").attr("name");
  var itemId = $(this).attr('data-id');
$.ajax({
  method: 'POST',
  cache: false,
  dataType: "json",
  data: { [token]: "1", id: itemId},
  url: 'index.php?option=com_contract&task=contract.resetData'
}).success(function (r) {
  console.log('Response :');
  console.log(r);
  if (r.responseText) {
    UIkit.modal.alert(r.responseText).then(function () {
      window.location.reload();
    });
  }
  if (r.message) {
    UIkit.modal.alert(r.message).then(function () {
      window.location.reload();
    });
  }
}).error(function (err) {
  console.log(err);
  UIkit.modal.alert('<div class="alert alert-error">' + err + '</div>').then(function () {
    return;
  });
}).complete(function (r) {
  console.log(r.responseText);
});
_

セッションの有効期限が切れると、メインのコントローラーでログインページにリダイレクトします。 JFactory::getApplication()->redirect(JURI::base() . 'index.php?option=com_users&view=login', $error, 'error'); //redirect to login page

つまり、Ajax応答で穴のhtmlが返され、応答をポップアップすると、人間が読めるエラーではなく_[object object]_が表示されます。

Ajaxを呼び出す前に、clickイベントが発生したときにセッションが期限切れになったかどうかを確認してエラーを通知する方法を見つける必要があると思います。

JavaScriptでJSESSIONをチェックすること、またはそれを解決する他の方法は可能ですか?

3
mixahlos

セッションを確認するために私が想像できる1つの方法は、上記のajax呼び出しを開始する前に、com_contract/controller(task =新しいセッションチェック関数の別の関数に対して以前のajax呼び出しを行うことです。so:url:... com_contract/task = checkSession)次のような関数を作成します。

public function checkSession() 
{
  try
    {    
      $session1 = JFactory::getSession();
      $isActive = $session1->isActive();
      $sessionState = $session1->getState();
      echo new JResponseJson($isActive, $sessionState);
    }
  catch(Exception $e)
    {
      echo new JResponseJson($e);
    }
}

この関数をここですばやく作成したので、間違いがある可能性があり、さらに何かを改善することができますが、これがajaxを介してセッションのチェックを開始する方法です。

もう1つの意味は、私によると、セッションが期限切れになると、この呼び出し中にトークンが無効になる可能性があるということです。私はそれを試みなかったので、ajax呼び出しが(期限切れのセッションから)トークンを使用して送信できるかどうかをテストする必要があります。論理的に聞こえません。

まさにこの理由(期限切れのトークン)が原因で、セッションの他のソリューションではなく、セッションを存続させることを以前に提案しました。

このサブジェクトに関する追加のヒント(このサブジェクトはここで何度も表示されるため)

期限切れのセッショントークンを使用してajax呼び出しを行おうとすると、常に「無効なトークン」応答が返されるため、とにかくajax呼び出しが失敗するため、応答が「無効」の場合はJavaScriptでリダイレクトすることをお勧めします。トークン」は、セッションが期限切れになったため、または無効な応答(単にajax呼び出しが失敗した)が原因です。次に、セッションのチェック機能を例として数行で拡張できますが、この場合はおそらく有効な目的がありません。

public function checkSession() 
{
    if (! JSession::checkToken())
    {
        echo new JResponseJson('invalid token');
        // jexit( 'Invalid Token' );
    }
    else
    {
      try
        {    
          $session1 = JFactory::getSession();
          $isActive = $session1->isActive();
          $sessionState = $session1->getState();
          echo new JResponseJson($isActive, $sessionState);
        }
      catch(Exception $e)
        {
          echo new JResponseJson($e);
        }
    }
}

これをこの主題に追加したかった。ただし、この比較的冗長な機能がなければ、無効なトークンの応答によってJavaScriptのリダイレクトが開始されるため、ここではセッションの状態を確認する必要はありません。少なくとも今のところ、その理由はわかりません。

別の重要なポイントについてAJAX通話

上記の理論と理由により、この問題の解決策は2つではなく1つのajax呼び出しのみです(javascriptのpromise構造が複雑になる可能性があるため)。問題がコメントで言及されたように。つまり、トークンチェックを元のコントローラー関数(resetData)に配置するだけです。したがって、トークンをチェックするために別の関数を使用する必要はありません。ここでは基本に戻ります。もちろん、元のJoomla関数はトークンチェックで開始する必要があります。無効なトークンで失敗しない場合は、完了することができます。

public function resetData()
{
    if (! JSession::checkToken())
    {
        echo new JResponseJson('invalid token');
        die('my messages';
    }
    elseif ( JSession::checkToken())
    {

        // all of your resetData function steps

    }
}

または、この種類のJoomla関数のすべてで指定されているため、さらに簡単です。

public function resetData()
{
    JSession::checkToken() or die('my messages');
    // then all of your resetData function steps...
    // what is giving back different responses
}

したがって、これはajaxで呼び出されるJoomla関数の正しいスタートです。

3
Zollie

セッション状態を取得するには、以下を使用できます。

_JFactory::getSession()->getState();
_

このスクリプトがインラインか別のファイルかはわかりません。インラインの場合は、次のコードをJavaScriptに追加するだけです。

_var sessionState = '<?php echo JFactory::getSession()->getState(); ?>';
if (sessionState === 'expired') {
    // redirect to login page
}
_

補足として、.success().error()の使用はjQueryでは非推奨です。 .done()および.fail()を使用してください。また、ご存知のとおり、.then()はIE11では機能しません。

2
Lodder

@Zollieの貴重な助けの後で、私は他の人を助けるために答えと作業コードを投稿します。

テンプレートファイルのサンプル:

    <form action="<?php echo JRoute::_('index.php?option=com_contract&view=contracts'); ?>" id="adminForm" method="post" name="adminForm">
      <?php if (!empty($this->items)) { ?>
        <div class="contractList items">
          <?php foreach ($this->items as $item) {?>
            <div class="contract item">
              <h3> <?php echo $item->title; ?></h3>
              <p> <?php echo $item->text; ?></p>
              <div class="actions">
                <a class="action" href="#" data-action="unpublish"><?php echo JText::_('COM_CONTRACT_UNPUBLISH_ITEM');?></a>
                <a class="action" href="#" data-action="resetData"><?php echo JText::_('COM_CONTRACT_RESTET_ITEM');?></a>
                    <input type="checkbox" class="uk-checkbox" name="cid[<?php echo $i; ?>]" id="cb<?php echo $i; ?>" value="<?php echo $item->id; ?>" onclick="Joomla.isChecked(this.checked);">
              </div>
           </div>
          <?php } ?>
        </div>
      <? } ?>
      <input type="hidden" name="task" value=""/>
      <?php echo '<input id="token" type="hidden" name="' . JSession::getFormToken() . '" value="1" />'; // We need the token this way in order to get it to the javascript. ?>
    </form>

JavaScript

<script type="text/javascript">
  function checkSession(caller) {
    var token = jQuery("#token").attr("name");
    $.ajax({
      method: 'POST',
      dataType: "json",
      data: {[token]: "1"},
      url: 'index.php?option=com_contract&task=contracts.checkSession'
    }).done(function (r) {
      // Since we had a success call, means that the session is active so we can continue to call the actual task.
      var data = {};
      data.id = $(caller).closest("div.actions").find("input[type='checkbox']").val();
      data.action = $(caller).attr('data-action');
      ajaxSubmit('index.php?option=com_contract&task=contracts.' + data.action, token, data);
    }).fail(function (err) {
      // If there the call fails, means there is no active session.
      UIkit.modal.alert('<div class="alert alert-error">' + Joomla.JText._('SESSION_TIMEOUT') + '</div>').then(function () {
        window.location.reload(); // reload to get to the login page.
      });
    });
  }

  function ajaxSubmit(Url, token, data) {
    $.ajax({
      method: 'POST',
      dataType: "json",
      data: {[token]: "1", data},
      url: Url
    }).done(function (r) {
        window.location.reload();
      }
      if (r.message) {
        UIkit.modal.alert(r.message).then(function () {
          window.location.reload();
        });
      }
    }).fail(function (err) {
      UIkit.modal.alert('<div class="alert alert-error">' + err + '</div>').then(function () {
        return;
      });
    });
  }
$(document).ready(function () {
  $('.action').on('click', function (e) {
    e.preventDefault();
    checkSession(this);
  });
});
</script>

コントローラーの機能

checkSession関数では、関数が呼び出された場合、セッションがまだアクティブであることを意味するため、何を返すかは問題ではないことに気付きました。

  public function checkSession() {
    if (!JSession::checkToken()) {
      echo new JResponseJson('invalid token');
      JFactory::getApplication()->close();
    }
  }

私は数多くのテストを行っており、常に動作しています。

2
mixahlos