Angular向Spring Boot传递Bearer Token时遇CORS错误求助
CORS问题求助:/getUser接口调用失败,/oauth/token正常
我已经尝试了所有相关CORS配置,但调用/parking/getUser接口时仍出现CORS错误,/oauth/token接口可以正常工作,恳请帮忙解决。
后端Spring Boot相关配置
OAuth配置类
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; @Configuration public class OAuthConfiguration extends AuthorizationServerConfigurerAdapter { @Value("${spring.oauth.clientId}") private String clientId; @Value("${spring.oauth.clientSecret}") private String clientSecret; @Value("${spring.oauth.accessTokenValidity}") private int accessTokenValidity; @Value("${spring.oauth.refreshTokenValidity}") private int refreshTokenValidity; private final BCryptPasswordEncoder passwordEncoder; private final AuthenticationManager authenticationManager; private final UserDetailsService userDetailsService; @Autowired public OAuthConfiguration(BCryptPasswordEncoder passwordEncoder, AuthenticationManager authenticationManager, UserDetailsService userDetailsService) { this.passwordEncoder = passwordEncoder; this.authenticationManager = authenticationManager; this.userDetailsService = userDetailsService; } @Override public void configure(final AuthorizationServerSecurityConfigurer security) throws Exception { security.allowFormAuthenticationForClients(); security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.applyPermitDefaultValues(); // add allow-origin to the headers config.addAllowedHeader("access-control-allow-origin"); source.registerCorsConfiguration("/oauth/token", config); CorsFilter filter = new CorsFilter(source); security.addTokenEndpointAuthenticationFilter(filter); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient(clientId).secret(passwordEncoder.encode(clientSecret)) .authorizedGrantTypes("password", "authorization_code", "refresh_token") .scopes("read","write") .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT", "USER","ADMIN") .autoApprove(true) .accessTokenValiditySeconds(accessTokenValidity) .refreshTokenValiditySeconds(refreshTokenValidity); } @Override public void configure(final AuthorizationServerEndpointsConfigurer endpoints) { endpoints .accessTokenConverter(accessTokenConverter()) .userDetailsService(userDetailsService) .authenticationManager(authenticationManager); } @Bean JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); return converter; } }
Security配置类
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import java.util.Arrays; //@Order(Ordered.HIGHEST_PRECEDENCE) @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter{ private final UserDetailsService userDetailsService; @Autowired public SecurityConfig(@Qualifier("userService")UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } @Override protected void configure(HttpSecurity http) throws Exception { /*** * Note down to uncomment */ // http.csrf().disable().cors().and() // .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // //.and() // //.cors() // .and().authorizeRequests().antMatchers("/oauth/token") // .permitAll() // .antMatchers("/parking/**").permitAll() // .antMatchers(HttpMethod.OPTIONS).permitAll() // .anyRequest().authenticated(); // http // .csrf().disable() // .anonymous().disable() // .authorizeRequests() // .antMatchers("/api-docs/**").permitAll(); http.csrf().disable().cors().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests().antMatchers("/parking/**").permitAll() .antMatchers("/oauth/token").permitAll().antMatchers(HttpMethod.OPTIONS).permitAll() .anyRequest().authenticated(); } // private Customizer<CorsConfigurer<HttpSecurity>> corsConfigurationCustomizer(){ // return new Customizer<CorsConfigurer<HttpSecurity>>() { // @Override // public void customize(CorsConfigurer<HttpSecurity> httpSecurityCorsConfigurer) { // httpSecurityCorsConfigurer.configurationSource(corsConfigurationSource()); // } // }; // } // @Override // public void configure(WebSecurity web) throws Exception { // web.ignoring().antMatchers("/**"); // } @Bean public DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setPasswordEncoder( bCryptPasswordEncoder() ); provider.setUserDetailsService(userDetailsService); return provider; } @Bean public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("http://127.0.0.1:4200")); configuration.addAllowedHeader("*"); configuration.addAllowedMethod("*"); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } //@Bean //public CorsFilter corsFilter(){ // CorsConfiguration corsConfiguration = new CorsConfiguration(); // corsConfiguration.setAllowCredentials(false); // corsConfiguration.setAllowedOrigins(Arrays.asList("*")); // corsConfiguration.setAllowedHeaders(Arrays.asList("Origin","Access-Control-Allow-Origin","Content-Type", // "Accept", "Authorization", "Origin, Accept", "X-Requested-With", // "Access-Control-Request-Method", "Access-Control-Request-Headers")); // corsConfiguration.setExposedHeaders(Arrays.asList("Origin", "Content-Type", "Accept","Authorization", // "Access-Control-Allow-Origin", "Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")); // corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST","PUT","DELETE","OPTIONS")); // UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); // urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); // return new CorsFilter(urlBasedCorsConfigurationSource); //} // @Bean // public FilterRegistrationBean<CORSFilter> filterRegistrationBean(){ // FilterRegistrationBean<CORSFilter> registrationBean = new FilterRegistrationBean<>(new CORSFilter()); // registrationBean.setName("CORS FIlter"); // registrationBean.addUrlPatterns("/*"); // registrationBean.setOrder(1); // return registrationBean; // } }
尝试过的WebMvc配置(已注释)
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; //@EnableWebSecurity //@Configuration //public class WebConfiguration implements WebMvcConfigurer { // // @Override // public void addCorsMappings(CorsRegistry registry) { // registry.addMapping("/**").allowedOrigins("http://127.0.0.1:4200").allowedMethods("*") // .allowCredentials(true); // } //}
尝试过的自定义CORS Filter(已注释部分代码)
import org.springframework.core.annotation.Order; import org.springframework.web.filter.GenericFilterBean; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; //public class CORSFilter extends GenericFilterBean implements Filter { // @Override // public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) // throws IOException, ServletException { // // HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse; // httpServletResponse.setHeader("Access-Control-Allow-Origin", "*"); // httpServletResponse.setHeader("Access-Control-Allow-Methods", "*"); // httpServletResponse.setHeader("Access-Control-Allow-Headers", "*"); // httpServletResponse.setHeader("Access-Control-Allow-Credentials", "*"); // httpServletResponse.setHeader("Access-Control-Max-Age", "3600"); // filterChain.doFilter(servletRequest, servletResponse); // } // } @Order(1) public class CORSFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException { res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); res.setHeader("Access-Control-Max-Age", "3600"); res.setHeader("Access-Control-Allow-Headers", "X-PINGOTHER,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization"); res.addHeader("Access-Control-Expose-Headers", "xsrf-token"); if ("OPTIONS".equals(req.getMethod())) { res.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } }
前端Angular代码
export class LoginService { userDto: UserDto = new UserDto(); private baseUrl = 'http://127.0.0.1:8080/parking'; constructor(private http: HttpClient) { } login(login:login,token:string):Observable<Object>{ console.log('Bearer '+token); const httpOptions = { headers: new HttpHeaders().set('Content-Type','application/json') .set('Authorization',"Bearer "+token).set('Access-Control-Allow-Origin','*').set('Access-Control-Allow-Methods','GET, POST, PATCH, PUT, DELETE,OPTIONS') .set('Access-Control-Allow-Headers','Origin, Content-Type, X-Auth-Token') .set('Access-Control-Allow-Credentials','true') }; this.userDto.setBatchNo(login.getBatchNo()); this.userDto.setPassword(login.getPassword()); return this.http.post(`${this.baseUrl}/getUser`,this.userDto,httpOptions); } }
错误情况
/oauth/token接口可正常调用,获取Token无问题- 调用
/parking/getUser接口传递Token时,浏览器控制台出现CORS错误
错误截图:

内容的提问来源于stack exchange,提问作者Tanmay Naik
相关产品推荐
相关产品推荐

