2011-08-04 10 views
1

私は、ユーザーがそのURLを入力するときに、ユーザーが意図的にroomIdを変更した場合、フローは、その後に作成され、この春のWebflow - エンドの流れと実行スナップショット

http://webserver.com/someapp/test/test-flow?roomId=12345

のようなURLを入力するセキュリティ要件のこの種を持っていますパラメータいくつかのセキュリティフィルタは、ユーザがその部屋に特にアクセスしているかどうかをチェックします。アクセス可能であれば、ユーザは処理を進めることができますが、そうでない場合は、フローを終了しなければなりません。だから、コードはフィルタからこの

エキスのようなものです:

public void doFilter(ServletRequest request, ServletResponse response, 
    FilterChain chain) throws IOException, ServletException { 
HttpServletRequest req = (HttpServletRequest) request; 
HttpServletResponse resp = (HttpServletResponse) response; 
String roomId = req.getParameter("roomId"); 
if (roomId != null) { 
    if (currentUserHasAccess(roomId)) { 
    chain.doFilter(request, response); 
    } else { 
    flowExecutionManager.endFlow(); 
    return; 
    } 
} 
chain.doFilter(request, response); 
} 

は今flowExecutionManagerは、私はこれらの行の順序を切り替えてみたendFlow方法では、この

public class FlowExecutionManager extends FlowExecutionListenerAdapter { 
private RequestControlContext context; 
private FlowDefinition definition; 

@Override 
public void sessionCreating(RequestContext context, 
    FlowDefinition definition) { 
super.sessionCreating(context, definition); 
this.context = (RequestControlContext) context; 
this.definition = definition; 
} 

public void endFlow() { 
if (context != null && definition != null) { 
    context.removeAllFlowExecutionSnapshots(); 
    context.endActiveFlowSession(definition.getId(), definition.getAttributes()); 
    Flow flow = (Flow)definition; 
    flow.destroy(); 
} 
} 

のようなものです

context.endActiveFlowSession(definition.getId(), definition.getAttributes()); 
context.removeAllFlowExecutionSnapshots(); 

これらの2行の順番に関係なく、私は常にこのようなNPEを取得します(extrスタックトレースの行為)

java.lang.NullPointerException 
at org.springframework.webflow.conversation.impl.SessionBindingConversationManager.getConversationContainer(SessionBindingConversationManager.java:140) 
at org.springframework.webflow.conversation.impl.SessionBindingConversationManager.getConversation(SessionBindingConversationManager.java:116) 
at org.springframework.webflow.execution.repository.support.AbstractFlowExecutionRepository.getConversation(AbstractFlowExecutionRepository.java:183) 
at org.springframework.webflow.execution.repository.support.AbstractFlowExecutionRepository.getConversation(AbstractFlowExecutionRepository.java:170) 
at org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository.removeAllFlowExecutionSnapshots(DefaultFlowExecutionRepository.java:156) 
at org.springframework.webflow.engine.impl.FlowExecutionImpl.removeAllFlowExecutionSnapshots(FlowExecutionImpl.java:431) 
at org.springframework.webflow.engine.impl.RequestControlContextImpl.removeAllFlowExecutionSnapshots(RequestControlContextImpl.java:230) 
at com.ags.blackcorp.finances.web.FlowExecutionManager.endFlow(FlowExecutionManager.java:26) 
at com.ags.blackcorp.finances.web.RoomFilter.doFilter(RoomFilter.java:100) 
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) 
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084) 
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378) 
at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109) 
at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) 
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101) 
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
at org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91) 
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
at com.ags.blackcorp.security.ui.webapp.AfterAuthenticationProcess.doFilterHttp(AfterAuthenticationProcess.java:55) 
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
at org.springframework.security.ui.preauth.AbstractPreAuthenticatedProcessingFilter.doFilterHttp(AbstractPreAuthenticatedProcessingFilter.java:69) 
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235) 
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175) 
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) 
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084) 

どうやらラインcontext.endActiveFlowSession(definition.getId(), definition.getAttributes());は、フローを終了ですが、私は、実行スナップショットを削除傾けます。 私が間違っていると思われるアイデア、または実行スナップショットを削除する方法。 最良のアプローチに関する考え方。 ありがとうございます。自分の質問に答えるためにしようと

+0

フロー開始時にflowId変数にroomIdを格納してからクエリパラメータその後?その後、ユーザーが何をしているのか気にする必要はありません。 – Patrick

答えて

0

は、次のコードに私を導いた:

public void endFlow() { 
if (context != null && definition != null) { 
    ExternalContextHolder.setExternalContext(contex.getExternalContext()); 
    context.removeAllFlowExecutionSnapshots(); 
    context.endActiveFlowSession(definition.getId(), definition.getAttributes()); 
    Flow flow = (Flow)definition; 
    flow.destroy(); 
    } 
} 

ExternalContextHolder ...ラインは、NPEを回避し、スナップショットを除去し、flowSessionそのも終了、しかし新たな疑問を持っています発生しました

  • なぜExternalContextHolderが必要ですか?大丈夫ですか?。以下は

いくつかの奇妙な(あるいは、それは正常です?)行動イムは

を取得している「私は、ブラウザのTAB1に流れe1s1を開始し、またe2s1別のタブでは、e2s1になりました場合イムをクリックしたとし私のウィザードの次のボタンはe2s2を取得します(これは正しいです)。e1s1に属する実行スナップショットを削除すると問題なく削除されますが、e2s2のタブに移動して「前の」ボタンをクリックすると以前のスナップショットに戻ると、スナップショットe2s1もなくなりました。つまり、スナップショットの削除は「実行ごと」のようなものでなければなりません。私は、FlowExecutionRepositoryクラスのメソッドremoveFlowExecutionを使用してフロー実行を削除する新しいコードをテストしましたが、今は表示されません。代わりに誰かがいくつかのポインタを投げることができます。とにかく誰もループに興味を持っていない場合、何も表示されない。

もう一度私の質問に答えて、うまくいけば、これは最後の答えです。

Q:ExternalContextHolderはなぜ必要ですか?

Ans:Springのアクセス権(HttpServletRequestとHttpServletResponse)が要求を行っている誰から送信されたデータにもアクセスできるように、私の小さな経験によればおそらく他のものの中でも特にExternalContextHolderが必要です。

最後に、フィルタからのフロー実行を削除することは良いアイデアのように聞こえるかもしれませんが、webflowを使用すると、FlowExecutionListenerAdapterをサブクラス化し、この場合はメソッド "void requestSubmitted(RequestContext context)"をオーバーロードします私は、ユーザーがroomIdへのアクセス権を持つwheterか現在確認した後、私は、メソッドendFlowを呼ぶ(以下のコードを参照)

public void endFlow(ExternalContext externalContext) { 
FlowUrlHandler handler = flowController.getFlowUrlHandler(); 
HttpServletRequest request = (HttpServletRequest) externalContext.getNativeRequest(); 
String stringKey = handler.getFlowExecutionKey(request); 
if (stringKey != null) { 
    FlowExecutorImpl flowExecutor = (FlowExecutorImpl) flowController.getFlowExecutor(); 
    FlowExecutionRepository repository = flowExecutor.getExecutionRepository(); 
    FlowExecutionKey key = repository.parseFlowExecutionKey(stringKey); 
    ExternalContextHolder.setExternalContext(externalContext); 
    FlowExecutionLock lock = null; 
    try{ 
    lock = repository.getLock(key); 
    }catch(NoSuchFlowExecutionException nsfee){  
    return; 
    } 
    lock.lock(); 
    try { 
    FlowExecution flowExecution = repository.getFlowExecution(key); 
    repository.removeFlowExecution(flowExecution); 
    } finally { 
    lock.unlock(); 
    } 
} 
} 

なFlowController(org.springframework.webflow.mvc.servlet.FlowController)はバネによって注入され、そのWebflow設定ファイルに追加されました。 上記のコードは、フローの実行を完全に削除します。ユーザーが前のフローに戻る場合は、e1s1とし、webflowが自動的に新しいフロー実行e2s1を作成します。場合

uは、フィルタのアプローチを使用したいuはdoFilterメソッドに必要なすべてのこの

public void doFilter(ServletRequest request, ServletResponse response, 
    FilterChain chain) throws IOException, ServletException { 
HttpServletRequest req = (HttpServletRequest) request; 
HttpServletResponse resp = (HttpServletResponse) response; 
String roomId = req.getParameter("roomId"); 
ExternalContext externalContext = new ServletExternalContext(
    this.servletContext, req, resp); 
if (roomId != null) { 
    if (!currentUserHasAccess(roomId)) { 
     flowExecutionManager.endFlow(); 
     return; 
    } 
} 
chain.doFilter(request, response);  

this.servletContextそのfilterConfig.getServletContext()

0

ごめんなさい、私ができる経て得られました私はそのようにするには十分なポイントがないので、コメントしませんが、あなたのユースケースへの実装は、はるかに複雑であるようです。あなたの質問のコメント欄に@Patrickが提案したように、なぜroomId引数をflowScope varに格納できないのですか?フローファイルで検証を実行したり、検証メソッドを呼び出したり、検証の成功または失敗のために必要な遷移を実行することができます。フレームワークによって処理されることになっているWebFlow成果物であるため、スナップショットを気にする必要はありません。