【问题标题】:Spring-Security-Oauth2: Full authentication is required to access this resourceSpring-Security-Oauth2:访问此资源需要完全身份验证
【发布时间】:2015-01-08 23:16:57
【问题描述】:

我正在尝试将 spring-security-oauth2.0 与基于 Java 的配置一起使用。我的配置已经完成,但是当我在 tomcat 上部署应用程序并点击/oauth/token url 获取访问令牌时,Oauth 生成以下错误:

<oauth>
<error_description>Full authentication is required to access this resource</error_description>
<error>unauthorized</error>
</oauth>

我的配置在Git hub, please click on link

代码比较大,参考git。我正在使用 chrome postman 客户端发送请求。以下是我的要求。

POST /dummy-project-web/oauth/token HTTP/1.1
Host: localhost:8081
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=abc%40gmail.com&client_secret=12345678 

错误就像,Oauth 的 URL 是安全的,但在配置中,我授予访问此 URL 的所有权限。这个问题究竟是什么?

【问题讨论】:

  • 错误是spring框架错误。检查我的答案here

标签: java oauth-2.0 unauthorized spring-security-oauth2


【解决方案1】:

client_idclient_secret 默认情况下应该放在 Authorization 标头中,而不是 form-urlencoded 正文中。

  1. 用冒号连接client_idclient_secretabc@gmail.com:12345678
  2. Base 64 编码结果:YWJjQGdtYWlsLmNvbToxMjM0NTY3OA==
  3. 设置授权标头:Authorization: Basic YWJjQGdtYWlsLmNvbToxMjM0NTY3OA==

【讨论】:

  • 我认为,这是与grant_type=password 一起使用的client_credentials,没有必要这样做。如果我错了,请纠正我。
  • 当我尝试这个时,异常会抛出error="invalid_token", error_description="Invalid access token: abc@gmail.com"。我瘦了,为了访问这个资源,它需要身份验证令牌,但为什么?
  • 不,grant_type=password 是资源所有者的用户/通行证(即最终用户)将直接提供给客户端的位置。当您根本不验证资源所有者时使用 client_credentials;只是客户本身。这就是你的问题所表明的。如果您确实只想验证客户端而不是用户,请使用我在回答中指出的方案的 client_credentials。
  • 感谢@GaryF 提供的解决方案,但这仍然不起作用,仍然生成上述错误error="invalid_token", error_description="Invalid access token: abc@gmail.com" ,这是什么问题?
  • 我正在使用BcryptPasswordEncoder 如果我删除它,现在错误是更改The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers. 我认为这是生成,当响应错误时?
【解决方案2】:

原因是默认情况下/oauth/token 端点是通过Basic Access Authentication 保护的。

您需要做的就是将Authorization 标头添加到您的请求中。

您可以使用curl 之类的工具轻松地对其进行测试,方法是发出以下命令:

curl.exe --user abc@gmail.com:12345678 http://localhost:8081/dummy-project-web/oauth/token?grant_type=client_credentials

【讨论】:

  • 我尝试了你的答案,但随后我得到一个弹出窗口来插入用户名和密码。我尝试登录,但没有帮助
【解决方案3】:

使用 Spring OAuth 2.0.7-RELEASE,以下命令适用于我

curl -v -u abc@gmail.com:12345678 -d "grant_type=client_credentials" http://localhost:9999/uaa/oauth/token

它也适用于 Chrome POSTMAN,只需在“基本身份验证”选项卡中确保您的客户端和机密,将方法设置为“POST”并在“表单数据”选项卡中添加授权类型。

【讨论】:

    【解决方案4】:

    默认情况下,Spring OAuth 需要基本的 HTTP 身份验证。如果您想使用基于 Java 的配置将其关闭,您必须允许客户端的表单身份验证,如下所示:

    @Configuration
    @EnableAuthorizationServer
    protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
      @Override
      public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.allowFormAuthenticationForClients();
      }
    }
    

    【讨论】:

    【解决方案5】:

    您应该预先验证令牌 API "/oauth/token"

    扩展 ResourceServerConfigurerAdapter 并覆盖 configure function 以执行此操作。

    例如:

    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers("/oauth/token").permitAll().
    anyRequest().authenticated();
    

    【讨论】:

      【解决方案6】:

      我遇到了同样的问题,但我用以下课程解决了这个问题:

      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.security.authentication.AuthenticationManager;
      import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
      import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
      import org.springframework.security.crypto.password.NoOpPasswordEncoder;
      import org.springframework.security.crypto.password.PasswordEncoder;
      
      @Configuration
      @EnableWebSecurity
      public class OAuthSecurityConfiguration extends WebSecurityConfigurerAdapter {
      
          @Bean
          @Override
          public AuthenticationManager authenticationManager() throws Exception {
              return super.authenticationManager();
          }
      
          @Bean
          public PasswordEncoder passwordEncoder() {
              return NoOpPasswordEncoder.getInstance();
          }
      }
      

      【讨论】:

        【解决方案7】:

        这令人难以置信,但却是真实的。

        csrf 过滤器默认启用,它实际上会阻止任何 POST、PUT 或不包含 de csrf 令牌的 DELETE 请求。

        尝试使用 GET 而不是 POST 来确认就是这样。

        如果是这样,那么允许任何 HTTP 方法:

        @Throws(Exception::class)
        override fun configure(http: HttpSecurity) {
        
            /**
             * Allow POST, PUT or DELETE request
             *
             * NOTE: csrf filter is enabled by default and it actually blocks any POST, PUT or DELETE requests
             * which do not include de csrf token.
             */
            http.csrf().disable()
        
        }
        

        如果您获得 401,最直观的做法是认为在请求中您没有身份验证,或者您在标题中缺少有关授权的内容。

        但显然有一个内部函数正在过滤使用 POST 并返回 401 的 HTTP 方法。修复它后,我认为这是状态码的缓存问题,但显然不是。

        GL

        【讨论】:

          猜你喜欢
          • 2018-09-11
          • 2020-11-21
          • 2016-11-11
          • 2020-10-25
          • 2016-10-03
          • 2018-03-04
          • 2017-08-14
          • 2019-01-01
          • 2020-03-30
          相关资源
          最近更新 更多