首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HTTP 405不允许- Spring Boot + Spring Security

HTTP 405不允许- Spring Boot + Spring Security
EN

Stack Overflow用户
提问于 2015-05-11 23:07:25
回答 3查看 11K关注 0票数 2

我有一个简单的rest API与数据库一起工作。它工作正常,直到我添加了安全部分。现在,它提供了POST和DELETE请求上不允许的HTTP 405。我不知道为什么。GET请求可以正常工作。

下面是控制器类:

代码语言:javascript
复制
@Controller
public class MarkerController {

    private Logger logger = Logger.getLogger(MarkerController.class.getName());

    @Autowired
    private MarkerServiceInterface markerService;

    @RequestMapping(value="/markers", method=RequestMethod.GET)
    public @ResponseBody List<Marker> getMarkers(@RequestParam(value="city", defaultValue="") String city) {
        logger.info("HANDLE GET REQUEST");



        return this.markerService.getAllMarkers();
    }

    @RequestMapping(value="/markers/new", method=RequestMethod.POST)
    public @ResponseBody Marker addMarker(@RequestBody Marker marker) {
        logger.info("HANDLE POST REQUEST");

        this.markerService.addMarker(marker);
        return marker;
    }

    @RequestMapping(value="/markers/delete", method=RequestMethod.DELETE)
    public @ResponseBody String deleteMarker(@RequestParam(value="id", defaultValue="") String id) {
        logger.info("HANDLE DELETE REQUEST");
        if (!id.equals("")) {
            logger.info(id);
            this.markerService.deleteMarker(Long.parseLong(id));
        }
        return "";
    }

    @RequestMapping(value="/admin/map")
    public String trafficSpy() {
        logger.info("HANDLE MAP");
        return "index";
    }

    @RequestMapping(value="/admin")
    public String admin() {
        return "admin";
    }

    @RequestMapping(value="/login")
    public String login() {
        return "login";
    }

}

这是SecurityConfig:

代码语言:javascript
复制
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    @Qualifier("userDetailsService")
    UserDetailsService userDetailsService;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http    
            .authorizeRequests()
            .antMatchers("/admin/**")
            .access("hasRole('ROLE_ADMIN')")
            .antMatchers("/markers/**")
            .access("hasRole('ROLE_USER')")
            .and()
            .formLogin()
            .loginPage("/login")
            .failureUrl("/login?error")
            .usernameParameter("username")
            .passwordParameter("password")
            .and()
            .logout()
            .logoutSuccessUrl("/login?logout")
            .and()
            .csrf()
            .and()
            .exceptionHandling()
            .accessDeniedPage("/403");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder;
    }

    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }
}

使用以下ajax代码调用DELETE请求:

代码语言:javascript
复制
$.ajax({
        url: "localhost:8080/markers/delete?id=" + currentMarker.get("id"),
        type: 'DELETE',
        success: function(result) {
            console.log(result);
        }
    });

下面是控制台中给出的消息:

代码语言:javascript
复制
2015-05-11 15:48:13.671  WARN 8279 --- [nio-8181-exec-6] o.s.web.servlet.PageNotFound             : Request method 'DELETE' not supported

这些是响应的标头。我可以看到,在AlLLOW中,我只有GET和HEAD。因此,如果我是对的,这意味着控制器中的方法只接受GET和HEAD请求。

代码语言:javascript
复制
(Status-Line)               HTTP/1.1 405 Method Not Allowed
Server                      Apache-Coyote/1.1
x-content-type-options      nosniff
x-xss-protection            1; mode=block
Cache-Control               no-cache, no-store, max-age=0, must-revalidate
Pragma                      no-cache
Expires                     0
X-Frame-Options             DENY
Allow                       GET, HEAD
Content-Type                application/json;charset=UTF-8
Transfer-Encoding           chunked
Date                        Mon, 11 May 2015 17:35:31 GMT

在我的回答中,我有这样的体验:

代码语言:javascript
复制
org.springframework.web.HttpRequestMethodNotSupportedException

你知道是什么导致了这个问题吗?如何允许POST和DELETE方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-05-31 05:10:50

你忘了csrf-Token吧。

建议您在元标记中添加csrf-Token。您可以在Spring Security Documentation中阅读它

使用此选项,您可以执行以下操作:

代码语言:javascript
复制
$(function () {
  var token = $("meta[name='_csrf']").attr("content");
  var header = $("meta[name='_csrf_header']").attr("content");
  $(document).ajaxSend(function(e, xhr, options) {
    xhr.setRequestHeader(header, token);
  });
});
票数 3
EN

Stack Overflow用户

发布于 2016-10-21 00:19:55

我想留下一个额外的解决方案,因为尽管Manu Zi的答案是正确的,但我不能立即弄清楚为什么我第一次遇到这个问题并找到了这个答案。

潜在的问题被405方法不允许的直接问题所掩盖。

在我的例子中,有两个因素在起作用。首先,我的AccessDenied控制器没有POST方法,当POST方法被拒绝并被重定向到AccessDenied控制器时,这会导致405。只有在org.springframework.web上打开调试日志后,这一点才明显。

一旦明确了这一点,就需要弄清楚为什么我的访问被拒绝了。所有的权限和角色都是正确的,但是在从Spring3升级到Spring4之后,我发现CSRF保护在默认情况下是启用的。要么需要禁用它,要么必须使用Manu Zi的解决方案。

要禁用它,请参阅:spring security 4 csrf disable via xml

票数 1
EN

Stack Overflow用户

发布于 2021-02-16 01:17:32

在我的例子中,协议必须是https而不是http

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30171265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档