使用OAuth2(更新的#2)时,Spring-boot应用程序不进行身份验证

问题描述 投票:1回答:2

我正在尝试创建OAuth2客户端来访问第三方OAuth2服务器。我已将此行添加到我的application.properties文件中:

spring.security.oauth2.client.registration.mercadolivre=mercadolivre
spring.security.oauth2.client.registration.mercadolivre.client-id=...
spring.security.oauth2.client.registration.mercadolivre.client-secret=...
spring.security.oauth2.client.registration.mercadolivre.client-authentication-method=basic
spring.security.oauth2.client.registration.mercadolivre.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.mercadolivre.redirect-uri=http://localhost:8080
spring.security.oauth2.client.provider.mercadolivre.authorization-uri=https://auth.mercadolivre.com.br/authorization
spring.security.oauth2.client.provider.mercadolivre.token-uri=https://auth.mercadolivre.com.br/oauth

我有这个Spring安全配置:

@Configuration
@EnableWebSecurity
@EnableOAuth2Sso
public class Security extends WebSecurityConfigurerAdapter {
  @Override
  public void configure(HttpSecurity http) throws Exception {
      http
        .csrf().disable()
        .authorizeRequests()
          .antMatchers("/css/**", "/images/**", "/js/**", "/**").permitAll()
          .anyRequest().authenticated()
        .and()
          .oauth2Login()
        .and()
        .logout()
          .logoutUrl("/logout");
  }
...
}

以及此html用于我的开放安全区域:

  <body>
    <ul>
      <!--<li class="navbar-brand">
        <img th:src="@{/img/logo.png}" class="sticky" width="120px" height="120px" alt="logo">
      </li> -->

      <li>
        Loja
      </li>

      <li class="right" sec:authorize="isAnonymous()">
        <a class="button" th:href="@{/oauth2/authorization/mercadolivre}">Entrar</button>
      </li>

      <li sec:authorize="isAuthenticated()">
        Logged in as: <span sec:authentication="name">Bob</span>
      </li>

      <li class="right" sec:authorize="isAuthenticated()">
        <a class="button" th:href="@{/logout}">Sair</button>
      </li>
    </ul>
  </body>

但是,当我在浏览器中打开应用程序并尝试登录时,我将被正确转发到授权页面,但是当我重定向回我的应用程序时,我没有经过身份验证。

任何人都可以看到这里有什么问题吗?

UPDATE

将我的spring-security配置更改为此后

@Configuration
@EnableWebSecurity
@EnableOAuth2Sso
public class Security extends WebSecurityConfigurerAdapter {
  @Override
  public void configure(HttpSecurity http) throws Exception {
      http
        .csrf().disable()
        .authorizeRequests()
          .antMatchers("/css/**", "/images/**", "/js/**", "/**").permitAll()
          .anyRequest().authenticated()
        .and()
        .formLogin()
          .loginPage("/login")
          .loginProcessingUrl("/doLogin").permitAll()
        .and()
        .oauth2Login()
          .loginPage("/login")
          .loginProcessingUrl("/login/oauth")
        .and()
        .logout()
          .logoutUrl("/logout");
  }
...
}

application.properties redirect_uri到此:

spring.security.oauth2.client.registration.mercadolivre.redirect-uri=http://localhost:8080/login/oauth

现在尝试登录时出现此错误:

java.lang.NullPointerException: null
        at org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient.getTokenResponse(DefaultAuthorizationCodeTokenResponseClient.java:84) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient.getTokenResponse(DefaultAuthorizationCodeTokenResponseClient.java:52) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider.authenticate(OAuth2LoginAuthenticationProvider.java:103) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:175) ~[spring-security-core-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:185) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:160) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.30.jar!/:9.0.30]
        at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]

(重定向URL看起来不错,包括附加的必要代码:http://localhost:8080/login/oauth?code=...&state=...

更新2

我当前的设置在下面。这样,我将被转发到服务授权页面,但是当我返回到我的项目时,我没有通过身份验证(获取访问令牌的授权代码会成功附加到URL上)。

App.java

@EnableOAuth2Client
@EnableOAuth2Sso
@SpringBootApplication
@RestController
public class App extends WebSecurityConfigurerAdapter {

    @GetMapping("/user")
    public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
            return Collections.singletonMap("name", principal.getAttribute("name"));
    }

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests(a -> a
                            .antMatchers("/", "/error", "/webjars/**", "/css/**", "/js/**", "/img/**").permitAll()
                            .anyRequest().authenticated()
                    )
                    .exceptionHandling(e -> e
                            .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
                    )
                    .csrf(c -> c
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            )
                    .logout(l -> l
                        .logoutSuccessUrl("/").permitAll()
                    )
                    .oauth2Login();
    }

}

application.properties

security.basic.enabled=false

spring.security.oauth2.client.registration.mercadolivre.client-id=...
spring.security.oauth2.client.registration.mercadolivre.client-secret=...

spring.security.oauth2.client.registration.mercadolivre.client-authentication-method=basic
spring.security.oauth2.client.registration.mercadolivre.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.mercadolivre.scope=read
spring.security.oauth2.client.registration.mercadolivre.redirect-uri=http://localhost:8080

spring.security.oauth2.client.provider.mercadolivre.authorization-uri=https://auth.mercadolibre.com/authorization
spring.security.oauth2.client.provider.mercadolivre.token-uri=https://api.mercadolivre.com.br/oauth/token
spring.security.oauth2.client.provider.mercadolivre.user-info-uri=https://api.mercadolibre.com/users/me
spring.security.oauth2.client.provider.mercadolivre.user-info-authentication-method=form

spring.security.oauth2.client.clientId=...
spring.security.oauth2.client.clientSecret=...
spring.security.oauth2.client.accessTokenUri=https://api.mercadolivre.com.br/oauth/token
spring.security.oauth2.client.userAuthorizationUri=https://auth.mercadolibre.com/authorization
spring.security.oauth2.client.clientAuthenticationScheme=form

spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false

index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title></title>
    <link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}"/>
</head>
<body>
  <nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
    <a class="navbar-brand" href="#">
      <img th:src="@{/img/bootstrap-solid.svg}" width="30" height="30" class="d-inline-block align-top" alt="kleber app store">
      Kleber App Store
    </a>

    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav mr-auto">
      </ul>
      <ul class="navbar-nav">
        <li class="nav-item" sec:authorize="isAnonymous()">
          <a class="nav-link" href="/oauth2/authorization/mercadolivre">
            Fazer login com Mercado Livre
          </a>
        </li>
        <li class="nav-item" sec:authorize="isAuthenticated()">
          <a class="nav-link" href="#">
            Logged in as: <span sec:authentication="name">Bob</span>
          </a>
        </li>
        <li class="nav-item" sec:authorize="isAuthenticated()">
          <a class="btn btn-primary" th:href="@{/logout}">
            Logout
          </a>
        </li>
      </ul>
    </div>
  </nav>

  <script type="text/javascript" th:src="@{/webjars/jquery/jquery.min.js}"></script>
  <script type="text/javascript" th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
  <script type="text/javascript" th:src="@{/webjars/js-cookie/js.cookie.js}"></script>
  <script type="text/javascript" th:src="@{/js/script.js}"></script>
</body>
</html>
spring spring-boot oauth oauth-2.0 spring-oauth2
2个回答
0
投票

我认为OAuth2客户端的重定向Uri应该设置为:

spring.security.oauth2.client.registration.mercadolivre.redirect-uri=http://localhost:8080/login/oauth2/mercadolivre

并且该相同的URI应该作为重定向URL输入到您的第三方OAuth2授权服务器中,因为授权服务器应该在该位置发送用于Spring安全性的授权代码以最终获取令牌。

Pero


0
投票

看起来您来自第三方的令牌终结点正在返回空响应。验证正确的请求已发送到令牌端点,或者可能是错误的端点。

来自docs令牌端点应为https://api.mercadolibre.com/oauth/token

spring.security.oauth2.client.provider.mercadolivre.token-uri=https://api.mercadolibre.com/oauth/token

您可以运行curl命令以验证令牌响应

类似

curl -X POST https://api.mercadolibre.com/oauth/token?grant_type=authorization_code&client_id=$APP_ID&client_secret=$SECRET_KEY&code=$SERVER_GENERATED_AUTHORIZATION_CODE&redirect_uri=$REDIRECT_URI
© www.soinside.com 2019 - 2024. All rights reserved.