Spring 启动 Oauth2 + Angular CORS 问题

Spring boot Oauth2 + Angular CORS problem

我是制作授权服务的新手。当我尝试从 Postman 获取访问令牌时,一切正常。但是当我使用 Angular 时,我得到了这个错误:

Access to XMLHttpRequest at 'localhost:8082/oauth/token' from origin 'http://localhost:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

我的配置是:

@SpringBootApplication
@EnableEurekaClient
@EnableWebSecurity
public class AuthMsApplication extends WebSecurityConfigurerAdapter {

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

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@WebFilter("/*")
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        final HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Allow-Headers", "content-type, x-requested-with, authorization");
        response.setHeader("Access-Control-Max-Age", "3600");
        if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }
}

    @EnableAuthorizationServer
    @Configuration
    public class OAuth2Config extends AuthorizationServerConfigurerAdapter {

        private static final String READ = "read";
        private static final String WRITE = "write";
        private static final String PASSWORD = "password";
        private static final String REFRESH_TOKEN = "refresh_token";

        @Value("${client.id}")
        private String clientId;
        @Value("${client.secret}")
        private String clientSecret;
        @Value("${tokenSignature}")
        private String tokenSignature;
        @Value("${accessTokenValiditySeconds}")
        private int accessTokenValiditySeconds;
        @Value("${refreshTokenValiditySeconds}")
        private int refreshTokenValiditySeconds;

        private final AuthenticationManager authenticationManager;
        private final UserDetailsService customDetailsService;

        public OAuth2Config(@Qualifier("authenticationProviderImpl") AuthenticationManager authenticationManager,
                            UserDetailsService customDetailsService) {
            this.authenticationManager = authenticationManager;
            this.customDetailsService = customDetailsService;
        }

        @Bean
        public JwtAccessTokenConverter tokenEnhancer() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setSigningKey(tokenSignature);
            return converter;
        }

        @Bean
        public JwtTokenStore tokenStore() {
            return new JwtTokenStore(tokenEnhancer());
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
            endpoints.authenticationManager(authenticationManager)
                    .tokenStore(tokenStore())
                    .accessTokenConverter(tokenEnhancer())
                    .userDetailsService(customDetailsService);
        }

        @Bean
        public PasswordEncoder encoder() {
            return new BCryptPasswordEncoder();
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) {
            security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");

        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            String encodedClientSecret = encoder().encode(clientSecret);
            clients.inMemory()
                    .withClient(clientId)
                    .secret(encodedClientSecret)
                    .scopes(READ, WRITE)
                    .authorizedGrantTypes(PASSWORD, REFRESH_TOKEN)
                    .accessTokenValiditySeconds(accessTokenValiditySeconds)
                    .refreshTokenValiditySeconds(refreshTokenValiditySeconds);
        }
    }

任何不作为全局 CORS 工作的搜索信息。一件事正在发挥作用,它是

@CrossOrigin(origins = "*", allowedHeaders = "*")

但是我可以把它放在我自己的控制器上,我不知道如何为 oauth/token 端点设置它。

这个官方文档解决方案不起作用。 https://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html

过滤器也不起作用。

这是一个普遍存在的问题, 由于来源不同,它保护了不同来源的注入。

解决方案:

1) 如果您使用的是 dev,则在 chrome 上启用 CORS(扩展)(POSTMAN 默认执行此操作)

2) 在生产中,托管它的 angular 应用程序应该将您列入白名单 API URL,

3)第三组cors允许原点headers

3 天后我找到了解决方案。首先,我删除了我的身份验证服务中的所有过滤器。其次,我在我的网关服务中添加了这个道具:

cloud:
gateway:
  globalcors:
    corsConfigurations:
      '[/**]':
        allowedOrigins: "*"
        allowedHeaders:
          - content-type
          - x-requested-with
          - Authorization
        allowedMethods:
          - GET
          - POST
          - OPTIONS
          - DELETE
          - PUT

您只需要在网关属性中为所有服务添加全局headers,这也可以与服务中的过滤器结合使用以进行更灵活的设置。 我希望这可以帮助一些人节省 3 天)