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

  • 微信
  • 赶快加我聊天吧
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
言曌
广告也精彩

发表评论

:?::razz::sad::evil::!::smile::oops::grin::eek::shock::???::cool::lol::mad::twisted::roll::wink::idea::arrow::neutral::cry::mrgreen: