I am trying to send a request from my Webstorm application to my backend application, which both are at different ports, I am working with angularJS in the front end and java in backend. I have read up a bit about CORS Filters and I learned that in order to do Cross Origin Requests I need to implement these. However, after doing this my error, being
我正在尝试将Webstorm应用程序的请求发送到我的后端应用程序,它们都在不同的端口上,我在前端使用angularJS,在后端使用java。我读了一些关于CORS过滤器的知识,我了解到,为了实现这些交叉源请求,我需要实现它们。然而,在这样做之后,我的错误,存在
Failed to load resource: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63343' is therefore not allowed access. http://localhost:8080/register?password=&username=
XMLHttpRequest cannot load http://localhost:8080/register?password=&username=. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63343' is therefore not allowed access.
did not change at all which led me to believe I have done something wrong, here is the code from which I am sending the request:
没有改变,使我相信我做错了什么,这是我发送请求的代码:
var charmanderServices = angular.module('charmanderServices', ['ngResource']);
var hostAdress = "http://localhost:8080";
charmanderServices.factory("register", ["$resource",
function($resource){
console.log('in service');
return $resource(hostAdress + "/register", {}, {
'registerUser' : { method: 'POST', isArray: false,
params: {
username: '@username',
password: '@password'
}
},
headers : {'Content-Type' : 'application/x-www-form-urlencoded'}
});
}
]);
My corsFilter is written like this:
我的过滤器是这样写的:
@Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
//This is not even printing
System.out.println("Cheers lads, I'm in the filter");
HttpServletResponse response = (HttpServletResponse) res;
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, X-Auth-Token, Content-Type");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
This is my web.xml:
这是我的web . xml。
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd">
<display-name>Project</display-name>
<!-- Load Spring Contexts -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- CORS Filter -->
<filter>
<filter-name>cors</filter-name>
<filter-class>com.robin.filters.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
This is the controller where I am catching the request:
这是控制器,我在这里捕捉请求:
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/register" , method= RequestMethod.POST, produces = "application/json")
@ResponseBody
public boolean register(@RequestParam(value = "username") String username, @RequestParam(value = "password") String password){
System.out.println("Im in register hurray");
return userService.register(username, password);
}
}
Update: I have tried implementing the filter as a OncePerRequestFilter, still doesn't work. Is anyone able to help me further here?
更新:我尝试将过滤器实现为OncePerRequestFilter,但仍然无效。这里有人能帮我吗?
Update#2: Also tried this one, http://software.dzhuvinov.com/cors-filter-installation.html, no luck
更新#2:也试过这个,http://software.dzhuvinov.com/cors-filter-installation.html,运气不好
Update#3: This was my output in the console, I can see that the response did not add any headers:
更新#3:这是我在控制台的输出,我可以看到响应没有添加任何标题:
Request URL:http://localhost:8080/register?password=g&username=g
Request Method:OPTIONS
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,nl;q=0.6
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:63343
Referer:http://localhost:63343/Project/index.html?uName=g&uPassword=g&uPasswordConfirm=g
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36
Query String Parametersview sourceview URL encoded
password:g
username:g
Response Headersview source
Allow:GET, HEAD, POST, PUT, DELETE, OPTIONS
Content-Length:0
Date:Fri, 04 Apr 2014 09:50:35 GMT
Server:Apache-Coyote/1.1
Update#4: Annotated the filter with @WebFilter instead of @Component, didn't help
更新#4:用@WebFilter而不是@Component来注释过滤器,没有帮助
Update#5: Here is my applicationContext.xml file:
更新#5:这是我的应用程序上下文。xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.robin"/>
<mvc:annotation-driven/>
<!-- Hibernate Session Factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan">
<array>
<value>com.robin.model</value>
</array>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.robin.model.User</value>
</list>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!--Driver for mysqldb -->
<import resource="mysql-context.xml"/>
</beans>
I also added the code from my controller and register.html file here:
我还添加了来自我的控制器和寄存器的代码。html文件:
charmanderControllers.controller('registerController', ['$scope', 'register',
function($scope, register){
$scope.username = '';
$scope.password = '';
$scope.register = function () {
register.registerUser({'username': $scope.username, 'password': $scope.password}).$promise.then(function(data){
switch(data.response){
case true:
//succes
$scope.registered = true;
$scope.userExists = false;
break;
case false:
//user exists
$scope.registered = false;
$scope.userExists = true;
break;
}
console.log(data.response);
})
};
$scope.checkValidRegister = function (invalid) {
console.log(invalid);
console.log($scope.passwordConfirm);
console.log($scope.password);
console.log($scope.username);
if (invalid || $scope.password != $scope.passwordConfirm) {
console.log("I shouldnt be here");
$scope.validation = true;
if ($scope.password != $scope.passwordConfirm) {
$scope.passwordError = true;
}
} else {
register();
}
};
}]);
register.html
register.html
<h1>Register now!</h1>
<form method="post" class="register" novalidate>
<p>
<label for="email">E-mail:</label>
<input type="text" name="login" id="email" placeholder="E-mail address..." required ng-model="username">
</p>
<p>
<label for="password">Password:</label>
<input type="password" name="password" id="password" placeholder="Password..."
required ng-model="password">
</p>
<p>
<label for="confirm_password">Confirm password: </label>
<input type="password" name="confirm_password" id="confirm_password" placeholder="Confirm password..."
required ng-model="passwordConfirm">
<span ng-show="passwordError">Passwords do not match!</span>
</p>
<p class="register_submit">
<button type="submit" class="register-button" ng-click="checkValidRegister()">Register</button>
</p>
</form>
1 个解决方案
#1
31
Your code and configuration looks good in general and I was able to run it on local environment. Please remove @Component annotation from your SimpleCORSFilter
, because you use it as a plain Servlet Filter and it doesn't need to be a part of Spring context.
您的代码和配置看起来很好,我可以在本地环境中运行它。请从SimpleCORSFilter中删除@Component注释,因为您将它用作普通的Servlet过滤器,它不需要是Spring上下文的一部分。
UPD. Tomcat 7 has its own CORS filter implementation. You can check documentation and source code for more details. I have modified the headers to reflect its default configuration, should work as expected now.
乌利希期刊指南。Tomcat 7有自己的CORS过滤器实现。您可以查看文档和源代码,了解更多细节。我已经修改了头部以反映其默认配置,现在应该可以像预期的那样工作了。
Since you are already using Spring and if you are using Spring 4.2 or higher, you dont need CorsFilter
, but can simply annotate your controller method with CrossOrigin
. Here is the excellent article on this, worth a read.
由于您已经在使用Spring,并且如果您正在使用Spring 4.2或更高版本,那么您不需要CorsFilter,只需使用CrossOrigin对控制器方法进行注释。这里有一篇很好的文章,值得一读。
Please also check nice resource which describes CORS configuration for different platforms.
还请检查nice资源,它描述了不同平台的CORS配置。
Here is my working example using plain Filter implementation:
下面是我使用plain Filter实现的工作示例:
Controller:
控制器:
@Controller
public class UserController {
private static Logger log = Logger.getAnonymousLogger();
@RequestMapping(
value = "/register",
method = RequestMethod.POST,
consumes = "application/x-www-form-urlencoded")
@ResponseBody
public String register(@RequestParam(value = "user") String username,
@RequestParam(value = "password") String password) {
log.info(username + " " + password);
return "true";
}
}
Filter:
过滤器:
public class CorsFilter implements Filter {
private static final Logger log = Logger.getAnonymousLogger();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("Adding Access Control Response Headers");
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, HEAD, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
Filter mapping in web.xml:
在web . xml过滤器映射:
<filter>
<filter-name>cors</filter-name>
<filter-class>com.udalmik.filter.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/register</url-pattern>
</filter-mapping>
JS to perform request from separate web app (JQuery):
JS执行来自独立web应用程序(JQuery)的请求:
$(document).ready(function() {
$('#buttonId').click(function() {
$.ajax({
type: "POST",
url: "http://localhost:8080/register",
success : function(data){
console.log(data);
},
data : {
user : 'test.user@acme.com',
password : 'password'
}
});
}
}
#1
31
Your code and configuration looks good in general and I was able to run it on local environment. Please remove @Component annotation from your SimpleCORSFilter
, because you use it as a plain Servlet Filter and it doesn't need to be a part of Spring context.
您的代码和配置看起来很好,我可以在本地环境中运行它。请从SimpleCORSFilter中删除@Component注释,因为您将它用作普通的Servlet过滤器,它不需要是Spring上下文的一部分。
UPD. Tomcat 7 has its own CORS filter implementation. You can check documentation and source code for more details. I have modified the headers to reflect its default configuration, should work as expected now.
乌利希期刊指南。Tomcat 7有自己的CORS过滤器实现。您可以查看文档和源代码,了解更多细节。我已经修改了头部以反映其默认配置,现在应该可以像预期的那样工作了。
Since you are already using Spring and if you are using Spring 4.2 or higher, you dont need CorsFilter
, but can simply annotate your controller method with CrossOrigin
. Here is the excellent article on this, worth a read.
由于您已经在使用Spring,并且如果您正在使用Spring 4.2或更高版本,那么您不需要CorsFilter,只需使用CrossOrigin对控制器方法进行注释。这里有一篇很好的文章,值得一读。
Please also check nice resource which describes CORS configuration for different platforms.
还请检查nice资源,它描述了不同平台的CORS配置。
Here is my working example using plain Filter implementation:
下面是我使用plain Filter实现的工作示例:
Controller:
控制器:
@Controller
public class UserController {
private static Logger log = Logger.getAnonymousLogger();
@RequestMapping(
value = "/register",
method = RequestMethod.POST,
consumes = "application/x-www-form-urlencoded")
@ResponseBody
public String register(@RequestParam(value = "user") String username,
@RequestParam(value = "password") String password) {
log.info(username + " " + password);
return "true";
}
}
Filter:
过滤器:
public class CorsFilter implements Filter {
private static final Logger log = Logger.getAnonymousLogger();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("Adding Access Control Response Headers");
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, HEAD, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
Filter mapping in web.xml:
在web . xml过滤器映射:
<filter>
<filter-name>cors</filter-name>
<filter-class>com.udalmik.filter.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/register</url-pattern>
</filter-mapping>
JS to perform request from separate web app (JQuery):
JS执行来自独立web应用程序(JQuery)的请求:
$(document).ready(function() {
$('#buttonId').click(function() {
$.ajax({
type: "POST",
url: "http://localhost:8080/register",
success : function(data){
console.log(data);
},
data : {
user : 'test.user@acme.com',
password : 'password'
}
});
}
}