Crossorigin doesn't work - spring

React keep me saying Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/users. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
The strange think it worked to me and it stopped working without any change to the controller code...
UserController.java
#RestController
#CrossOrigin
#RequestMapping(value = "/users")
public class UserController {
#Autowired
private UserService userService;
#RequestMapping(value = "/{userId}", method = RequestMethod.GET)
private User findOne(#PathVariable("userId") Integer userId) {
return userService.findOne(userId);
}
#RequestMapping(method = RequestMethod.GET)
private List<User> findAll() {
return userService.findAll();
}
#RequestMapping(method = RequestMethod.POST)
private User create(#RequestBody User user) {
user.setId(null); // To ensure we create instead of update
return userService.save(user);
}
#RequestMapping(value = "/{userId}", method = RequestMethod.PUT)
private User update(#PathVariable("userId") Integer userId, #RequestBody User user) {
user.setId(userId); // To ensure we update instead of create
return userService.save(user);
}
#RequestMapping(value = "/{userId}", method = RequestMethod.DELETE)
private void delete(#PathVariable("userId") Integer userId) {
final User user = userService.findOne(userId);
userService.delete(user);
}
}
and this is my fetch on React
fetch('http://localhost:8080/users', {
method: 'GET',
headers: {
'content-type': 'application/json'
},
}).then(response => { return response.json();
}).then(data => {
this.setState({users:data});
});
}
Any reason why it stopped working suddenly?
edit:
I tried making a clean new maven project and copied all packages into the new project and now it works, but I still don't know why it stopped work, the code is the same and now its working.

If you are using Spring Security and want CORS globally in your project then try to add it to the configuration:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors()
.and()
........ other config
}
But before that try the following approaches. To apply CORS on class level use it like this:
#CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
#Controller
public class SomeController{
}
or use it in method level like this:
#CrossOrigin("http://example.com")
#RequestMapping("/some")
public Account retrieve() {
// ...
}
OR
#CrossOrigin(origins = "*")
#RequestMapping("/some")
public Account retrieve() {
// ...
}

Related

Vaadin + Spring Boot returns 403 Forbidden error on PUT, POST, DELETE requests

Implementing a simple web application using REST Api using Spring Boot + Vaadin. Also, Security is connected in the project, a simple login with a login-password is carried out. Get() requests work fine, but a 403 "Forbidden" error occurs on PUT, POST, DELETE requests.
I tried disabling csrf using the http.httpBasic().and().csrf().disable() method, it does not help, and this is not recommended in production either.
I also tried adding to antMatchers() specifically a request type like this: http.httpBasic().and().authorizeRequests().antMatchers(HttpMethod.POST,"/**").permitAll(), also not helps.
Configuration class:
#EnableWebSecurity
#Configuration
public class SecurityConfig extends VaadinWebSecurity {
private static class SimpleInMemoryUserDetailsManager extends InMemoryUserDetailsManager {
public SimpleInMemoryUserDetailsManager() {
createUser(Manager.withUsername("manager1")
.password("{noop}123")
.roles(ROLE_MANAGER)
.build());
createUser(Manager.withUsername("manager2")
.password("{noop}123")
.roles(ROLE_MANAGER)
.build());
}
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests().antMatchers("/enterprises/\*\*").hasRole(ROLE_MANAGER);
super.configure(http);
setLoginView(http, LoginView.class);
}
#Bean
public InMemoryUserDetailsManager enterprisesService() {
return new SimpleInMemoryUserDetailsManager();
}
}
Rest-controller:
#org.springframework.web.bind.annotation.RestController
#RequestMapping(path = "/")
public class RestController {
#Autowired
private VehiclesRepository vehiclesRepository;
#Autowired
private EnterprisesRepository enterprisesRepository;
#Autowired
private DriversRepository driversRepository;
#Autowired
private ManagersRepository managersRepository;
#GetMapping(
path = "/vehicles",
produces = "application/json")
public VehiclesDto getVehicles() {
VehiclesDto vehiclesDto = new VehiclesDto();
for (Vehicle vehicle : vehiclesRepository.findAll()) {
vehiclesDto.getVehicles().add(vehicle);
}
return vehiclesDto;
}
#GetMapping(
path = "/enterprises",
produces = "application/json")
public #ResponseBody EnterprisesDto getEnterprises(#RequestParam("managerId") String managerId) {
Manager manager = null;
for (Manager managerFromRepo : managersRepository.findAll()) {
if (managerFromRepo.getId().equals(Long.parseLong(managerId))) {
manager = managerFromRepo;
break;
}
}
EnterprisesDto enterprisesDto = new EnterprisesDto();
if (manager == null) return enterprisesDto;
for (Enterprise enterprise : enterprisesRepository.findAll()) {
if (manager.getEnterprises().contains(enterprise.getId()))
enterprisesDto.getEnterprises().add(enterprise);
}
return enterprisesDto;
}
#GetMapping(
path = "/drivers",
produces = "application/json")
public DriversDto getDrivers() {
DriversDto driversDto = new DriversDto();
for (Driver driver : driversRepository.findAll()) {
driversDto.getDrivers().add(driver);
}
return driversDto;
}
#PostMapping("/createVehicle")
public #ResponseBody String createVehicle(#RequestBody String info) {
return "it works!!!";
}
#DeleteMapping("/deleteVehicle")
public #ResponseBody String deleteVehicle(){
return "it works!!!";
}
}
Testing requests through Postman using Basic Authentication.
You can disable CSRF just for your API:
http.csrf().ignoringRequestMatchers(new AntPathRequestMatcher("/enterprises/**"));

Spring RequestMapping DELETE and unauthorized access JWT

I have a problem with DELETE method in spring. I'm using JWT and sending it in request header but GET/POST/PATCH works, DELETE don't..I don't really know why. Even via postman I'm not authorized 401 to delete item but I can get/patch/post a new one... Here is my code of controllers:
#CrossOrigin(origins = "http://localhost:8081", maxAge = 3600)
#RestController
public class JwtAuthenticationController {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Autowired
private JwtUserDetailsService userDetailsService;
#Autowired
private CarDetailsService carDetailsService;
#RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(#RequestBody JwtRequest authenticationRequest) throws Exception {
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
}
#RequestMapping(value = "/register", method = RequestMethod.POST)
public ResponseEntity<?> saveUser(#RequestBody UserDTO user) throws Exception {
return ResponseEntity.ok(userDetailsService.save(user));
}
private void authenticate(String username, String password) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new Exception("INVALID_CREDENTIALS", e);
}
}
#RequestMapping(value = "/car", method = RequestMethod.POST)
public ResponseEntity<?> getRents(#RequestBody CarDTO car) throws Exception {
return ResponseEntity.ok(carDetailsService.saveCar(car));
}
#RequestMapping(value ="/cars", method = RequestMethod.GET)
public ResponseEntity<?> getCars() throws Exception{
return ResponseEntity.ok(carDetailsService.getAllCars());
}
#PatchMapping("/cars/{id}")
public ResponseEntity<?> partialUpdate(#RequestBody PartialCarDTO partialCar, #PathVariable("id") Integer id){
return ResponseEntity.ok(carDetailsService.updateCar(partialCar,id));
}
#RequestMapping(value = "/cars/{id}", method = RequestMethod.DELETE)
public ResponseEntity<?> deleteCar(#RequestBody PartialCarDTO partialCar, #PathVariable("id") Integer id){
return ResponseEntity.ok(carDetailsService.deleteCar(partialCar,id));
}
A good answer here: https://stackoverflow.com/a/299696/4573580
If a DELETE request includes an entity body, the body is ignored [...]
I deleted PartialCarDTO from requestmapping and via postman it is possible to delete entity, but in my rest api it's not .. :/ I tried a lot of variations but without success. Even if i pass NULL instead of payload in axios while keeping headers like authorization with my token, content type and access control allow origin. No I really don't know where is the problem. Always 401. Do You have any ideas?
return new Promise((resolve, reject) => {
let id=payload.id;
let url="http://localhost:8080/cars/"+id
let config = {
headers: {
"Authorization": "Bearer "+localStorage.getItem('token'),
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
}
axios.delete(url, payload, config)
.then(({data,status}) => {
if(status === 200){
resolve(true);
}
})
.catch(error=> {
reject(error);
})
}

Spring Boot, testing controller with secret token, how to?

In my microservice I have Spring boot controller which is receive also auth token from http request header and send it to another microservice for validation:
#Autowired
private AuthService authService;
#GetMapping(path = "/find", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
#ResponseBody
#Timed
#CrossOrigin
public ResponseEntity<?> find(
#RequestParam(name = "contactId", required = true) final Long contactId,
#RequestHeader(name = "secret-token", required = true) String token
) {
boolean checkTokenValidationFromAuthServer = authService.checkTokenValidationFromAuthServer(token);
if (!checkTokenValidationFromAuthServer) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("token is invalid");
}
return ResponseEntity.status(HttpStatus.OK).body("Your contact here!");
}
Auth Service must be like this
#Service
#Component
public class AuthService {
public boolean checkTokenValidationFromAuthServer(String token){
//make rest call to auth microservice
//validate token, return false, or true
return false;
}
}
Basic test always will fail because I from test I do not know secret token, I want to mock or prevent controller from validation:
#RunWith(SpringRunner.class)
#SpringBootTest
public class PoolApplicationTests {
#Autowired
private PoolController controller;
#Test
public void controllerInitializedCorrectly() {
assertThat(controller).isNotNull();
}
#Test
public void testCall() {
ResponseEntity<?> find = controller.find(1L, "token");
assertThat(find.getStatusCode()).isEqualTo(200);
}
}
I do not know what is the best strategy for this kind of cases.

Spring Social Facebook Template always return same user

I am using Spring Social 2.0.2.RELEASE to provide social login with Facebook. My problem is that Spring Social always return the same first user when I use FacebookTemplate. Here the example:
```
#Autowired
private Facebook facebook;
#RequestMapping(value = "/facebook/login", method = RequestMethod.GET)
public ModelAndView handleFacebookLogin(HttpServletResponse response) {
//always the same user
User profile = facebook.fetchObject("me", User.class, "id", "name", "link", "email");
return new ModelAndView("redirect:/dashboard");
}
```
I also have a Custom ConnectController:
```
#Controller
#RequestMapping("/connect")
public class CustomConnectController extends ConnectController {
#Autowired
public CustomConnectController(ConnectionFactoryLocator connectionFactoryLocator,
ConnectionRepository connectionRepository) {
super(connectionFactoryLocator, connectionRepository);
}
#Override
protected RedirectView connectionStatusRedirect(String providerId, NativeWebRequest request) {
return new RedirectView("/facebook/login");
}
}
```
If a open two browsers and try to login with different users, it always return the first one. My current solution is just copy the entire ConnectController to my app and change the behaviour. It is terrible and I hope that I am making a big mistake.
I had the same issue and solved the problem by creating this class:
#Configuration
public class UniqueSessionUserID extends SocialConfigurerAdapter {
#Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
#Override
public String getUserId() {
RequestAttributes request = RequestContextHolder.getRequestAttributes();
String uuid = (String) request.getAttribute("_socialUserUUID", RequestAttributes.SCOPE_SESSION);
if (uuid == null) {
uuid = UUID.randomUUID().toString();
}
request.setAttribute("_socialUserUUID", uuid, RequestAttributes.SCOPE_SESSION);
return uuid;
}
};
}
}
Here is a link where it is explained in more detail why this is necessary:
Spring Social Facebook more than one user

Rest template giving null body and status 302

I am trying to consume a rest call in my mvc controller, however every time I do it returns a null body with http status as 302.Also I am using spring boot with spring security to get https.
I've followed code samples from here: http://websystique.com/springmvc/spring-mvc-4-restful-web-services-crud-example-resttemplate/
and Get list of JSON objects with Spring RestTemplate however none of these work
Can someone please point me in the right direction
Thank you,
REST
#RequestMapping(value = "/api/*")
#RestController
public class PostApiController {
static final Logger logger = LogManager.getLogger(PostApiController.class.getName());
private final PostService postService;
#Inject
public PostApiController(final PostService postService) {
this.postService = postService;
}
//-------------------Retrieve All Posts--------------------------------------------------------
#RequestMapping(value = "post", method = RequestMethod.GET)
public ResponseEntity<List<Post>> getAllPosts() {
List<Post> posts = postService.findAllPosts();
if(posts.isEmpty()){
return new ResponseEntity<List<Post>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND
}
return new ResponseEntity<List<Post>>(posts, HttpStatus.OK);
}
}
Controller
#Controller
public class PostController {
static final Logger logger = LogManager.getLogger(PostController.class.getName());
public static final String REST_SERVICE_URI = "http://localhost:8080/api"; //"http://localhost:8080/api";
private final PostService postService;
#Inject
public PostController(final PostService postService) {
this.postService = postService;
}
#SuppressWarnings("unchecked")
#RequestMapping(value = "/getAll")
// public String create(#Valid Post post, BindingResult bindingResult, Model
// model) {
public ModelAndView getAll() {
// if (bindingResult.hasErrors()) {
// return "mvchome";
// }
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<List<Post>> responseEntity = restTemplate.exchange(REST_SERVICE_URI+"/post",HttpMethod.GET, null, new ParameterizedTypeReference<List<Post>>() {});
// ResponseEntity<Post[]> responseEntity = restTemplate.getForEntity(REST_SERVICE_URI+"/post", Post[].class);
List<Post> postsMap = responseEntity.getBody();
MediaType contentType = responseEntity.getHeaders().getContentType();
HttpStatus statusCode = responseEntity.getStatusCode();
// List<LinkedHashMap<String, Object>> postsMap = restTemplate.getForObject(REST_SERVICE_URI+"/post", List.class);
// String s= REST_SERVICE_URI+"/post";
// logger.info(s);
if(postsMap!=null){
for(Post map : postsMap){
logger.info("User : id="+map.getUid());
}
}else{
logger.info("No user exist----------");
}
//List<Post> postList = postService.findAllPosts();
ModelAndView mav = new ModelAndView("mvchome");
mav.addObject("postsList", postsMap);
Post newpost = new Post();
mav.addObject("post", newpost);
return mav;
}
}
***** to fix my issue I modified my code to just do a redirect on select url paths instead of "/*"
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat =
new TomcatEmbeddedServletContainerFactory() {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
//used to be just collection.addPattern("/*"); now I changed it to specify which path I want it to redirect
collection.addPattern("/mvchome/*");
collection.addPattern("/home/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(createHttpConnector());
return tomcat;
}
The http status 302 is usually caused by wrong url setting.
First, make sure that public ResponseEntity<List<Post>> getAllPosts() {} method is called (just print List<Post> result inside it).
If it's called properly and you can get the return value inside public ModelAndView getAll() {}.
The problem should be the directing setting of the public ModelAndView getAll() {} method.
Check if you make something wrong in your web.xml or spring configuration. Pay attention to the configuration which redirects to views and the url mapping of your dispatcher servlet.
If public ResponseEntity<List<Post>> getAllPosts() {} is called but you can't get the return value, then it should be the issues of directing setting of the public ResponseEntity<List<Post>> getAllPosts() {} method.
Check your spring configuration and web.xml for that. The possible cause usually will be the misuse of wildcard in the configuration and web.xml, or just unnoticed wrong mapping.

Resources