Spring security 如何将Spring web流、Spring安全性和HandlerExceptionResolver(如SimpleMappingExceptionResolver)结合起来?

Spring security 如何将Spring web流、Spring安全性和HandlerExceptionResolver(如SimpleMappingExceptionResolver)结合起来?,spring-security,spring-webflow,Spring Security,Spring Webflow,我有一个SimpleMappingExceptionResolver来重定向每个未处理的异常 @Bean public SimpleMappingExceptionResolver exceptionResolver() { SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); resolver.setDefaultErrorView("gene

我有一个
SimpleMappingExceptionResolver
来重定向每个未处理的异常

 @Bean public SimpleMappingExceptionResolver exceptionResolver() {
           SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
           resolver.setDefaultErrorView("general-error");
           resolver.setWarnLogCategory(TamponException.class.getName());
           return resolver;
}
我一实现Spring安全性,就意识到需要排除
AccessDeniedException

resolver.setExcludedExceptions(AccessDeniedException.class);
现在我正在实现SpringWebFlow。SWF正在将那些基本的
AccessDeniedException
s包装在
FlowExecutionException
中。这种组合破坏了Spring的安全性,因为那些被包装的异常现在被
SimpleMappingExceptionResolver
捕获。我也可以排除
FlowExecutionException
,但这不是我想要的

如何正确解决这个问题


我的下一个想法是实现一个
HandlerExceptionResolver
,只有当未包装的异常不是
AccessDeniedException
时,它才会委托
resolveException()
。但是我想知道是否还没有可以用于组合SWF、安全性和HandlerExceptionResolver的配置。

我使用的配置与您的配置类似,包括SpringWebflow和SpringSecurity。为了处理异常,我使用webflow处理而不是SimpleMappingExceptionResolver,这对我来说非常有效

首先,您需要一个处理异常的全局xml流,该流将用作所有其他流的“父级”。或者,您也可以在流中直接包含全局转换和视图状态:

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
      http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
      abstract="true">

    <persistence-context/>

    <view-state id="generalException" view="../views/exception/generalException.xhtml">
        <on-entry>
            <evaluate expression="exceptionManager.extractMessages(flowExecutionException, rootCauseException)" result="viewScope.exc"/>
        </on-entry>
    </view-state>

    <global-transitions>
        <transition on-exception="java.lang.Exception" to="generalException"/>
    </global-transitions>

</flow>

类ExceptionManager仅用于以可读的方式格式化异常,特别是在我的示例BatchUpdateException中,它需要调用next()方法才能知道异常的来源:

@Service("exceptionManager")
public class ExceptionManagerImpl {

    public Map<String, String> extractMessages(Exception e, Exception root)
    {
        Map<String, String> out = new HashMap<String, String>();

        out.put("exc_message", e.getClass().toString() + ": " + e.getMessage());
        out.put("exc_details", formatStackTrace(e.getStackTrace()));
        out.put("root_message", root.getClass().toString() + ": " + root.getMessage());
        out.put("root_details", formatStackTrace(root.getStackTrace()));
        if (root instanceof BatchUpdateException)
        {
            out.put("batch_message", ((BatchUpdateException)root).getNextException().getClass().toString() + ": " + ((BatchUpdateException)root).getNextException().getMessage());
        }

        return out;
    }

    public String formatStackTrace(StackTraceElement[] elements)
    {
        String out = "";
        for (StackTraceElement ste: elements)
            out += ste.toString() + "<br/>";
        return out;
    }
}
@服务(“例外管理器”)
公共类例外管理器{
公共映射消息(异常e、异常根)
{
Map out=newhashmap();
out.put(“exc_message”,e.getClass().toString()+”:“+e.getMessage());
out.put(“exc_details”,formatStackTrace(e.getStackTrace());
out.put(“root_message”,root.getClass().toString()+”:“+root.getMessage());
out.put(“root_details”,formatStackTrace(root.getStackTrace());
if(BatchUpdateException的根实例)
{
out.put(“batch_message”,((BatchUpdateException)root.getNextException().getClass().toString()+”:“+((BatchUpdateException)root.getNextException().getMessage());
}
返回;
}
公共字符串格式StackTrace(StackTraceElement[]元素)
{
串出“”;
用于(StackTraceElement存储:元素)
out+=ste.toString()+“
”; 返回; } }
通过这种方式,所有未处理的异常都将显示在JSF页面中,或者任何您用于视图的页面中。AccessDeniedException通常通过我的系统中的Spring安全性来实现。您还可以为不同的异常指定不同的行为

 @Bean public SimpleMappingExceptionResolver exceptionResolver() {
           SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
           resolver.setDefaultErrorView("general-error");
           resolver.setWarnLogCategory(TamponException.class.getName());
           return resolver;
}
我希望这会有帮助,祝你过得愉快

马蒂亚