SpringBoot 使用 Spring Security 开启了 CSRF 防跨站攻击防护后 POST 方法无效

在使用 wangEdit 富文本编辑器的过程中,在测试上传图片时,一直显示上传失败。原因也很简单,post 方法的 /upload 一直是 404 ,使用 PostMan 测试也是,一直是 404 Not Found,根本进不了后台。甚至,换其他 post 请求的页面也是这样,搞半天没找到原因。但是,使用 form 表单发起 post 请求却能成功。 最终,找到了原因所在。 因为项目使用了 Spring Security,在配置文件里,开启了 CSRF (跨站请求伪造) 防护。   知道这个原因,就很容易解决问题了。 加一句
  1. http.csrf().ignoringAntMatchers("/upload"); // 禁用 富文本编辑器上传图片 upload 的 CSRF 防护
成功解决。  

关于开启 CSRF 防护后 POST 请求无法发起解决办法

【原因】 使用了 spring-security 后,默认开启了防止跨域攻击的功能,任何 POST 提交到后台的表单都要验证是否带有 _csrf 参数,一旦传来的 _csrf 参数不正确,服务器便返回 403 错误; 解决方法一:form 表单中添加 _csrf 隐藏域
  1. <form method="post" action="/login">
  2.     username: <input type="text" name="userName" />
  3.     <br />
  4.     password: <input type="password" name="password" />
  5.     <br />
  6.     <!-- 添加隐藏域 -->
  7.     <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
  8.     <button type="submit">Submit</button>
  9. </form>
以上代码相对之前代码,添加了
  1. <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
做为提交到后台的 _csrf 值;   解决方法二:form 表单使用 th:action 属性, thymeleaf 会自动在 form 表单中生成 _csrf 隐藏域;
  1. <form method="post" th:action="@{/login}">
  2.     username: <input type="text" name="userName" />
  3.     <br />
  4.     password: <input type="password" name="password" />
  5.     <br />
  6.     <button type="submit">Submit</button>
  7. </form>
  解决方法三:关闭防跨域攻击功能,使用 http.csrf().disable():
  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  4. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  5. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  6. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  7. @Configuration
  8. @EnableWebSecurity
  9. public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
  10.     @Override
  11.     protected void configure(HttpSecurity http) throws Exception {
  12.         http.csrf().disable();
  13.         // 省略其他代码;  
  14.     }
  15.     @Autowired
  16.     public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  17.         // 代码省略...  
  18.     }
  19. }
  解决方法四:忽略指定请求的 CSRF 防护
  1. @Override
  2.     protected void configure(HttpSecurity http) throws Exception {
  3.         //其他代码     
  4.         http.csrf().ignoringAntMatchers("/h2-console/**"); // 禁用 H2 控制台的 CSRF 防护
  5.         http.csrf().ignoringAntMatchers("/upload"); // 禁用 富文本编辑器上传图片 upload 的 CSRF 防护
  6.     }
  【总结】 个人比较推荐方法二 和 方法四; 方法一需要手动在 form 表单中添加 _csrf 隐藏域,比较麻烦,个人并不怎么推荐; 方法三有点儿简单粗暴,如果网站没必要防止跨域攻击的,可以直接用方法三。   参考:http://blog.csdn.net/shawearn1027/article/details/71119587

发表评论

目前评论:1