【问题标题】:Spring Boot + Spring Security + Spring Rest Issue: 'Access Denied' errorSpring Boot + Spring Security + Spring Rest 问题:“拒绝访问”错误
【发布时间】:2020-04-10 21:24:42
【问题描述】:

我从 Spring 初始化程序创建了一个 Spring Boot 应用程序,根本不包含任何依赖项。 然后我将此应用程序导入 STS-4.4.2。我创建了一个休息控制器并添加了一个 POST 方法。我的控制器类如下:

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/app-api/tests")
public class AppApiController {

    @PostMapping(consumes = "application/json", produces = "application/json")
    @ResponseStatus(HttpStatus.CREATED)
    public String returnTestString(@RequestBody String testString) {
        return "bla bla bla";
    }

}

使用Postman,执行POST方法,在响应中成功打印出字符串消息'bla bla bla'。

现在我添加了 Spring Security 库,并且没有对应用程序进行任何进一步的修改。

从 Postman 重新测试现在不会返回任何内容。我将日志级别提高到“调试”并获得以下信息:

 Access is denied (user is anonymous); redirecting to authentication entry point

org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) ~[spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103) [spring-web-5.1.12.RELEASE.jar:5.1.12.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103) [spring-web-5.1.12.RELEASE.jar:5.1.12.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:206) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103) [spring-web-5.1.12.RELEASE.jar:5.1.12.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103) [spring-web-5.1.12.RELEASE.jar:5.1.12.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103) [spring-web-5.1.12.RELEASE.jar:5.1.12.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) [spring-web-5.1.12.RELEASE.jar:5.1.12.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) [spring-web-5.1.12.RELEASE.jar:5.1.12.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:461) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:384) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:394) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:253) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:175) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1591) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_141]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_141]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_141]
  • 在 Postman 上,我尝试将授权信息添加为基本授权,使用控制台上打印的“用户”用户名和密码:

    使用生成的安全密码:6fc537b1-a9ad-439b-8d96-a75f8b49f6d2

结果相同。

有什么提示可以解决这个问题吗?提前致谢。

问候,

【问题讨论】:

    标签: spring rest spring-boot spring-security


    【解决方案1】:

    当您添加入门安全库时,将为应用程序启用身份验证。

    每个应用程序的密码更改都会重新启动,并且可以在控制台日志中找到。以下是格式:

    Using default security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35
    

    在 application.properties 文件中设置以下属性

    spring.security.user.name = root
    spring.security.user.password = the default password in console log
    

    要在默认设置之前添加您自己的应用程序安全层,

    @EnableWebSecurity
    public class SecurityConfig {
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth
                .inMemoryAuthentication()
                    .withUser("user").password("password").roles("USER");
        }
    }
    

    现在您可以使用新凭据:

    spring.security.user.name = user
    spring.security.user.password = password
    

    【讨论】:

      【解决方案2】:

      春季安全

      Spring Security 的一个常见问题是在执行 POST 时获得 HTTP 403 Forbidden。

      这在 Spring Security FAQ here 中被引用,说:

      我在执行 POST 时收到 403 Forbidden

      如果 HTTP 403 被禁止 为 HTTP POST 返回,但适用于 HTTP GET 那么问题是 最有可能与 CSRF 有关。提供 CSRF 令牌或禁用 CSRF 保护(不推荐)。

      这是因为默认情况下启用了 CSRF。 另请参阅CSRF in Spring Security。
      servlet 配置的默认设置是写入名为 XSRF-TOKEN 的 cookie,并从名为 X-XSRF-TOKEN 的标头或 HTTP 参数 _csrf 读取它(参见课程HttpSessionCsrfTokenRepository)。

      春季启动

      当在类路径中找到 Spring Security 时,Spring Boot 会自动配置安全性。 见Security in Spring Boot。

      看看它是如何在 Spring Boot 中自动配置的:SecurityAutoConfiguration

      【讨论】:

        猜你喜欢
        • 2015-11-13
        • 2015-07-12
        • 2023-03-16
        • 2017-01-10
        • 2015-08-07
        • 2020-12-19
        • 2014-09-25
        • 1970-01-01
        • 2019-05-17
        相关资源
        最近更新 更多