非常に機密性の高いデータを表示しています。ユーザーがサーバーからログアウトした後、ブラウザーの「戻る」ボタンを押してデータを他のユーザーが見ることができないようにします。
どうすればこれを達成できますか?
デフォルトでは、ブラウザの戻るボタンは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リクエストで実行するには、webappの<servlet-name>
のFacesServlet
のweb.xml
の値がfacesServlet
であると仮定して、フィルタークラスに次のアノテーションを設定します。
@WebFilter(servletNames={"facesServlet"})
または、制限されたページに一致するような特定のURLパターンのみで実行するようにするには、 /app/*
、/private/*
、/secured/*
などで、フィルタークラスに次の注釈を設定します。
@WebFilter("/app/*")
既にログインしているユーザーがいる場合は、ログインしているユーザーをチェックするフィルターで同じ作業を行うこともできます。
JSFユーティリティライブラリ OmniFaces を使用する場合は、その CacheControlFilter
を取得することもできます。また、これにより、JSFリソースが透過的に考慮されます。
また、別の良い解決策を見つけました。
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");
}
}