使用global-method-security,Access Denied错误将作为HTTP 500错误返回

时间:2014-02-07 19:50:35

标签: java spring security methods annotations

我正在尝试将Spring Security Annotations用于安全性,而不是在XML中定义规则。它似乎工作,但当我遇到访问被拒绝错误时,我得到一个返回的HTTP状态代码500。我的tomcat日志文件中没有看到任何异常。当执行命中我的AuthenticationEntryPoint时,响应将被提交。

如果我恢复使用XML中的规则并获得拒绝访问错误,我会返回401状态代码。

该方法使用@PreAuthorize

进行注释
@GET
@Produces(MediaType.APPLICATION_JSON)
@PreAuthorize("hasRole('user')")
public String list() throws IOException 

这是我的XML(之前的XML规则已被注释掉)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <security:debug/>

    <security:global-method-security pre-post-annotations="enabled"/>

    <security:authentication-manager id="authenticationManager">
        <security:authentication-provider user-service-ref="userDao">
            <security:password-encoder ref="passwordEncoder"/>
        </security:authentication-provider>
    </security:authentication-manager>

    <security:http
            realm="Protected API"
            use-expressions="true"
            auto-config="false"
            create-session="stateless"
            entry-point-ref="unauthorizedEntryPoint"
            authentication-manager-ref="authenticationManager">
        <security:access-denied-handler ref="accessDeniedHandler"/>
        <security:custom-filter ref="tokenAuthenticationProcessingFilter" position="FORM_LOGIN_FILTER"/>
        <security:custom-filter ref="tokenFilter" position="REMEMBER_ME_FILTER"/>
        <!--<security:intercept-url method="GET" pattern="/rest/news/**" access="hasRole('user')"/>-->
    </security:http>

</beans>

1 个答案:

答案 0 :(得分:10)

此问题与Spring Security无关。问题在于泽西岛。

Jersey正在拦截AccessDeniedException并将其重新抛出为ServletException。

我要做的就是编写一个ExceptionMapper。更多信息https://jersey.java.net/documentation/latest/representations.html#d0e4866

@Provider
/**
 * AccessDeniedMapper is instantiated by Jersey directly through the "jersey.config.server.provider.packages" setting
 */
public class AccessDeniedMapper implements ExceptionMapper<AccessDeniedException> {
    @Override
    public Response toResponse(AccessDeniedException e) {
        return Response.status(401)
                .build();
    }
}

在启动时,Jersey使用jersey.config.server.provider.packages属性扫描@ Provider。来自我的web.xml

<!-- Map the REST Servlet to /rest/ -->
<servlet>
    <servlet-name>RestService</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <!--Every class inside of this package (com.unsubcentral.rest) will be available to Jersey-->
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.rince.rest</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>RestService</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>