我正在尝试使用 Spring Security Annotations 来确保安全,而不是在 XML 中定义规则。它似乎有效,但是当我遇到访问被拒绝错误时,我返回了 500 的 HTTP 状态代码。我在我的 tomcat 日志文件中没有看到任何异常。当执行到达我的 AuthenticationEntryPoint 时,响应被提交。
如果我恢复使用 XML 中的规则并收到拒绝访问错误,我将返回 401 的 HTTP 状态代码。
方法用@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>
最佳答案
此问题与 Spring Security 无关。问题出在 Jersey 。
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。来 self 的 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>
关于java - 使用全局方法安全,拒绝访问错误作为 HTTP 500 错误返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21636566/