繁体   English   中英

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

[英]POST request to Spring server returns 403 forbidden

我已将 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 网络安全时它就会发生。 没有安全性,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 compile("org.springframework.boot:spring-boot-starter-security")来启用网络安全

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

使用 .csrf().disable() 临时修复它

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

我看到这是一个老问题,如果有人仍然遇到这个问题,解决方案很简单,您需要将“_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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM