spring-security - invalid - spring boot cors allow all origins
Servidor de autorizaciĆ³n independiente de Spring OAuth2 JWT+CORS (5)
¡Encontré la razón de mi problema!
¡Solo necesitaba terminar la cadena de filtros y devolver el resultado inmediatamente si CorsFilter procesa una solicitud de OPCIONES!
SimpleCorsFilter.java
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCorsFilter implements Filter {
public SimpleCorsFilter() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
Después de eso, podría ignorar la solicitud de verificación previa de OPTIONS en mi AuthServer = D
Por lo tanto, el servidor funciona como en el recorte anterior y puede ignorar el comentario de bloque con la clase MyWebSecurity al principio.
Así que tengo el siguiente Servidor de Autorización condensado de este ejemplo de Dave Syer
@SpringBootApplication
public class AuthserverApplication {
public static void main(String[] args) {
SpringApplication.run(AuthserverApplication.class, args);
}
/* added later
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
protected static class MyWebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http //.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
}
}*/
@Configuration
@EnableAuthorizationServer
protected static class OAuth2AuthorizationConfig extends
AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyPair keyPair = new KeyStoreKeyFactory(
new ClassPathResource("keystore.jks"), "foobar".toCharArray())
.getKeyPair("test");
converter.setKeyPair(keyPair);
return converter;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("acme")
//.secret("acmesecret")
.authorizedGrantTypes(//"authorization_code", "refresh_token",
"password").scopes("openid");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.authenticationManager(authenticationManager).accessTokenConverter(
jwtAccessTokenConverter());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
throws Exception {
oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess(
"isAuthenticated()");
}
}
}
cuando lo ejecuto y lo pruebo con curl
curl acme@localhost:8110/oauth/token -d grant_type=password -d client_id=acme -d username=user -d password=password
Recibo un JWT como respuesta, pero tan pronto como intento acceder al AuthServer desde mi Frontend (Angular JS en un puerto diferente) recibo un error CORS. No porque faltan encabezados, sino porque la solicitud de OPCIÓN es rechazada y faltan las credenciales.
Request URL:http://localhost:8110/oauth/token
Request Method:OPTIONS
Status Code:401 Unauthorized
WWW-Authenticate:Bearer realm="oauth", error="unauthorized", error_description="Full authentication is required to access this resource"
Ya sabía que tenía que agregar un CorsFilter y además encontré
esta publicación
donde utilicé el fragmento para la primera Respuesta para permitir que las OPCIONES soliciten acceso
/oauth/token
sin credenciales:
@Order(-1)
public class MyWebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
}
}
Después de eso obtuve con curl el siguiente error:
{"timestamp":1433370068120,"status":403,"error":"Forbidden","message":"Expected CSRF token not found. Has your session expired?","path":"/oauth/token"}
Entonces, para simplificar, acabo de agregar
http.csrf().disable()
al método de
configure
de la clase MyWebSecurity, que resuelve el problema con la solicitud OPTION, pero por lo tanto la solicitud POST ya no funciona y obtengo
There is no client authentication. Try adding an appropriate authentication filter.
There is no client authentication. Try adding an appropriate authentication filter.
(también con rizo).
Traté de averiguar si tengo que conectar de alguna manera la clase MyWebSecurity y el AuthServer, pero sin suerte. El ejemplo original (enlace al principio) también inyecta el Administrador de autenticación, pero esto no cambió nada para mí.
Encontré un problema similar usando siguiente
-
Backend
Spring Boot 1.5.8.RELEASE
-
Spring OAuth2
Spring OAuth 2.2.0.RELEASE
w -
Vuejs
usando la biblioteca de solicitudesaxios
ajax
¡Con el
postman
todo funciona!
Cuando comencé a hacer una solicitud desde la aplicación
Vuejs
, recibí los siguientes errores
OPCIONES http://localhost:8080/springboot/oauth/token 401 ()
y
XMLHttpRequest no puede cargar http://localhost:8080/springboot/oauth/token . La respuesta para la verificación previa tiene un código de estado HTTP no válido 401
Después de leer un poco, descubrí que puedo ordenar a mi
Spring OAuth
que ignore la solicitud de
OPTIONS
anulando la
configure
en mi clase de implementación
WebSecurityConfigurerAdapter
siguiente manera
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS);
}
La adición de lo anterior ayudó pero luego, me encontré con el error específico de
CORS
OPCIONES http://localhost:8080/springboot/oauth/token 403 ()
y
XMLHttpRequest no puede cargar http://localhost:8080/springboot/oauth/token . La respuesta a la solicitud de verificación previa no pasa la verificación de control de acceso: no hay encabezado ''Access-Control-Allow-Origin'' en el recurso solicitado. Por lo tanto, el origen '' http: // localhost: 8000 '' no tiene acceso permitido. La respuesta tenía el código de estado HTTP 403.
Y resolvió el problema anterior con la ayuda de un
CorsConfig
como se muestra a continuación
@Configuration
public class CorsConfig {
@Bean
public FilterRegistrationBean corsFilterRegistrationBean() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.applyPermitDefaultValues();
config.setAllowCredentials(true);
config.setAllowedOrigins(Arrays.asList("*"));
config.setAllowedHeaders(Arrays.asList("*"));
config.setAllowedMethods(Arrays.asList("*"));
config.setExposedHeaders(Arrays.asList("content-length"));
config.setMaxAge(3600L);
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}
Después de agregar la clase anterior, funciona como se esperaba.
Antes de comenzar, investigaré las
consequences
de usar
web.ignoring().antMatchers(HttpMethod.OPTIONS);
así como las
best practices
para la configuración de
Cors
anterior.
Por ahora
*
hace el trabajo pero definitivamente no es seguro para la producción.
La respuesta de Cyril me ayudó
partially
y luego me encontré con la idea de
CorsConfig
en este número de
Github
.
Encontré una solución usando la solución para la pregunta. Pero tengo otra forma de describir la solución:
@Configuration
public class WebSecurityGlobalConfig extends WebSecurityConfigurerAdapter {
....
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS);
}
...
}
Usando Spring Boot 2 aquí.
Tenía que hacer esto en mi
AuthorizationServerConfigurerAdapter
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
Map<String, CorsConfiguration> corsConfigMap = new HashMap<>();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
//TODO: Make configurable
config.setAllowedOrigins(Collections.singletonList("*"));
config.setAllowedMethods(Collections.singletonList("*"));
config.setAllowedHeaders(Collections.singletonList("*"));
corsConfigMap.put("/oauth/token", config);
endpoints.getFrameworkEndpointHandlerMapping()
.setCorsConfigurations(corsConfigMap);
//additional settings...
}
bueno, tienes razon! esa es una solución, y también funcionó para mí (tuve el mismo problema)
Pero permítanme suscribir el uso de una implementación más inteligente del filtro CORS para Java: http://software.dzhuvinov.com/cors-filter.html
Esta es una solución muy completa para aplicaciones Java.
En realidad, puedes ver here cómo se resuelve tu punto.