在 Spring OAuth2 中配置安全性:身份验证请求的访问被拒绝

Posted

技术标签:

【中文标题】在 Spring OAuth2 中配置安全性:身份验证请求的访问被拒绝【英文标题】:Configure security in Spring OAuth2: Access is denied for authentication request 【发布时间】:2020-10-17 01:19:06 【问题描述】:

我想用 OAuth2 实现 Spring Security。我试过这个安全配置:

@Override
protected void configure(HttpSecurity http) throws Exception 
        http.authorizeRequests()
            .antMatchers("/users/authorize").permitAll()
            .antMatchers("/users/reset_request").permitAll()
            .antMatchers("/users/reset_token").permitAll()
            .antMatchers("/users/reset_password").permitAll()
            .antMatchers("/users/confirmation_token").permitAll()
            .antMatchers("/users/reset_user_password").permitAll()
            .anyRequest().authenticated()
            .and().formLogin().permitAll()
            .and().csrf().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

完整代码:Github

但我总是得到:


    "error": "unauthorized",
    "error_description": "Full authentication is required to access this resource"

我向身份验证端点发出 POST 请求:

localhost:8080/engine/users/authorize

回复:

    01:57:19.237 [http-nio-8080-exec-5] DEBUG ExceptionTranslationFilter[sendStartAuthentication:211] - Calling Authentication entry point.
01:57:19.239 [http-nio-8080-exec-5] DEBUG HstsHeaderWriter[writeHeaders:169] - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@69e77584
01:57:19.251 [http-nio-8080-exec-5] DEBUG DefaultOAuth2ExceptionRenderer[writeWithMessageConverters:101] - Written [error="unauthorized", error_description="Full authentication is required to access this resource"] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@4fe0c045]
01:57:19.252 [http-nio-8080-exec-5] DEBUG SecurityContextPersistenceFilter[doFilter:119] - SecurityContextHolder now cleared, as request processing completed
09:07:01.012 [PRODUCTION_HIKARICP_CONNECTION_POOL housekeeper] WARN  HikariPool[run:787] - PRODUCTION_HIKARICP_CONNECTION_POOL - Thread starvation or clock leap detected (housekeeper delta=6h6m24s237ms51╡s500ns).
09:07:02.931 [WAREHOUSE_HIKARICP_CONNECTION_POOL housekeeper] WARN  HikariPool[run:787] - WAREHOUSE_HIKARICP_CONNECTION_POOL - Thread starvation or clock leap detected (housekeeper delta=6h6m24s237ms408╡s400ns).
11:16:17.556 [http-nio-8080-exec-7] DEBUG OrRequestMatcher[matches:65] - Trying to match using Ant [pattern='/oauth/token']
11:16:27.735 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/oauth/token'
11:16:27.754 [http-nio-8080-exec-7] DEBUG OrRequestMatcher[matches:65] - Trying to match using Ant [pattern='/oauth/token_key']
11:16:27.754 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/oauth/token_key'
11:16:27.754 [http-nio-8080-exec-7] DEBUG OrRequestMatcher[matches:65] - Trying to match using Ant [pattern='/oauth/check_token']
11:16:27.754 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/oauth/check_token'
11:16:27.754 [http-nio-8080-exec-7] DEBUG OrRequestMatcher[matches:72] - No matches found
11:16:27.756 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
11:16:27.757 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
11:16:27.758 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
11:16:27.770 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
11:16:27.771 [http-nio-8080-exec-7] DEBUG OrRequestMatcher[matches:65] - Trying to match using Ant [pattern='/logout', GET]
11:16:27.773 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:157] - Request 'POST /users/authorize' doesn't match 'GET /logout'
11:16:27.773 [http-nio-8080-exec-7] DEBUG OrRequestMatcher[matches:65] - Trying to match using Ant [pattern='/logout', POST]
11:16:27.773 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/logout'
11:16:27.773 [http-nio-8080-exec-7] DEBUG OrRequestMatcher[matches:65] - Trying to match using Ant [pattern='/logout', PUT]
11:16:27.774 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:157] - Request 'POST /users/authorize' doesn't match 'PUT /logout'
11:16:27.774 [http-nio-8080-exec-7] DEBUG OrRequestMatcher[matches:65] - Trying to match using Ant [pattern='/logout', DELETE]
11:16:27.774 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:157] - Request 'POST /users/authorize' doesn't match 'DELETE /logout'
11:16:27.774 [http-nio-8080-exec-7] DEBUG OrRequestMatcher[matches:72] - No matches found
11:16:27.774 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
11:16:27.775 [http-nio-8080-exec-7] DEBUG BearerTokenExtractor[extractToken:54] - Token not found in headers. Trying request parameters.
11:16:27.782 [http-nio-8080-exec-7] DEBUG BearerTokenExtractor[extractToken:57] - Token not found in request parameters.  Not an OAuth2 request.
11:16:27.783 [http-nio-8080-exec-7] DEBUG OAuth2AuthenticationProcessingFilter[doFilter:141] - No token in request, will continue chain.
11:16:27.783 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
11:16:27.783 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
11:16:27.784 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
11:16:27.787 [http-nio-8080-exec-7] DEBUG AnonymousAuthenticationFilter[doFilter:100] - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@461b50c6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
11:16:27.788 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
11:16:27.789 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
11:16:27.789 [http-nio-8080-exec-7] DEBUG FilterChainProxy[doFilter:328] - /users/authorize at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
11:16:27.791 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/*'
11:16:27.799 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/v1/swagger.**'
11:16:27.800 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:157] - Request 'POST /users/authorize' doesn't match 'GET /v2/api-docs'
11:16:27.800 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:157] - Request 'POST /users/authorize' doesn't match 'GET /swagger-resources/**'
11:16:27.800 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:157] - Request 'POST /users/authorize' doesn't match 'GET /swagger-ui.html**'
11:16:27.801 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:157] - Request 'POST /users/authorize' doesn't match 'GET /webjars/**'
11:16:27.802 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:157] - Request 'POST /users/authorize' doesn't match 'GET favicon.ico'
11:16:27.802 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/v1/application.wadl'
11:16:27.803 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/v1/admin/**'
11:16:27.803 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/v1/dev/**'
11:16:27.803 [http-nio-8080-exec-7] DEBUG AntPathRequestMatcher[matches:177] - Checking match of request : '/users/authorize'; against '/v1/pages/**'
11:16:27.805 [http-nio-8080-exec-7] DEBUG FilterSecurityInterceptor[beforeInvocation:219] - Secure object: FilterInvocation: URL: /users/authorize; Attributes: [#oauth2.throwOnError(authenticated)]
11:16:27.805 [http-nio-8080-exec-7] DEBUG FilterSecurityInterceptor[authenticateIfRequired:348] - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@461b50c6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
11:16:27.835 [http-nio-8080-exec-7] DEBUG AffirmativeBased[decide:66] - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@2938ceb8, returned: -1
11:16:27.842 [http-nio-8080-exec-7] DEBUG ExceptionTranslationFilter[handleSpringSecurityException:180] - 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)
        at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:123)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)

由于某种原因,未应用此安全配置。你知道我该如何解决这个问题吗?

【问题讨论】:

您可能应该显示您的依赖项和 application.yml,因为这会影响 Spring Boot 应用程序中自动配置的内容。您问题中的更多信息会有所帮助 这里是:github.com/rcbandit111/oauth2_jwt/blob/master/src/main/… 该项目托管在 Guhub 上。您应该可以浏览它。 【参考方案1】:

您可能错过了端点中的/engine。如下


使用 configure(HttpSecurity http)

antMatchers 中添加 /engine

改变

.antMatchers("/users/authorize").permitAll()

.antMatchers("/engine/users/authorize").permitAll()

配置(HttpSecurity http)

@Override
protected void configure(HttpSecurity http) throws Exception 
        http.authorizeRequests()
            .antMatchers("/engine/users/authorize").permitAll()
            .antMatchers("/engine/users/reset_request").permitAll()
            .antMatchers("/engine/users/reset_token").permitAll()
            .antMatchers("/engine/users/reset_password").permitAll()
            .antMatchers("/engine/users/confirmation_token").permitAll()
            .antMatchers("/engine/users/reset_user_password").permitAll()
            .anyRequest().authenticated()
            .and().formLogin().permitAll()
            .and().csrf().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);


使用 configure(WebSecurity web) 方法,您可以完全避免使用 configure(WebSecurity web) 方法的 spring 安全过滤器。

@Override
public void configure(WebSecurity web) throws Exception 
    web.
        ignoring()
            .antMatchers("/engine/users/authorize")
            .antMatchers("/engine/users/reset_request")
            .antMatchers("/engine/users/reset_token")
            .antMatchers("/engine/users/reset_password")
            .antMatchers("/engine/users/confirmation_token")
            .antMatchers("/engine/users/reset_user_password");

注意:如果您同时使用 configure(WebSecurity web)configure(HttpSecurity http),则将 configure(WebSecurity web) 保持在 configure(HttpSecurity HTTP) 上方,如 here 所述 p>

@Override
public void configure(WebSecurity web) throws Exception 
    ...


@Override
protected void configure(HttpSecurity http) throws Exception 
     ...

【讨论】:

@PeterPenzov,你试过configure(WebSecurity web)吗? 是的,这就是问题所在。谢谢! 还有一个问题:你知道我如何实现刷新令牌吗? 是的,您可以在成功的身份验证后创建两个令牌(访问令牌、刷新令牌),这些令牌将添加到 cookie 中并在每个请求时发送。访问令牌的有效性低于刷新令牌。如果访问令牌已过期且刷新令牌仍然有效,您可以为同一请求分配一个新令牌。 您可能还想探索 jhipster,它可以创建即用型项目,我们可以根据需要对其进行配置。 jhipster.tech

以上是关于在 Spring OAuth2 中配置安全性:身份验证请求的访问被拒绝的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot 2.0.3 + 安全 + Oauth2 自动配置

一个应用程序中的 Spring Security OAuth2 身份验证和表单登录

Spring Oauth2:在 SecurityContext 中找不到身份验证对象

使用令牌的 Spring OAuth2 身份验证

使用oauth2向授权URL添加附加参数的Spring安全性?

Spring OAuth2 安全 - 客户端凭据 - 自定义 AuthenticationProvider