我用作服务器端Spring-boot并为测试提供虚拟服务
我的 ServiceCaller.java =
package com.user.server.mfw;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.handler.MappedInterceptor;
@RestController
public class ServiceCaller {
@CrossOrigin(allowedHeaders="*",allowCredentials="true")
@RequestMapping(value="/serviceCaller",method=RequestMethod.POST, headers="content-type=text/*")
@ResponseBody
String serviceListener(@RequestParam("serviceName") String serviceName,HttpSession session,HttpServletRequest theHttpServletReq ) throws IOException
{
if(!serviceName.isEmpty())
{
byte[] encoded = Files.readAllBytes(Paths.get("C://Users//something//Desktop//asd.json"));
return new String(encoded, "UTF-8");
}
return "gelemedi";
}
private void checkActiveSessionControl(HttpSession session)
{
System.out.println("Session Id:" + session.getId() +" // " + session.getCreationTime());
if(session == null)
System.out.println("Null");
else if(session.isNew())
System.out.println("New");
else
System.out.println("Old");
}
}
我的客户端是离子框架,基于angular.js ......
Controller.js
$scope.getInfo = function() {
$http({
url: SERVER_ENDPOINT.url + '/serviceCaller',
method: 'POST',
params: {serviceName: 'deneme'},
withCredentials: true
}).then(function(result) {
var alertPopup = $ionicPopup.alert({
title: 'ALOHA!',
template: 'dksjd ' + result
});
$scope.memberInfo = result.data.accountNumber;
}, function() {
var alertPopup = $ionicPopup.alert({
title: ' failed!',
template: 'da'
});
}
);
};
基本上,当我使用POST方法而不是GET时,我得到“无效的HTTP状态代码403”。但是,我想使用 POST 来代替 GET 进行调用。 但是我无法弄清楚我在哪里弄错了......
任何解决方案将不胜感激!
答案 0 :(得分:7)
如果您的浏览器正在发送飞行前OPTIONS请求,您只需通过允许http OPTIONS在WebSecurity配置中允许该操作。
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
答案 1 :(得分:1)
我认为您没有使用此anotation传递任何参数:
@CrossOrigin(allowedHeaders="*",allowCredentials="true")
@RequestMapping(value="/serviceCaller",method=RequestMethod.POST, headers="content-type=text/*")
@ResponseBody
String serviceListener(@RequestParam("serviceName") String serviceName,HttpSession session,HttpServletRequest theHttpServletReq ) throws IOException
{
您应该value="/serviceCaller"
替换value="/{serviceCaller}"
编辑
请将此课程添加到您的项目中以解决CORS问题
@Component
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig fc) throws ServletException {}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, resp);
}
@Override
public void destroy() {}
}
答案 2 :(得分:1)
XSRF是一种未经授权的网站可以获取用户私人数据的技术。 Angular提供了一种对抗XSRF的机制。执行XHR请求时,$ http服务从cookie(默认情况下为XSRF-TOKEN)读取令牌并将其设置为HTTP头(X-XSRF-TOKEN)。由于只有在您的域上运行的JavaScript才能读取Cookie,因此您的服务器可以确保XHR来自您域上运行的JavaScript。不会为跨域请求设置标头。
所以默认标头是x-xsrf-token。
在CsrfFilter
之后的websecurity配置中添加此过滤器public class CsrfHeaderFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
}
添加过滤器,如下所示:
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()...
.and()
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
}
}
答案 3 :(得分:0)
我在回答问题Angularjs Post not sending headers to Spring JWT时非常清楚地发现了预检请求的解释。
由于您使用的是Spring Security,因此必须在Spring Security级别启用CORS,以允许它利用Spring MVC级别定义的配置:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}
Here是非常优秀的教程,解释了Spring MVC框架中的CORS支持。
这使HttpMethod.Options
请求能够在预检请求中包含标题。