I try to make a POST request to my springboot app hosted on heroku,
const email = 'x#x.com';
const password = 'x';
const data = JSON.stringify({
email,
password
});
fetch(
'https://culinareat-test.herokuapp.com/api/user/users/_login',
{
method: 'POST',
headers : {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
},
body : data,
}
).then(res => {
console.log(res);
})
I got this as the response:
This is the controller on my springboot app:
#RestController
#AllArgsConstructor
public class UserController {
private final UserService userService;
#RequestMapping(method = RequestMethod.POST, value = "/user/users/_login")
public LoginResponse logUserIn(#RequestBody LoginRequest loginRequest, HttpServletResponse response, HttpServletRequest request){
return userService.logUserIn(loginRequest, response, request);
}
//another endpoints
}
I tried to do this from another articles i just read on stackoverflow:
#Configuration
public class AppConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
}
Still, it does nothing and i still cannot do the request.
Any recommendation what should i do? Is there anything i should add on the server-side? Thanks in advance!
You need to add annotation #CrossOrigin in your controller
#RestController
#CrossOrigin(origins = "*", maxAge = 3600)
#AllArgsConstructor
public class UserController {
private final UserService userService;
#RequestMapping(method = RequestMethod.POST, value = "/user/users/_login")
public LoginResponse logUserIn(#RequestBody LoginRequest loginRequest, HttpServletResponse response, HttpServletRequest request){
return userService.logUserIn(loginRequest, response, request);
}
//another endpoints
}
Keep in mind that cross-origin issues are raised by Browsers. By default, if you are running javascript on origin http://localhost, you cannot specify CORS for localhost on the back-end.
Browsers such as Chrome do not allow javascript running on origin http://localhost to share resources in a cross-origin manner. See answer https://stackoverflow.com/a/10892392/15262845.
The solution is simple. Resolve a domain, e.g., example.com to 127.0.0.1 in hosts file. Then request example.com:8080 or example.com to load your front-end application and post the request from example.com origin.
Besides, you can always debug CORS by navigating to Network tab and copy, paste these two following headers.
access-control-allow-credentials: true
access-control-allow-origin: http://example.com/
Related
I am trying to send a request with an authorization header with Angular to a Spring backend.
export class TokenInterceptor implements HttpInterceptor{
constructor(public sharedService : SharedService){}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const jwtToken = this.sharedService.getJwtToken();
if(jwtToken){
req = this.addToken(req, jwtToken)
}
return next.handle(req)
}
addToken(req: HttpRequest<any>, jwtToken: any){
return req.clone({
headers: req.headers.append('Authorization', 'Bearer ' + jwtToken)
});
}
}
This is what my interceptor looks like. If I try to console.log() the authorization header before returning the next().handle , I can see the correct token inside the request. The problem is that the backend instead recieves a null Authorization header.
Inside by backend I have a doFilterInternal() method that filters any request and gets the Authentication header.
I don't think the problem is inside this filter because the request sent with Postman are handled correctly.
I have already enabled CORS on my backend
#Override
public void addCorsMappings(CorsRegistry corsRegistry){
corsRegistry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowedHeaders("*")
.exposedHeaders("Authorization")
.allowCredentials(true)
.maxAge(3600L);
}
I believe token is not set, because headers property is read-only.
Try to use setHeaders property of clone method argument:
addToken(req: HttpRequest<any>, jwtToken: any){
return req.clone({
setHeaders: { Authorization: 'Bearer ' + jwtToken }
});
}
After banging my head against the wall for several hours I found the solution.
When creating a class and implementing the WebMvcConfigurer (to enable CORS) this is right and it SHOULD work.
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry corsRegistry){
corsRegistry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowedHeaders("*")
.exposedHeaders("Authorization")
.allowCredentials(true)
.maxAge(3600L);
}
}
BUT this isn't enough, since I had to enable CORS also into the security config chain
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
http.cors().and().csrf().disable();
return http.build();
}
by tiping http.cors()
I am working on a project with FE as react and BE as Springboot. I am trying to add FE to the application. After registration, I have tried to login to the application. After successful login, we get JWT Token. For that we need to send username, password and grant type in body and Basic authentication details in header. The is
var postData = {
username: a,
password: b,
grant_type:'c'
};
let axiosConfig = {
headers: {
'Content-Type': 'application/json;charset=UTF-8',
"Access-Control-Allow-Origin": "*",
"Accept": "application/json" ,
"Authorization":"Basic" + " " +base64.encode("U" + ":" + "p")
}
};
axios.post('http://localhost:9003/login/token', postData,axiosConfig)
.then((res) => {
console.log("RESPONSE RECEIVED: ", res);
})
.catch((err) => {
console.log("AXIOS ERROR: ", err);
})
When I run this program, I got the error,
Access to XMLHttpRequest at 'http://localhost:9003/login/token' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
And My Spring boot Code is
#Override
#CrossOrigin(origins = "*", allowedHeaders = "*") public void
configure(HttpSecurity http) throws Exception {
http.cors().and().exceptionHandling() .authenticationEntryPoint( (request,
response, authException) ->
response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.and().authorizeRequests().antMatchers("/*").authenticated().and().httpBasic();
http.exceptionHandling().authenticationEntryPoint(new
CustomAuthenticationEntryPoint());
}
#Override
#CrossOrigin(origins = "*",allowedHeaders="*")
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.pathMapping("/oauth/token", "/login/token").tokenStore(tokenStore())
.tokenEnhancer(jwtAccessTokenConverter()).authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
Anybody know how to solve this?
As per MDN docs, the pre-flight response headers for a credentialed request should include a specific set of Access-Control-Allow-Origin and not a wild-card * .The cors config for the service can be setup by extending the WebSecurityConfigurerAdapter.
We faced a similar challenge with our spring-boot project and the following configuration helped overcome the cors failure
#EnableWebSecurity
public class DefaultAuthConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors(cors -> {
CorsConfigurationSource cs = resources -> {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOrigins(List.of("http://localhost:3000","http://localhost:3001"));
corsConfiguration.setAllowedMethods(List.of("POST", "GET", "PUT", "DELETE", "OPTIONS"));
corsConfiguration.setAllowedHeaders(List.of("Authorization",
"Content-Type",
"X-Requested-With",
"Accept",
"X-XSRF-TOKEN"));
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
};
cors.configurationSource(cs);
});
}
}
This class below to config CORS policy it worked for me.And i think your poblem is #CrossOrigin should be located in controller class.
#Configuration
public class AppConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
If you want more config follow this link https://spring.io/guides/gs/rest-service-cors/
updateStudent(userName: string, age: number): Observable<any> {
debugger;
let formData = new FormData();
let reqJson: any = {};
reqJson["userName"] = userName;
reqJson["age"] = age;
formData.append('info', JSON.stringify(reqJson));
return this.httpClient.post(this.url + '/update-student', formData);
}
... and I have this notation in my Java Spring Boot backend:
#CrossOrigin(origins = "*", maxAge = 3600)
#RestController
#RequestMapping("/api")
public class HomeController {
This is an error that I get:
Access to XMLHttpRequest at 'http://localhost:8080/api/update-student' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
You can use this code:
#Configuration
#EnableWebMvc
public class CourseConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "OPTIONS", "PUT", "DELETE")
.maxAge(3600);
}
}
I am working on the Spring Boot web application. I am running two different application one for service (Rest Resource) and other one is UI which show the request on HTML page on the bases of response got on the rest request.
My all rest services are created by
#Component
#Api(value = "/api/1/registration", description = "Access and manage your information")
#Path("/api/1/registration")
#Produces(MediaType.APPLICATION_JSON)
#Slf4j
public class RegistrationResource {
...
...
#ApiOperation(value = "Find user by id", notes = "Return a user by id", response = Registration.class)
#Path("/{id}")
#GET
#Timed
#Override
public Registration get(#PathParam("id") String id) {
// my logic
}
}
Restangular Request
Restangular.one("registration/1").get().then(function (data) {
...
},function(error) {
...
});
When I do restangular request from ui, its working fine. Now I need to have a servlet resource. For that I create new resource class
#Slf4j
#RestController
#RequestMapping("/api/1/test")
public class DownloadResource{
#RequestMapping(value = "/downloadtesting", method = RequestMethod.GET)
public void download(HttpServletResponse response, HttpServletRequest request){
// I need to call this method... How can I
}
}
FYI: All my resources are registered as following...
Reflections reflections = new Reflections("com.sample.resource");
Set<Class<? extends Object>> resources =
reflections.getTypesAnnotatedWith(Path.class); //
resources.forEach(r -> {
log.debug("Registering resource " + r);
register(beanFactory.getBean(r));
});
// Same I did for RequestMapping.class also but I am getting 404 error for downloadtesting api.
NOTE: If I try with following version for downloadtesting in RegistrationResource then I am getting HttpServletRequest / Response null.
public class RegistrationResource{
#Path("/downloadtesting")
public void download(HttpServletResponse response, HttpServletRequest request){
// I need to call this method... How can I
}
}
Can any one help me?
So I have a spring server in which I have implemented the following configuration:
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static String REALM="Authentication";
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("cris").password("123").roles("ADMIN");
auth.inMemoryAuthentication().withUser("felix").password("felix123").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
httpBasic().and()
.authorizeRequests()
.antMatchers("/user", "/vehicles", "/signin").permitAll()
.anyRequest().authenticated().and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}
I have the following interface
#RequestMapping("logs")
public interface LogController {
#RequestMapping(value = "", method = RequestMethod.GET)
ResponseEntity getLogs();
}
And it's implementation:
#CrossOrigin(origins = "*", exposedHeaders = {"x-auth-token", "x-requested-with"}, allowedHeaders="*", allowCredentials = "true")
#RestController( )
public class LogControllerImpl implements LogController {
#Autowired
LogService logService;
//Get all logs
public ResponseEntity getLogs() {
List<LogEntityDTO> allLogs = logService.getAllLogs();
if (allLogs == null)
return ResponseEntity.notFound().build();
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("authenticated", "you");
return ResponseEntity.ok(allLogs);
}
In angular2 I make a request as following:
sendAuthentification(credentials: string): Observable {
var headers = new Headers();
headers.append('Authorization', 'Basic ' + btoa('cris:123'));
headers.append('Content-Type', 'application/x-www-form-urlencoded');
headers.append('withCredentials', 'true');
return this.http.get(this.requestService.getPath() + "/logs", {headers});
}
The problem is that when I make the request from Angular2 the response has the following headers (pragma, content-type, cache control, expires ) :
But in reality the response headers from the server are the following:
The expected behaiviour would be the for the JSESSIONID and XSRF-TOKEN to be saved automatically in browser as cookies, but it does not do that.
And the problem is that with angular2 I can not access the Get-Cookie header to try to manually save the cookies.
NOTE: If I try to make the request from the browser directly (without the angular2 app) the browser stores automatically the JSESSIONID and XSRF-TOKEN as cookies.
So is this problem an angular2 problem or a spring server configuration problem? And how can get the JSESSIONID and XSRF-TOKEN from angular2?