[spring-projects/spring-boot]从 1.5.7 迁移到 Spring Boot 2 会破坏 OAuth2 安全性

2024-04-29 607 views
3

问题

由于 Spring 安全性和 OAuth2 中的一些更改,我很难将 Spring Boot 1.5.7 应用程序迁移到 Spring Boot 2。迁移指南中描述了一些步骤,但它们几乎没有描述所有更改以及如何解决这些更改以保持现有行为。

错误报告

以前,我在我的身份验证服务器上并行实现了基本身份验证和 OAuth2 - REST 端点使用 OAuth2 进行保护,而我的 Thymeleaf 页面则使用会话进行保护。这是使用以下配置完成的:

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  private static final String LOGIN = "/login";
  private static final String LOGOUT_SUCCESS = "/login?logout";

  private final UserDetailsService userDetailsService;
  private final AuthenticationManager authenticationManager;

  public WebSecurityConfig(UserDetailsService userDetailsService, @Lazy AuthenticationManager authenticationManager) {
    this.userDetailsService = userDetailsService;
    this.authenticationManager = authenticationManager;
  }

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

    http
      // enable cors
      .cors().and()
      .requestMatchers().antMatchers("/oauth/**", "/*").and()
      // These from the above are secured by the following way
      .authorizeRequests().antMatchers("/").permitAll()
      // These from the rest are secured by the following way
      .anyRequest().authenticated().and()
      // Set login page
      .formLogin().loginPage(LOGIN).permitAll().defaultSuccessUrl("/")
      // Set logout handling
      .and().logout().logoutSuccessUrl(LOGOUT_SUCCESS);
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.parentAuthenticationManager(authenticationManager);
    auth.userDetailsService(userDetailsService);
  }

}

我正在使用包并按照建议spring-security-oauth2切换到。spring-security-oauth2-autoconfigure然而,OAuth2 似乎完全被基本安全性覆盖,SecurityProperties.ACCESS_OVERRIDE_ORDER不再可用。所有 REST 端点都会返回 302 - 重定向到登录(包括/token端点),而不是没有有效令牌的 401。

有人可以向我指出如何成功迁移此安全配置吗?

回答

1

问题并不真正属于 GitHub 问题,但让我们先讨论一下这个问题,看看是否有必要更新迁移指南。

所有 REST 端点都会返回 302 - 重定向到登录(包括 /token 端点),而不是没有有效令牌的 401。

这意味着您要么有一个配置错误WebSecurityConfigurerAdapter,要么有多个配置错误,并且优先级较高的一个会覆盖您的 OAuth 安全配置。我不知道哪个,因为您还没有共享您在 Boot 2.0 中使用的代码。

如果您希望我们进一步调查,请分享一个最小、完整且可验证的问题示例。

4

谢谢回复。我只有作为这个问题的一部分发布的这个 WebSecurityAdapter。该适配器在 Spring Boot 1.5.7 中工作,唯一的变化(除了缺少 ACCESS_OVERRIDE_ORDER 之外)是迁移到 Spring Boot 2。

0

感谢您提供样品。不幸的是,它不会重现您所描述的行为。例如,我从令牌端点收到 401 响应:

curl -v localhost:8000/auth/oauth/token
*   Trying ::1...
* Connected to localhost (::1) port 8000 (#0)
> GET /auth/oauth/token HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 401
< Set-Cookie: JSESSIONID=BB55F9E770A2E66FC9F4F3B47ABA58E3; Path=/auth; HttpOnly
< WWW-Authenticate: Basic realm="oauth2/client"
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Mon, 05 Mar 2018 17:34:16 GMT
<
* Connection #0 to host localhost left intact
{"timestamp":"2018-03-05T17:34:16.021+0000","status":401,"error":"Unauthorized","message":"Unauthorized","path":"/auth/oauth/token"}

我只有作为这个问题的一部分发布的这个 WebSecurityAdapter。

这对于您的代码来说是正确的,但对于您的应用程序来说却不是这样。spring-security-oauth2-autoconfigure提供ResourceServerConfiguration的是 aWebSecurityConfigurerAdapter并且阶数为 3。您的WebSecurityConfig没有阶数,因此它使用 Spring Security 默认值 100。这意味着它的优先级低于ResourceServerConfigurationand,在请求匹配中存在重叠的情况下,ResourceServerConfiguration它将获胜。

2

我尝试发送令牌请求并收到 302 - 重定向到登录,而不是您描述的 401。当我回到我的电脑前时,我会向您发送 cUrl 请求。

9

我尝试了在另一台计算机上创建的示例项目,但仍然遇到我试图描述的问题。您似乎没有在请求中包含基本身份验证标头(clientId:secret 是 base64 编码的acme:secret)。

请参阅下面的 cUrl 命令示例:

curl -X POST http://localhost:8000/auth/oauth/token   -H 'authorization: Basic YWNtZTpzZWNyZXQ=' -H 'cache-control: no-cache' -H 'content-type: multipart/form-data' -H -F username=john@example.com -F password=password -F grant_type=password

这是输出:

<!DOCTYPE html>
<html lang="en">
    <body>
        <div id="container">
            <form class="form-signin" action="/auth/login" method="post">
                <input type="hidden" name="_csrf" value="c9d03931-77b9-4e7d-ac1b-79361cc31adb"/>
                <h2 class="form-signin-heading">Login</h2>
                <div class="form-group input-group">
                    <span class="input-group-addon">
                        <span class="glyphicon glyphicon-envelope"></span>
                    </span>
                    <input 
                    type="email"
                    id="username"
                    class="form-control"
                    placeholder="email"
                    name="username"
                    required="required" autofocus="autofocus" />
                </div>
                <div class="form-group input-group">
                    <span class="input-group-addon">
                        <span class="glyphicon glyphicon-lock"></span>
                    </span>
                    <input
                    type="password"
                    id="inputPassword"
                    class="form-control"
                    placeholder="password" 
                    name="password" required="required" />
                </div>
                <button class="btn btn-lg btn-primary btn-block" type="submit">login</button>
            </form>
        </div>
    </body>
</html>

预期行为是接收带有不匹配凭据的 401 或带有令牌的 200 作为响应。

9

谢谢。不确定我是否错过了上面的内容,但如果您在提供基本身份验证凭据时说您收到了 302,那么将会节省大量时间。

我现在可以重现您所描述的行为,这是因为您的客户端密钥没有使用 BCrypt 进行编码,而这正是 Spring Security 5 默认要求的。您可以在日志中看到这一点的指示:

2018-03-07 10:10:28.904  WARN 68489 --- [nio-8000-exec-4] o.s.s.c.bcrypt.BCryptPasswordEncoder     : Encoded password does not look like BCrypt

这可以通过更新来纠正V1_1__Test_Data.sql

diff --git a/src/main/resources/db/development/V1_1__Test_Data.sql b/src/main/resources/db/development/V1_1__Test_Data.sql
index f741085..6f219db 100644
--- a/src/main/resources/db/development/V1_1__Test_Data.sql
+++ b/src/main/resources/db/development/V1_1__Test_Data.sql
@@ -5,4 +5,4 @@ INSERT INTO users (user_id, username, password) VALUES
 INSERT INTO oauth_client_details (client_id, resource_ids, client_secret, scope,
 authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity,
 refresh_token_validity, additional_information, autoapprove) VALUES
-       ('acme', 'resource', 'secret', 'read,write', 'authorization_code,refresh_token,implicit,password,client_credentials', '', '', 3600, 2592000, '{}', 'true');
\ No newline at end of file
+       ('acme', 'resource', '$2a$10$s7rR9qxaUnOJaE3J6ZSICupQxm.xTJhvScmXV.ylsI3AIY5OMXp.q', 'read,write', 'authorization_code,refresh_token,implicit,password,client_credentials', '', '', 3600, 2592000, '{}', 'true');
\ No newline at end of file

此卷曲请求现在可以进行身份​​验证:

curl -X POST http://localhost:8000/auth/oauth/token   -H 'authorization: Basic YWNtZTpzZWNyZXQ=' -H 'cache-control: no-cache' -H 'content-type: multipart/form-data' -F username=john@example.com -F password=password -F grant_type=password

但是,尝试获取访问令牌时请求失败:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.authentication.AuthenticationManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.context.annotation.Lazy(value=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1509) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver$1.getTarget(ContextAnnotationAutowireCandidateResolver.java:90) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:193) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at com.sun.proxy.$Proxy96.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter.getOAuth2Authentication(ResourceOwnerPasswordTokenGranter.java:71) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
    at org.springframework.security.oauth2.provider.token.AbstractTokenGranter.getAccessToken(AbstractTokenGranter.java:70) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
    at org.springframework.security.oauth2.provider.token.AbstractTokenGranter.grant(AbstractTokenGranter.java:65) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
    at org.springframework.security.oauth2.provider.CompositeTokenGranter.grant(CompositeTokenGranter.java:38) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
    at org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer$4.grant(AuthorizationServerEndpointsConfigurer.java:561) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
    at org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(TokenEndpoint.java:132) ~[spring-security-oauth2-2.2.1.RELEASE.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:870) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:776) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:215) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.0.3.RELEASE.jar:5.0.3.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_151]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_151]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_151]

发生这种情况是因为您的应用程序中没有AuthenticationManagerbean。您可以通过迁移指南中描述的这一更改来公开:

diff --git a/src/main/java/com/smedzl/example/config/WebSecurityConfig.java b/src/main/java/com/smedzl/example/config/WebSecurityConfig.java
index f8f2af0..ccfc0ec 100644
--- a/src/main/java/com/smedzl/example/config/WebSecurityConfig.java
+++ b/src/main/java/com/smedzl/example/config/WebSecurityConfig.java
@@ -1,5 +1,6 @@
 package com.smedzl.example.config;

+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.http.HttpMethod;
@@ -55,4 +56,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                auth.userDetailsService(userDetailsService);
        }

+       @Bean
+       @Override
+       public AuthenticationManager authenticationManagerBean() throws Exception {
+               return super.authenticationManagerBean();
+       }
+
 }

然后您会遇到问题,因为密码编码不正确。这可以通过对 V1_1__Test_Data.sql 的另一个更新来纠正:

diff --git a/src/main/resources/db/development/V1_1__Test_Data.sql b/src/main/resources/db/development/V1_1__Test_Data.sql
index f741085..48a7a6c 100644
--- a/src/main/resources/db/development/V1_1__Test_Data.sql
+++ b/src/main/resources/db/development/V1_1__Test_Data.sql
@@ -1,8 +1,8 @@
 INSERT INTO users (user_id, username, password) VALUES
-       ('1', 'john@example.com', 'password'),
-       ('2', 'jane@example.com', 'password');
+       ('1', 'john@example.com', '$2a$10$1XqtAJZ9EXiuCCK2gy6gTuUEyYFsB97g5op1AXxRHQibf2mNe4x0i'),
+       ('2', 'jane@example.com', '$2a$10$1XqtAJZ9EXiuCCK2gy6gTuUEyYFsB97g5op1AXxRHQibf2mNe4x0i');

 INSERT INTO oauth_client_details (client_id, resource_ids, client_secret, scope,
 authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity,
 refresh_token_validity, additional_information, autoapprove) VALUES
-       ('acme', 'resource', 'secret', 'read,write', 'authorization_code,refresh_token,implicit,password,client_credentials', '', '', 3600, 2592000, '{}', 'true');
\ No newline at end of file
+       ('acme', 'resource', '$2a$10$s7rR9qxaUnOJaE3J6ZSICupQxm.xTJhvScmXV.ylsI3AIY5OMXp.q', 'read,write', 'authorization_code,refresh_token,implicit,password,client_credentials', '', '', 3600, 2592000, '{}', 'true');

完成这些更改后,将授予令牌:

$ curl -X POST http://localhost:8000/auth/oauth/token -H 'authorization: Basic YWNtZTpzZWNyZXQ=' -H 'cache-control: no-cache' -H 'content-type: multipart/form-data' -F username=john@example.com -F password=password -F grant_type=password
{"access_token":"8f6d7f22-db8e-4799-b45a-c856bc9c766e","token_type":"bearer","refresh_token":"d622e5fa-78c4-45f9-8396-2ab50b4cdff6","expires_in":3599,"scope":"read write"}
8

反应非常好。我不知道 Spring Security 5 中的这些变化。它仍然让我有点困惑为什么错误的 basic auth clientId:secret 凭证会导致 302 而不是 401,但除此之外,它工作正常。我现在可以继续迁移到 Spring Boot 2。

非常感谢!

8

它仍然让我有点困惑为什么错误的 basic auth clientId:secret 凭证会导致 302 而不是 401

IIRC,从我调试这个问题开始,请求就被转发到/error通过表单登录保护的地方,因此最终会出现 302 将您重定向到登录页面。

8

谢谢@Smedzlatko!你帮助解决了我的问题,这是一样的。

2

谁能评论一下 Spring 2.0 中删除 SecurityProperties.ACCESS_OVERRIDE_ORDER 有何影响?

9

@Datta4400 我们不想使用问题跟踪器来提问,请加入我们的 gitter.im 或在 stackoverflow.com 上提问。您可能还想查看迁移指南