sudeep cv
sudeep cv

Reputation: 1951

spring boot starter security post methods not working

I have added spring 'spring-boot-starter-security' to existing spring boot project ; after that the post methods in spring rest controller not working properly it shows a error something like this :

o.s.web.servlet.PageNotFound             : Request method 'POST' not supported


Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/authenticate
Request Method:POST
Status Code:405 Method Not Allowed
Response Headers
view source
Allow:GET, HEAD
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Content-Type:application/json;charset=UTF-8
Date:Wed, 14 Oct 2015 05:41:06 GMT
Expires:0
Pragma:no-cache
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
Request Headers
view source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:47
Content-Type:application/json;charset=UTF-8
Cookie:_ga=GA1.1.630164096.1442901791; JSESSIONID=B9F1946DAE5BCA7772526CFC735616EC
Host:localhost:8080
Origin:http://localhost:8080
Referer:http://localhost:8080/
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36
X-ZUMO-APPLICATION:GSECUHNQOOrCwgRHFFYLXWiViGnXNV88
Request Payload

my controller method is this:

@RequestMapping(value="/authenticate",method = {RequestMethod.POST})
public  LinkedHashMap<String,Object> authenticate(@RequestBody UserCredentials user){


    LinkedHashMap<String, Object> res =new LinkedHashMap<String, Object>();
    //business logic 
    return res;
}

pom file:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.dfasfa</groupId>
    <artifactId>AdminDashboard</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>AdminDashboard</name>


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>      
        <java.version>1.7</java.version>
    </properties>

    <dependencies>
            <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.0.3.Final</version>
        </dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <!--<scope>provided</scope>-->
</dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>



        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.21</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <!--<scope>provided</scope>-->
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <!--<scope>provided</scope>-->
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-jpamodelgen</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


@Configuration
@ComponentScan
@EnableWebMvcSecurity

public class WebSecurityConfig extends  WebSecurityConfigurerAdapter {

 @Autowired
 private UserDetailsService userDetailsService;

 @Autowired
 public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
     auth.userDetailsService(userDetailsService).passwordEncoder(passwordencoder());
 }

 @Override
 protected void configure(HttpSecurity http) throws Exception {
   http.authorizeRequests()
           .antMatchers("/addService").permitAll()
           .antMatchers("/app/*").permitAll()
           .antMatchers("/lib/*").permitAll()
           .antMatchers("/css/*").permitAll()
           .antMatchers("/styles/*").permitAll()
           .antMatchers("/login").permitAll()
           .antMatchers("/getAllUsers").permitAll()
           .anyRequest().permitAll()  // for testing 
  .and()
//    .formLogin().loginPage("/login")
           .formLogin()
    .usernameParameter("username").passwordParameter("password")
  .and()
    .logout().logoutSuccessUrl("/login?logout")
   .and()
   .exceptionHandling().accessDeniedPage("/#/login")
  .and()
    .csrf();
 }

 @Bean(name="passwordEncoder")
    public PasswordEncoder passwordencoder(){
     return new BCryptPasswordEncoder();
    }





}


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Application  {


    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        System.out.println("Let's inspect the beans provided by Spring Boot:");             

    }

}

if i remove all these security related stuff the code is working great . Is there any thing wrong in my configuration ? . the security login form and all other functionality is working great . but the post methods is not working .

Upvotes: 4

Views: 13634

Answers (5)

sudeep cv
sudeep cv

Reputation: 1951

.csrf().disable() solved the problem

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception{
        httpSecurity.csrf().disable();
    }
}

Upvotes: 19

Piyush Priyadarshi
Piyush Priyadarshi

Reputation: 21

This error is happening because when you add the Spring security to your classpath or pom.xml file, by default csrf gets enabled and you can only hit get method but for hitting put, post, patch, and delete rest endpoints, you have 2 options:

A) Disable the csrf like this

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests().antMatchers("/","/saveUser/**","/css/").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin();
}

B) Include csrf token while hitting from Postman Client

Please Refer this Image

Upvotes: 2

Jeffrey Maier
Jeffrey Maier

Reputation: 131

As sudeep cv mentioned, you can disable CSRF for your application

As user16115 mentioned, it would probably better not to disable important security mechanisms.

Whether or not CSRF protection is important or not is dependant on your application. Spring Boot has a recommendation for when you should or should not include it:

When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.

Upvotes: 0

user16115
user16115

Reputation: 344

Rather than disabling a security feature, it's better to search how to correctly implement it. http://www.baeldung.com/spring-security-csrf

In short you need to add an hidden attribute to all your POST forms.

<input type="hidden" th:attr="name=${_csrf.parameterName},value=${_csrf.token}"/>

Upvotes: 5

Jean-Charles Eloi
Jean-Charles Eloi

Reputation: 1

Could you please provide insight on what the UserCredentials object is ? I can't see it posted in the request too.

What you try to do rather reminds me what you can achieve using the @AuthenticationPrincipal annotation rather than posting content with a @RequestBody. This will yet imply some other mechanisms.

Anyway, two things :

  1. What do you want to return from this controller ? Isn't there a @ResponseBody missing from the authenticate method ? Could you try adding that ?
  2. Just in case : could you try to enforce the content-type consumed by your controller (consumes attribute of the @RequestMapping annotation) as sent in your request (already mentionned as application/json)

Upvotes: 0

Related Questions