对Spring服务器的POST请求返回403禁止

时间:2014-12-09 22:53:07

标签: android spring

我已设置spring服务器以响应包含Message对象的POST请求:

@RequestMapping(value = "/signup", method = RequestMethod.POST, consumes = "application/json")
    public @ResponseBody Message signUp(@RequestBody Message message) {
        logger.info("Accessing protected resource");
        return new Message(100, "Congratulations!", "You have signed up. msg:"+message.toString());
    }

Android客户端设置为将请求发送为:

@Override
    protected Message doInBackground(Void... params) {
        // TODO Auto-generated method stub
        final String url = "http://10.0.2.2:8080/signup";
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<Message> requestEntity = new HttpEntity<Message>(signupmsg, requestHeaders);

        // Create a new RestTemplate instance
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());

        try {
            // Make the network request
            Log.d(TAG, url);
            ResponseEntity<Message> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Message.class);
            return response.getBody();
        } catch (HttpClientErrorException e) {
            Log.e(TAG, e.getLocalizedMessage(), e);
            return new Message(0, e.getStatusText(), e.getLocalizedMessage());
        } catch (ResourceAccessException e) {
            Log.e(TAG, e.getLocalizedMessage(), e);
            return new Message(0, e.getClass().getSimpleName(), e.getLocalizedMessage());
        }
    }

但是服务器始终返回403 Forbidden错误。我希望它返回另一个Message对象 Message对象是在单独的类中自定义的。但是,如果我发送没有封装对象的GET请求,它就可以工作。我是Spring的新手。我在这里缺少什么?

更新:我诊断出这个问题,当我启用spring web安全性时就会发生这种情况。没有安全性,POST请求成功。我尝试在配置中禁用安全性但它仍然无法正常工作。 (但GET请求工作正常。)我目前在WebSecurityConfiguration.java中有以下内容

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // @formatter:off
        auth.inMemoryAuthentication()
                .withUser("roy")
                .password("spring")
                .roles("USER");
        // @formatter:on
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
                .authorizeRequests()
                .anyRequest().permitAll()
                .and()
                .httpBasic().disable();
        // @formatter:on
    }

我通过在build.gradle中添加以下内容来启用Web安全性 compile("org.springframework.boot:spring-boot-starter-security")

我尝试使用REST客户端使用浏览器发送POST请求,但它给出了错误: HTTP状态403 - 未找到预期的CSRF令牌。你的课程到期了吗?

使用.csrf()。disable()

暂时修复了它

解决这个问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

我认为这是一个老问题,如果有人仍然遇到此问题,解决方案很简单,您需要将“_csrf”标记作为参数添加到您的请求中。禁用它不是一个解决方案。 exchange()方法也接受参数映射。

    Map<String, Object> parameters = new HashMap<>();
    CsrfToken token = (CsrfToken) request.getAttribute("_csrf");
    parameters.put("_csrf", token);
    restTemplate.exchange("url", HttpMethod.POST, requestEntity, Message.class, parameters);

<强>更新 如何检索csrf令牌:

  1. 您可以更改方法以接受另一个参数String csrfToken,并在调用方法之前从请求中检索令牌。
  2. @Autowire HttpServletRequest在您拥有“doInBackground()”的类中,这不是一个好习惯,最好只在使用它的方法中传递请求对象。
  3. Spring通过名为“ServletRequestAttributes”的对象公开会话和请求对象,因此您可以这样做:

    HttpServletRequest request =
    ((ServletRequestAttributes)RequestContextHolder
                    .currentRequestAttributes())
                    .getRequest();