Spring Boot Starter安全性Post方法不起作用。

4
我已经将'spring-boot-starter-security'添加到现有的spring boot项目中; 之后,Spring Rest控制器中的POST方法不能正常工作,会显示一个错误,类似于这样:
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

我的控制器方法如下:

@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 文件:

<?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:");             

    }

}

如果我删除所有与安全相关的内容,代码将运行得很好。我的配置有什么问题吗?安全登录表单和所有其他功能都工作得很好,但是POST方法不起作用。

5个回答

19

.csrf().disable()解决了问题。

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


我认为最好的方法是禁用例如/graphql的端点,正如这个答案所解释的那样:https://dev59.com/x1oT5IYBdhLWcg3w2SQS#38108872 - Acapulco

5
没必要禁用安全功能,最好的方法是学习如何正确使用它。 http://www.baeldung.com/spring-security-csrf 简而言之,你需要在所有的POST表单中添加一个隐藏属性。
<input type="hidden" th:attr="name=${_csrf.parameterName},value=${_csrf.token}"/>

2
这个错误是因为当你将Spring安全性添加到你的类路径或pom.xml文件时,默认情况下会启用csrf,你只能使用get方法,但如果要访问put、post、patch和delete rest端点,则有两个选项:
A)禁用csrf,如下所示:
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests().antMatchers("/","/saveUser/**","/css/").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin();
}

B) 在使用Postman客户端时包含csrf令牌

请参考此图片


0

请问您能否提供一下UserCredentials对象的详细信息?我在请求中没有看到它被发布。

您尝试做的事情让我想起了使用@AuthenticationPrincipal注释而不是使用@RequestBody发布内容所能实现的功能。这将涉及其他机制。

无论如何,有两件事:

  1. 您想从此控制器返回什么?authenticate方法中是否缺少@ResponseBody?您可以尝试添加一下吗?
  2. 以防万一:您可以尝试强制执行您的控制器消耗的内容类型(@RequestMapping注释的consumes属性)与您的请求发送的内容类型相同(已经提到是application/json)

0

正如 sudeep cv 提到 的那样,您可以为应用程序禁用 CSRF。

正如 user16115 提到 的那样,最好不要禁用重要的安全机制。

CSRF 保护是否重要取决于您的应用程序。Spring Boot 对何时应该包含或不包含它有一个建议

何时应该使用 CSRF 保护?我们的建议是对任何可能由普通用户通过浏览器处理的请求使用 CSRF 保护。如果您只创建了一个由非浏览器客户端使用的服务,则可能希望禁用 CSRF 保护。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接