49

非常に機密性の高いデータを表示しています。ユーザーがサーバーからログアウトした後、別のユーザーがブラウザの [戻る] ボタンをクリックしたデータを表示できないようにします。

どうすればこれを達成できますか?

4

2 に答える 2

82

デフォルトでは、ブラウザの戻るボタンは HTTP リクエストをサーバーに送信しません。代わりに、ブラウザのキャッシュからページを取得します。これは本質的に無害ですが、実際にはエンドユーザーを混乱させます。なぜなら、エンドユーザーはそれが実際にサーバーから来ていると誤って考えているからです。

制限されたページをキャッシュしないようにブラウザに指示するだけです。これは、適切な応答ヘッダーを設定する単純なサーブレット フィルターで行うことができます。

@WebFilter
public class NoCacheFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (!request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
            response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
            response.setDateHeader("Expires", 0); // Proxies.
        }

        chain.doFilter(req, res);
    }

    // ...
}

(このフィルターは JSF リソース要求をスキップすることに注意してください。そのキャッシュは実際には個別に構成する必要があります)

すべての JSF リクエストで実行するには、フィルタ クラスに次のアノテーションを設定します。ただし、Web アプリケーションの の<servlet-name>の値が であると仮定します。FacesServletweb.xmlfacesServlet

@WebFilter(servletNames={"facesServlet"})

または、制限されたページ ( 、/app/*、など) に一致する特定の URL パターンのみで実行するには、フィルター クラスに次の注釈を設定します。/private/*/secured/*

@WebFilter("/app/*")

すでにログインしているユーザーをチェックするフィルターで、まったく同じジョブを実行することもできます。

JSF ユーティリティ ライブラリOmniFacesを使用している場合は、そのCacheControlFilter. これにより、JSF リソースも透過的に考慮されます。

以下も参照してください。

于 2012-04-24T20:50:46.097 に答える
10

また、別の良い解決策を見つけました。

faces-config.xml に追加

<lifecycle>
    <phase-listener id="nocache">client.security.CacheControlPhaseListener</phase-listener>
</lifecycle>

そして、次のクラスを実装します。

package client.security;

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class CacheControlPhaseListener implements PhaseListener
{
    public PhaseId getPhaseId()
    {
        return PhaseId.RENDER_RESPONSE;
    }

    public void afterPhase(PhaseEvent event)        
    {
    }

    public void beforePhase(PhaseEvent event)
    {
       FacesContext facesContext = event.getFacesContext();
       HttpServletResponse response = (HttpServletResponse) facesContext
                .getExternalContext().getResponse();
       response.addHeader("Pragma", "no-cache");
       response.addHeader("Cache-Control", "no-cache");
       // Stronger according to blog comment below that references HTTP spec
       response.addHeader("Cache-Control", "no-store");
       response.addHeader("Cache-Control", "must-revalidate");
       // some date in the past
       response.addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");
    }
} 
于 2012-04-25T15:01:37.840 に答える