我们正在使用Spring MVC + Spring Security + Hibernate创建一个RESTful
API。该API可以生成JSON和HTML。做好弹簧安全性的错误处理让我头疼:
身份验证可以通过多种方式进行:BasicAuth,通过POST请求中的不同参数以及通过Web登录。对于每种身份验证机制,<http>
在Spring
Security xml配置的名称空间元素中声明了一个过滤器。
我们在一个custom中处理所有spring异常HandlerExceptionResolver
。这对于在我们的控制器中抛出的所有异常都可以正常工作,但是我不知道如何处理在定制的Spring安全过滤器中抛出的定制的异常。由于spring安全过滤器是在调用任何控制器之前出现的,因此我们看不到在自定义spring安全过滤器中引发的异常。
我在stackoverflow上找到了这个问题:在SpringSecurity中使用自定义异常。但是我不明白他们在哪里处理抛出在那里的异常。我们尝试了这种方法,但是HandlerExceptionResolver
没有调用我们的习惯。取而代之的是,给用户显示了由tomcat渲染的难看的stacktrace。
我们为什么需要这个? 可以激活和停用用户。如果停用了它们并尝试执行某些操作,我们将返回JSON并带有自定义错误消息。这应该与spring
security抛出时显示的内容不同AccessDeniedException
。AccessDeniedException
不知何故进入了我们的行列HandlerExceptionResolver
,但我无法完全理解。
可能的解决方案
我们考虑过使用ExceptionTranslationFilter
,但是在抛出自定义异常时不会调用此方法(在doFilter()方法的catch语句中设置断点)。在我的理解中,应调用该catch块,并应使用身份验证入口点。
另一种可能性:我们可以执行与ExceptionTranslationFilter
spring安全过滤器链中类似的操作,并执行与其AccessDeniedHandler
功能相似的操作:
RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage);
dispatcher.forward(request, response);
我们可以在请求中添加一些参数(错误代码,原因等),并将其指向控制器,该控制器将负责JSON或HTML的呈现。
这是我们的配置的简短摘录:
春季安全:
<http create-session="stateless" use-expressions="true" >
<!-- Try getting the authorization object from the request parameters. -->
<security:custom-filter ref="filter1" after="SECURITY_CONTEXT_FILTER"/>
<security:custom-filter ref="filter2" before="LOGOUT_FILTER"/>
<!-- Intercept certain URLS differently -->
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
<!-- Some more stuff here -->
<intercept-url pattern="/**" access="denyAll" />
<http-basic />
</http>
HandlerExceptionResolver的AppConfig
@Bean
public HandlerExceptionResolver handlerExceptionResolver(){
logger.info("creating handler exception resolver");
return new AllExceptionHandler();
}
我们的自定义HandlerExceptionResolver
public class AllExceptionHandler implements HandlerExceptionResolver {
private static final Logger logger = LoggerFactory
.getLogger(AppConfig.class);
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
// This is just a snipped of the real method code
return new ModelAndView("errorPage");
}
我们的过滤器之一的相关部分:
try {
Authentication authResult = authenticationManger.authenticate(authRequest);
SecurityContextHolder.getContext().setAuthentication(authResult);
}
catch(AuthenticationException failed) {
SecurityContextHolder.clearContext();
throw failed;
}
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>xxx.xxx.xxx.config</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>LIVE</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<!-- Add multipart support for files up to 10 MB -->
<multipart-config>
<max-file-size>10000000</max-file-size>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<!-- Map filters -->
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<error-page>
<error-code>404</error-code>
<location>/handle/404</location>
</error-page>
</web-app>
有谁对我们如何解决这个问题有任何指示?我浏览了Google上的许多文章,其中大多数描述了在没有过滤器能够验证请求的情况下如何处理SpringSecurity抛出的AccessDeniedException。
我们正在使用Spring Security 3.1.0和spring web mvc 3.1.0。
重要的是要记住,Spring Security中过滤器的顺序很重要。
从Spring Security 3书中:
的
ExceptionTranslationFilter
将是能够处理和反应,只有那些抛出它下面的过滤器链执行堆栈异常。用户常常会感到困惑,尤其是在以错误的顺序添加自定义过滤器时,为什么预期的行为会与应用程序的实际异常处理有所不同-
在许多情况下,应该归咎于过滤器的顺序!
如果您的过滤器是关于授权的,则最好将它们放在链的末端,因为默认授权过滤器使用此方法。这样,您就不必重新发明轮子了。
标准过滤器:文档中的表
正确配置过滤器链后,您可以配置错误页面,甚至自定义处理程序。文档中提供了更多信息。
我使用的是Nifi 0.4.1版本。我写自定义代码转换CSV到avro格式。我已经创建了类文件,并能够生成nar文件。将nar文件放置在lib目录中,并重新启动nifi服务器。 任何帮助都很感激.. 谢谢,
我的要求是,如果post请求的JSON无效,我将需要发送400个HTTP响应代码,如果任何字段不可解析,返回状态代码将为422。例如,post请求可以是: Dto类提供如下:, 这是发出POST请求的控制器, 如果“金额”是,比如说,“sfdfd”,这不是大小数,我们应该提供422。但如果“金额”为“-12.3343”,则这是约束验证错误,但数据有效且可分析。所以我们不能拥有422。 这是我的异常
我来找你是因为我需要你的帮助。 在我的文件camel-context.xml中,我调用了一个存储过程来获取用户的信息。我需要解决的是: 如果存储过程不返回数据,则发送带有超文本传输协议代码404的UserNot的异常(我已经拥有该类)。 我一直在寻找如何做这件事,但找不到任何可以帮助我的东西。我刚刚开始使用这个框架,所以提前非常感谢您的帮助。 这里我的代码:
我使用netbeans创建了这个异常类: 当我尝试编译时,问题变得更加突出,在setter方法中,我得到以下消息: 错误:未报告异常异常;必须捕获或声明被抛出抛出新车辆异常(2,matricula);C:\users\ivan\desktop\examen isidrer\m03-uf5\exmaenm03uf5\src\info\infomila\vehicle.java:55:错误:未报告的异
我正在使用来自外部API的一些RESTendpoint,为此我正在使用REST模板接口。当我从这些调用中收到某些HTTP状态代码时,我希望能够抛出自定义应用程序异常。为了实现它,我正在实现ResponseErrorHandler接口,如下所示: 最后,这是客户端代码(无关代码省略): 我的应用程序上下文: 我怀疑我没有正确理解此自定义错误处理的行为。每个rest模板方法都可能抛出一个RestCli
我正在用Spring Boot开发一个rest应用程序。此应用程序有一个自定义筛选器,只允许在某些请求下访问。如果用户需要特定的资源,筛选器将抛出异常。如何在全局级别处理此筛选器中生成的所有异常? 我尝试了注释,但不起作用。