I am trying to build Spring boot REST application with angularJS.
So, application is loading well, every JS and CSS files included. The problem is that when I am doing GET request, it goes right way, but when I am doing POST request it fails and doesn't try to call the controller method.
That's my Spring Boot Application class
#EnableAspectJAutoProxy(proxyTargetClass=true)
#SpringBootApplication(scanBasePackages = {"org.test.controllers", "org.test.services"})
#Import({ WebSecurityConfig.class, DBConfig.class, ViewConfig.class})
public class Application extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
System.out.println("STARTING APP");
SpringApplication.run(Application.class, args);
}
}
And that's my controller class
#RestController
#RequestMapping("/tag")
public class TagController {
#Autowired
private TagService tagService;
#RequestMapping(method = RequestMethod.GET)
#ResponseStatus(HttpStatus.OK)
public Iterable<Tag> getAllTags() {
return tagService.getAll();
}
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public Tag saveTag(#RequestBody Tag tag) {
return tagService.save(tag);
}
}
So, when I am doing $http.get("/tag", success, error) it gives [], which means that controller was called.
And when I am doing $http.post("/tag", {name: 'name'}, success, error) it returns {"timestamp":1489939480282,"status":404,"error":"Not Found","message":"No message available","path":"/tag"}
To make sure that mapping was done, here's part of logs
Mapped "{[/tag],methods=[POST]}" onto public org.test.model.Tag org.expotest.controllers.TagController.saveTag(org.test.model.Tag)
I am running on Tomcat server if it matters.
Any ideas what could be wrong in my configuration? That seems really strange for me.
Thanks in advance.
If you are using Spring security try disabling csrf in your configure method, should look something like this:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
}
Related
In my application, I have few APIs that I want to allow without authentication. So I added that patterns in the permitall(). But this only works if those patterns are inside the #RestController annotation. If those patterns are in #Controller annotation (I want to return views), Spring asks for the authentication even though they are under permitall().
WebsecutiryConfig class
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().
.authorizeRequests().antMatchers("/pattern1", "/pattern2").permitAll()
.anyRequest().authenticated()
}
Class with #RestController annotation
#RestController
public class RESTClass {
#GetMapping("/pattern1")
public String hello() {
return "my response";
}
Class with #Controller annotation
#Controller
public class ControllerClass {
#GetMapping("/pattern2")
public String hello(Model model) {
return "my view";
}
So how can I allow users to see those views without authentication?
So I figured it out. What was happening was that spring was allowing the view file to load without the authentication but it was not allowing to load the related css and js files. So I had to add them to the permitall() pattern.
I'm new to Spring framework.
I try to make a simple web server application with Spring but I got 404 Not Found when I call url with Postman.
package com.leoaslan.doctorfinder;
//..import
#SpringBootApplication
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
#ComponentScan({"com.delivery.request"})
#EntityScan("com.delivery.domain")
#EnableJpaRepositories("com.delivery.repository")
public class DoctorfinderApplication {
public static void main(String[] args) {
SpringApplication.run(DoctorfinderApplication.class, args);
}
}
package com.leoaslan.doctorfinder.controller;
//import
#RestController
#RequestMapping("/api")
public class LoginController {
private final Logger log = LoggerFactory.getLogger(LoginController.class);
#Autowired
LoginService loginService;
#GetMapping("/auth/login")
ResponseEntity<?> login(HttpServletRequest request) {
System.out.println("OK");
return new ResponseEntity<>(HttpStatus.ACCEPTED);
}
}
I haven't configured anything yet in application.properties.
Thanks for any helps
Your Controller class is not being scanned, so just try to add the proper package of your controllers on your #ComponentScan
#ComponentScan({"com.delivery.request", "com.leoaslan.doctorfinder.controller"})
Actually, do you really have those packages (com.delivery.request, com.delivery.domain, com.delivery.repository) on your application ? They look suspiciously copy/pasted and they will not do anything unless you change them where your classes really are.
I have a problem using springboot-starter-security. I want to secure only urls that does not begin with "/api", all urls such as "/api" or "/api/" or "/api/**" must no be secured.
In WebSecurityConfigClass I have:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api*");
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
In the application I have two different controllers, webcontroller and restcontroller. For the moment web isn't yet implemented but it must address urls that i want to be secured, the rest controller manage urls that i want not to need an authentication.
I have a test class for the rest controller, and all tests fails because they are expecting a 200 as status, but they receive 401. For example:
#Test
public void testStatus200() throws Exception{
mvc.perform(get("/api")).andExpect(status().isOk());
}
this test fails due to status is 401 and not 200. Why?
I solved, the test class did not use the websecurityconfig class.
I fixed by adding an explicit import of the WebSecurityConfig as class annotation:
#RunWith(SpringRunner.class)
#WebMvcTest(controllers=ARestController.class)
#Import(WebSecurityConfig.class) // <---
public class ARestControllerTest { ... }
I'm wrote a web application in java using Spring framework. Tested it and deployed to remote tomcat server. After deploying I have message OK - Started application at context path [/proxynator]. But, if I use links like http://109.206.178.66:8080/proxynator/ and http://109.206.178.66:8080/proxynator/proxynator/test I have 404 – Not Found and Description: The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
In Application I have starter class
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
and controller
#RestController
#RequestMapping("/proxynator")
public class MainController {
#Autowired
private ProxyRepo proxyRepo;
#Autowired
private CountryRepo countryRepo;
#RequestMapping("/countries")
#ResponseBody
public List<Country> findCountries() {
return countryRepo.findAll();
}
#RequestMapping("/test")
#ResponseBody
public String testMethod() {
return "HELLO";
}
}
I don't know, why I have this problem, because I setting up my tomcat server right, path to my controller is right and application on server is running.
Any ideas how to solve it?
UPD
I was changed my controller like:
#RestController
public class MainController {
#Autowired
private CountryRepo countryRepo;
#RequestMapping("/countries")
#ResponseBody
public List<Country> findCountries() {
return countryRepo.findAll();
}
#RequestMapping("/")
#ResponseBody
public String testMethod() {
return "HELLO";
}
}
And now my enter point is / that calling testMethod(), but it doesn't working too.
To solve this problem I was extends SpringBootServletInitializer and override configure method`
#Override
override fun configure(application: SpringApplicationBuilder?):
SpringApplicationBuilder {
return super.configure(application)
}
and I changed project structure like in official documentation. And now it works good.
PS
I was rewrite project to Kotlin
I'm trying to add an authentification to my RestController, but i can't find any good documentation or any sample with Java Configuration.
I tried this but it doesn't work (i can access to all request without login)
My controller is annotated with #PreAuthorize
#RestController
#RequestMapping("/api/hello")
public class HelloController {
#RequestMapping(value = "/say", method = RequestMethod.GET)
public String sayHello() {
return "hello";
}
#PreAuthorize("hasRole('ROLE_USER')")
#RequestMapping(value = "/say/user", method = RequestMethod.GET)
public String sayHelloWithUserProtection(){
return "Hello USER";
}
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(value = "/say/admin", method = RequestMethod.GET)
public String sayHelloWithAdminrProtection(){
return "Hello ADMIN";
}
}
SecurityConfig
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#ComponentScan(basePackages = {"com.test.server.security"})
public class SecurityConfig {
#Autowired
public void configureAuthentification(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("admin").roles("USER","ADMIN");
}
#Configuration
public static class ApiWebConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.formLogin();
}
}
}
SecurityWebApplicationInitializer
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
How can i make it work?
And there is any good tutorial to make a REST token based (token which save session key and others custom values) authentification saved in database with JPA (or JDBC ?) with Java configuration ?
Drop the formLogin(). You need to maintain the mindset that REST is supposed to be stateless. Logging in with a form this way, is not purely REST.
You can create a fine masked filter with Spring security chains like this (randomly just added stuff to create a more complete. Spring Security works by filters, which means that you need to create an actual filter before it kicks in. Specifically you need to authorize requests before matching them to paths.
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/say/user/").hasRole("USER")
.antMatchers("/say/admin").hasRole("ADMIN")
.anyRequest().authenticated();
The code above should be self explaining. If not, I will try to elaborate on it.
As for token based login, this is a good idea, but you should not roll your own.
Spring has great Oauth support and getting started securing your REST API with it is awesome.
This tutorial explains it in great detail and should help you further in building better API's as well.
http://spring.io/guides/tutorials/bookmarks/
Also make sure you have a look at Fowler's writings on REST here
http://martinfowler.com/articles/richardsonMaturityModel.html
I forgot to put my WebApplicationInitialisation in the question.
My error was i put SecurityConfig in getRootConfigClasses() instead of getServletConfigClasses().
Now WebApplicationInitialisation looks like this and it work great !
public class WebApplicationInitialisation extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebMvcConfig.class, SecurityConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
}
}