我已设置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()
暂时修复了它解决这个问题的最佳方法是什么?
答案 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令牌:
Spring通过名为“ServletRequestAttributes”的对象公开会话和请求对象,因此您可以这样做:
HttpServletRequest request =
((ServletRequestAttributes)RequestContextHolder
.currentRequestAttributes())
.getRequest();