使用 global-method-security,拒绝访问错误作为 HTTP 500 错误返回 [英] Using global-method-security, Access Denied errors are returned as HTTP 500 errors

查看:22
本文介绍了使用 global-method-security,拒绝访问错误作为 HTTP 500 错误返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Spring Security Annotations 来确保安全性,而不是在 XML 中定义规则.它似乎有效,但是当我遇到访问被拒绝错误时,我得到了 500 的 HTTP 状态代码.我在我的 tomcat 日志文件中没有看到任何异常.当执行到达我的 AuthenticationEntryPoint 时,响应被提交.

I'm trying to use Spring Security Annotations for security instead of defining the rules in XML. It seems to work, but when I run into an access denied error I get a HTTP status code of 500 returned. I do not see any exceptions in my tomcat log files. And when the execution hits my AuthenticationEntryPoint, the response is committed.

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

If I revert to having the rules in XML and get an access denied error, I get a HTTP status code of 401 returned.

该方法用@PreAuthorize 注释

The method is annotated with @PreAuthorize

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

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

Here is my XML (the previous XML rule is commented out)

<?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>

推荐答案

此问题与 Spring Security 无关.问题出在泽西岛.

This issue is unrelated to Spring Security. The problem was with Jersey.

Jersey 拦截了 AccessDeniedException 并将其作为 ServletException 重新抛出.

Jersey was intercepting the AccessDeniedException and rethrowing it as a ServletException.

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

What I had to do was write an ExceptionMapper. More information 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

On startup Jersey scans for @Provider's using the jersey.config.server.provider.packages property. From my 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>

这篇关于使用 global-method-security,拒绝访问错误作为 HTTP 500 错误返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆