JQuery invoking Spring Rest service: Cross-Origin issue vs ParseError - java

I am trying to invoke a REST service with jquery, but either I get a Cross Origin Problem (when I do not specify the datatype in jquery invocation) or a parseerror (when I do).
JQuery use:
function requestData() {
$.ajax({
url: 'http://xxx.xx.xx.xxx:8080/Project/api/',
type: 'GET',
dataType:"jsonp",
success: function(json) {
console.log("OK");
console.log(json);
},
error: function(xhr, status, error) {
console.log("NO");
console.log("STATUS:" + status);
}
});
}
Server side, I am using Spring REST this way:
#RequestMapping(value = "/", method = RequestMethod.GET)
public #ResponseBody List<Entity> getEntities() {
List<Entity> found = controller.findEntities();
return found;
}
The serialized data are correct, as invoking the REST API in the browser produces correct JSON.
I also added the following CORS filter, which does NOT seem to be executed, as "AA" is not printed:
#Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
System.out.println("AA");
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");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() { }
}
My web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>simpleCORSFilter</filter-name>
<filter-class>org.lh.xxx.web.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>simpleCORSFilter</filter-name>
<servlet-name>/*</servlet-name>
</filter-mapping>
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
What's wrong with it?

The issue was strictly related to the filter not being executed: Spring Filter not getting invoked
When executing the filter, correct json is returned to the invoking client.

Related

Java filter doesn't work, when I tried to make request

I have this Cors filter:
public class SimpleCorsFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
System.out.println("here");
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");
chain.doFilter(req, res);
System.out.println("here2");
}
#Override
public void destroy() {
// TODO Auto-generated method stub
}
}
And it seems it doesnt work. HEre is my web.xml:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:app-context.xml</param-value>
</context-param>
<filter>
<filter-name>SimpleCORSFilter</filter-name>
<filter-class>org.heller.filter.SimpleCorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SimpleCORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
Can someone please give me a poit how to make this filter work? When I tried to request, there is no message ,,here" in console. I saw lot of tutorials, and code seems to be fine. It should be some mistake, which I dont see. Thank you for help.
My web.xml look like:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:app-context.xml</param-value>
</context-param>
<filter>
<filter-name>SimpleCORSFilter</filter-name>
<filter-class>org.heller.filter.SimpleCorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SimpleCORSFilter</filter-name>
<servlet-name>app</servlet-name>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
And now it runs! Thank you for help!
This is my filter :-
package com.test.test.apis.filter;
public class AuthenticationFilter implements Filter{
private FilterConfig filterConfig;;
private List<String> excludedApiUrls;
protected ServletContext servContext;
private static final String AUTHENTICATION_HEADER_KEY = "Authorization";
private static final String AUTHENTICATION_HEADER_VALUE_PREFIX = "Bearer "; // with trailing space to separate token
#Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
String excludePattern = filterConfig.getInitParameter("excludedUrls");
excludedApiUrls = Arrays.asList(excludePattern.split(","));
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {
if (filterConfig == null) return;
HttpServletRequest request = (HttpServletRequest) servletRequest;
if(!"OPTIONS".equalsIgnoreCase(request.getMethod())) {
// filter logic
}else {
filterChain.doFilter(request, servletResponse);
}
}
#Override
public void destroy() {
filterConfig = null;
}
}
CORS Configurration:-
package com.test.test.apis.filter;
public class CORSFilter implements ContainerResponseFilter {
#Override
public ContainerResponse filter(ContainerRequest request,ContainerResponse response) {
response.getHttpHeaders().add("Access-Control-Allow-Origin", "*");
response.getHttpHeaders().add("Access-Control-Allow-Headers","origin, content-type, accept, authorization");
response.getHttpHeaders().add("Access-Control-Allow-Credentials", "true");
response.getHttpHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
return response;
}
}
web.xml;-
<filter>
<filter-name>ApiFilter</filter-name>
<filter-class>com.test.test.apis.filter.AuthenticationFilter</filter-class>
<init-param>
<param-name>excludedUrls</param-name>
<param-value>/tb/login/doLogin</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>ApiFilter</filter-name>
<servlet-name>api-serlvet</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>api-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.test.test.apis.controllers</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.test.test.apis.filter.CORSFilter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>api-serlvet</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>

Preventing clickjacking attack

Currently, I'm working on a vaadin project where I'm working on preventing clickjacking attack on the project. After searching for the solution I've found that adding following snippet in web.xml would work:
<filter>
<filter-name>httpHeaderSecurity</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>antiClickJackingEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>antiClickJackingOption</param-name>
<param-value>SAMEORIGIN</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>httpHeaderSecurity</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I've added following dependency in pom.xml:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>9.0.2</version>
</dependency>
I'm running the project on payara server.
The project runs but throw the following error:
Caused by: java.lang.ClassNotFoundException:
org.apache.catalina.filters.HttpHeaderSecurityFilter not found by
org.glassfish.main.web.core [69] at
org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1532)
at
org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75)
at
org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at
org.apache.catalina.core.ApplicationFilterConfig.loadFilterClass(ApplicationFilterConfig.java:283)
at
org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:253)
at
org.apache.catalina.core.ApplicationFilterConfig.(ApplicationFilterConfig.java:123)
... 50 more
Which means my solution for preventing clickjacking attack won't work :)
Any help will be appreciated :).
I've solved this in the following way using web.xml:
First created the following filter:
public class ClickjackingPreventionFilter implements Filter
{
private String mode = "DENY";
// Add X-FRAME-OPTIONS response header to tell any other browsers who not to display this //content in a frame.
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse)response;
res.addHeader("X-FRAME-OPTIONS", mode );
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig filterConfig) {
String configMode = filterConfig.getInitParameter("mode");
if ( configMode != null ) {
mode = configMode;
}
}
}
Then configured that into web.xml like the following:
<filter>
<filter-name>ClickjackPreventionFilterDeny</filter-name>
<filter-class>com.groupbuilder.preventclickjacking.ClickjackingPreventionFilter</filter-class>
<init-param>
<param-name>mode</param-name><param-value>DENY</param-value></init-param>
</filter>
<filter-mapping>
<filter-name>ClickjackPreventionFilterDeny</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

404 in Jersey/Struts application

I am trying to use Jersey to provide a simple web service for my struts application.
When I call the client action I get the following error
com.sun.jersey.api.client.UniformInterfaceException
Message: GET http://localhost:8080/shumer/rest/employee/get returned a response status of 404
servlet declaration in web.xml
<servlet>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>spring.autowire</param-name>
<param-value>byName</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Server resource
#Path("employee")
public class EmployeeResource {
#Autowired
EmpDao empDao;
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Employee> get(#QueryParam("empCode") String empCode) throws Exception {
EmpCriteria criteria = new EmpCriteria();
criteria.setEmpCode(empCode);
return empDao.searchByCondition(criteria);
}
}
Client action
public class EmployeeClientTestAction extends Action {
#Override
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
Client client = Client.create();
WebResource resource = client.resource("http://localhost:8080/shumer/rest/employee/get");
String employees= resource.accept(MediaType.APPLICATION_JSON)
.get(String.class);
System.out.println(employees);
request.setAttribute("employees", employees);
return mapping.findForward("successful");
}
}
I have tried this with and without the /get and the end of the resource url, and with and without a leading / in the EmployeeResource #Path annotation. My guess is that there is somewhere I have to declare where my resources are lcoated at in order for the Jersey servlet to handle them, but I can't figure it out. A point in the right direction would be much appreciated.
EDIT
I have added the following init-param to the servlet element and it is still not working (this package is where my resource class is)
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>shumer.rest.resource</param-value>
</init-param>
in get method write #Path("/get")

Not able to call Jersey service using jquery

I'm trying to connect to a Jersey service using JQuery. But, it's not getting connected to the service, because I'm checking the logs whether it has hit the service or not. Is there anything missing?
$('#update').click(function() {
alert("updating the labelll");
$.ajax({
url:"/updatecontent",
type: 'POST',
dataType:"json",
data:$( "#labels option:selected" ).text(),
async:false,
success:function(contentdata) { // Success Call Back Function.
if(contentdata == "1") {
alert("successfully updated");
} else {
alert("sorry.. failed in updating");
}
},
error:function(){ // Error Call back function.
alert("sorry.. failed in updating in Error call back");
}
});
});
Service
---------
#Path("/updatecontent")
public class updatecontent {
private static final org.slf4j.Logger LOGGER=org.slf4j.LoggerFactory.getLogger(updatecontent.class);
#Context
HttpServletRequest request;
#Context
HttpServletResponse response;
#POST
#Consumes(MediaType.APPLICATION_JSON)
public String updateStatus(String packet) throws JSONException {
// Get the object from the UI.
LOGGER.info("In the API class of updating content for review.");
return "1";
}
}
Web.xml
---------
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>net.my.services</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>6</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Am I missing anything here? There should be a minor issue. Any ideas would be greatly appreciated.
Your web.xml has an url-pattern of
<url-pattern>/rest/*</url-pattern>
So jQuery must connect to
/rest/updatecontent

Session Filter usage

I need to do a session filter. localhost:8080/Project/faces/index.xhtml is the login. If login is successful, the user will be redirected for app/conta.xhtml, but if user writes localhost:8080/Project/faces/app/conta.xhtml directly in address bar and not logged in must be redirected for index.xhtml again.
All pages that are in app/* must not be accessed without successful login.
My class LoginFilter is in the package filtro
#WebFilter("/app/*")
public class LoginFilter implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
// If you have any <init-param> in web.xml, then you could get them
// here by config.getInitParameter("name") and assign it as field.
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("idUsuario") == null) {
response.sendRedirect(request.getContextPath() + "../index.xhtml"); // No logged-in user found, so redirect to login page.
} else {
chain.doFilter(req, res); // Logged-in user found, so just continue request.
}
}
#Override
public void destroy() {
// If you have assigned any expensive resources as field of
// this Filter class, then you could clean/close them here.
}
}
My web.xml
<?xml version="1.0" encoding="UTF-8"?>
<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_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<filter>
<filter-name>Login Filter</filter-name>
<filter-class>filtro.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Login Filter</filter-name>
<url-pattern>/app/*</url-pattern>
</filter-mapping>
</web-app>
Despite all this, I can enter /faces/app/conta.xhtml and have normal access!
This is my code for Login Validation = validarLogin()
BeanUsuarios.java
#ManagedBean
#ViewScoped
public class BeanUsuarios {
private Usuario usuario;
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
#PostConstruct
public void BeanUsuario(){
if(getUsuario()==null){
usuario = new Usuario();
}
}
public void validarLogin(){
UsuarioJpaController cUsuario = new UsuarioJpaController();
cUsuario.getEntityManager().createNamedQuery("Usuario.findByLogin").setParameter("login", this.usuario.getLogin()).getSingleResult();
if(usuario != null){
if(usuario.getSenha().equals(this.usuario.getSenha())){
FacesContext fc = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);
session.setAttribute("idUsuario", this.usuario.getId());
try {
FacesContext.getCurrentInstance()
.getExternalContext()
.redirect("app/conta.xhtml");
} catch (IOException ex) {
Logger.getLogger(BeanUsuarios.class.getName()).log(Level.SEVERE, null, ex);
}
}else{
}
}
}
}
You have two options:
Change the filter URL mapping to /faces/app* since that's how you're accessing your pages.
In the web.xml file, get rid of the /faces/* servlet mapping and use *.xhtml instead. This would require to change your welcome file to index.xhtml only.
IMO I would use option 2 since I don't like the Faces Servlet process the non-JSF related requests as JavaScript, CSS and images files.

Categories

Resources