I am using the latest version of GlassFish. I want to set the Access-Control-Allow-Origin header in response so that my API which is hosted on GlassFish can be called from any domain. But I am not able to find out where to set it.
In my case, the API requests are exclusively handled by Jersey, therefore I can set response headers in a ContainerResponseFilter:
package my.app;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;
public class CrossOriginResourceSharingFilter implements ContainerResponseFilter {
#Override
public ContainerResponse filter(ContainerRequest creq, ContainerResponse cresp) {
cresp.getHttpHeaders().putSingle("Access-Control-Allow-Origin", "*");
cresp.getHttpHeaders().putSingle("Access-Control-Allow-Credentials", "true");
cresp.getHttpHeaders().putSingle("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
cresp.getHttpHeaders().putSingle("Access-Control-Allow-Headers", "Content-Type, Accept");
return cresp;
}
}
The filter gets enabled in web.xml:
<servlet>
<servlet-name>Gateway Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>my.app.CrossOriginResourceSharingFilter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
If you don't use Jersey, I guess you can create a similar servlet response filter.
The best and easiest way of doing this, is right click on the project
and select Cross-Origin Resource Sharing Filter
Here is a Java EE standard way to do it. It's almost exactly the same as the Jersey example except for the library packages used (javax) and the method call to get the headers is different (getHeaders).
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
#Provider
public class RestResponseFilter implements ContainerResponseFilter{
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException{
responseContext.getHeaders().putSingle("Access-Control-Allow-Origin", "*");
responseContext.getHeaders().putSingle("Access-Control-Allow-Credentials", "true");
responseContext.getHeaders().putSingle("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
responseContext.getHeaders().putSingle("Access-Control-Allow-Headers", "Content-Type, Accept");
}
}
Since you use the tag java-ee-6, I believe #Provider isn't supported. I used the following code, based on the javaee6 tutorial:
import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
#WebFilter(filterName = "AddHeaderFilter", urlPatterns = {"/*"})
public class ResponseFilter implements Filter {
private final static Logger log = Logger.getLogger(ResponseFilter.class.getName() );
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (response instanceof HttpServletResponse) {
log.info("Adding headers");
HttpServletResponse http = (HttpServletResponse) response;
http.addHeader("Access-Control-Allow-Origin", "*");
http.addHeader("Access-Control-Allow-Credentials", "true");
http.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
}
chain.doFilter(request, response);
}
Related
Just as the title says, I need a help to get the local IP of the client in a quarkus resource ¿any idea?
I already try this but it dosen't work
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
#Path("/auth")
#RequestScoped
public class AuthResource {
#GET
#Path("/getIpAddres")
#Produces(MediaType.TEXT_PLAIN)
public String getIpAddres(#Context HttpServletRequest request){
String ip = request.getRemoteAddr();
return ip;
}
Pretty simple. Instead of using #Context HttpServletRequest request. do this instead:
#Path("/auth")
#RequestScoped
public class AuthResource {
#Inject
RoutingContext context;
#GET
#Path("/getIpAddres")
#Produces(MediaType.TEXT_PLAIN)
public String getIpAddres(){
String ip = context.request().host();
return ip;
}
I faced this problem myself. Cool thing about this RoutingContext is that this class can be injected into the Service layer, and it will have all the context of the ip, and other stuff, given that the Service was called by the Controller.
Hope this helps!
Just call the method remoteAddress()
#Path("/getIpAddres")
#Produces(MediaType.TEXT_PLAIN)
public String getIpAddres(#Context HttpServletRequest request){
String ip = request.remoteAddress().hostAddress();
return ip;
}
`
I would like to enable Facebook to crawl my website, however it needs user authentication. Facebook says one way to get around this is to whitelist their ips. I am using Apache Shiro and I know that you can get client's ip by calling getHost from BasicHttpAuthenticationFilter, however I do not know how to let certain ip addresses past the authentication.
You will likely have to build a custom implementation of Shrio's
org.apache.shiro.web.filter.authc.AuthenticatingFilter
Minimally, you will have to customize BasicHttpAuthenticationFilter by extending it and adding logic to skip the BasicHttpAuthenticationFilter if the request is coming from a whitelisted IP address.
package com.acme.web.filter.authc;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class WhitelistedBasicHttpAuthenticationFilter extends BasicHttpAuthenticationFilter {
private Set<String> whitelist = Collections.emptySet();
public void setWhitelist(String list) {
whitelist = new HashSet<String>();
Collections.addAll(whitelist, list.split(",")); //make sure there are no spaces in the string!!!!
}
#Override
protected boolean isEnabled (ServletRequest request, ServletResponse response) throws ServletException, IOException
{
if (whitelist.contains(request.getRemoteAddr())) {
return false;
}
return super.isEnabled(request, response);
}
}
In your 'shiro.ini'
authc=com.acme.web.filter.authc.WhitelistedBasicHttpAuthenticationFilter
authc.whitelist=192.168.1.1,192.168.1.2,192.168.2.3
We have a situation where we want to use filter for URL's containing some specific request parameters, e.g:
http://mydomain.com/?id=78&formtype=simple_form&.......
http://mydomain.com/?id=788&formtype=special_form&.......
and so on, id are fetched at run time, I want configure filter in web.xml only if formtype=special_form. How should achieve the solution? Can Filter be configured with regex patterns?
As far as I know there is no solution for matching requests to filters by query string directly in web.xml. So you could register the filter in your web.xml using init-params to make the filter configurable and set a pattern via void init(FilterConfig filterConfig) in your javax.servlet.Filter implementation.
package mypackage;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class MyFilter implements Filter {
private String pattern;
#Override
public void destroy() {
// TODO Auto-generated method stub
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// check whether we have a httpServletRequest and a pattern
if (this.pattern != null && request instanceof HttpServletRequest) {
// resolve the query string from the httpServletRequest
String queryString = ((HttpServletRequest) request).getQueryString();
// check whether a query string exists and matches the given pattern
if (queryString != null && queryString.matches(pattern)) {
// TODO do someting special
}
}
chain.doFilter(request, response);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
this.pattern = filterConfig.getInitParameter("pattern");
}
}
The configuration would look like this in your web.xml:
<!-- MyFilter -->
<filter>
<filter-name>myFilter</filter-name>
<filter-class>mypackage.MyFilter</filter-class>
<init-param>
<param-name>pattern</param-name>
<param-value>{{PATTERN HERE}}</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Further readings:
http://java.sun.com/javaee/5/docs/api/javax/servlet/Filter.html
You must parse the URL params in the body of the filter, not in web.xml;
I made such a thing, but I used a phase listener, a configuration entry (in a configuration file) that mapped URL params to FQN of classes that handle a particular "action" (by action I mean a URL param from a GET/POST); than, the phase listener would parse all the URL params from each GET/POST and send each of them to a Dispatcher. The Dispatcher's job is to call the right handler (singleton object corresponding to the FQN for that URL param). The handler then just does the specific thing with the URL value he receives.
The same thing can be made by using a filter instead of phase listener.
I am working in JAVA EE7, JAX-RS 2.0 Glassfish 4 is my SERVER.
I Want to work on CORS to enable Ajax Requests comming out of my domain.
I know that I need to make my server enabling it. And I did it in PHP. like the following code:
<?php header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Authorization");
but when I tried to do the same thing I always get an error message like that
"this is a screenshot".
So I've tried to modify the sever http response with many ways...
And this is my code , server side , I used a filer/provider:
#Provider
#CORSBinding
public class Filter implements ContainerRequestFilter{
#Override
public void filter(ContainerRequestContext request) throws IOException {
request.getHeaders().add("Access-Control-Allow-Origin", "*");
request.getHeaders().add("Access-Control-Allow-Headers", "Authorization");
if (request.getMethod().equals("OPTIONS")) {
System.out.println("OPTIONS is requested!!!!!!!!!!!!!");
}
if (request.getMethod().equals("GET")) {
System.out.println("GET is requested!!!!!!!!!!!!!");
}
if (request.getMethod().equals("POST")) {
System.out.println("POST is requested!!!!!!!!!!!!!");
}
if (request.getMethod().equals("DELETE")) {
System.out.println("DELETE is requested!!!!!!!!!!!!!");
}
if (request.getMethod().equals("PUT")) {
System.out.println("PUT is requested!!!!!!!!!!!!!");
}
}
}
But it seems like all blocked by a "firewall security" provided by Glassfish4 server.
here is my simple code javascript:
<script>
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://127.0.0.1:8080/CV/api/v2/posts");
xhr.setRequestHeader('Authorization', 'a');
xhr.send();
</script>
I even added an other filter using the #Prematching annotation to update the request from OPTIONS TO POST ... but I always lose my headers that I have sent within it (I mean within POST request).
#Provider
#PreMatching
public class HttpMethodOverrideEnabler implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
containerRequestContext.setMethod("POST");
containerRequestContext.getHeaders().add("Access-Control-Allow-Origin", "*");
containerRequestContext.getHeaders().add("Access-Control-Allow-Headers","Authorization");
containerRequestContext.getHeaders().add("Access-Control-Allow-Headers","Authorization");
String override = containerRequestContext.getHeaders().getFirst( "X-HTTP-Method-Override");
if (override != null) {
containerRequestContext.setMethod(override);
}
}
I knew that Glassfish3 had not the support for CORS and ("https://java.net/jira/browse/GLASSFISH-16049) they said that they will fix it with JEE7.
This is the whole story...
so how can I do the CORS with this JEE7 using Glassfish server and JAX-RS2.
Thanks in advance.
Use ContainerResponseFilter not ContainerRequestFilter as you want to add those headers into response and not to the request. For example:
#Provider
#Priority(Priorities.HEADER_DECORATOR)
public class AccessControlResponseFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
final MultivaluedMap<String,Object> headers = responseContext.getHeaders();
headers.add("Access-Control-Allow-Origin", "*");
headers.add("Access-Control-Allow-Headers", "Authorization, Origin, X-Requested-With, Content-Type");
headers.add("Access-Control-Expose-Headers", "Location, Content-Disposition");
headers.add("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, HEAD, OPTIONS");
}
}
You have to use the 2 *filters* the First because Chrome and other Browsers modify the headers for security purpose, and the second is to add the headers to response. So use ContainerResponseFilter and ContainerRequestFilter. it works fine with me Good luck!
I am new to struts and spring security.
Can anyone help me to figure out how to redirect to different urls different users with different roles ? In other words, how to provide determine target url based on user role in struts2 using action controller?
I found the following question determine target url based on roles in spring security 3.1 , but I cannot figure out how to configure the action.
I tried the following setup, but it does not work:
security.xml
<form-login login-page="/login" authentication-failure-url="/login?error=true" login-processing-url="/j_security_check" default-target-url="/default"/>
struts.xml
<action name="default" class="com.moblab.webapp.action.RoleRedirectAction" method="defaultAfterLogin"/>
RoleRedirectAction.java
package com.moblab.webapp.action;
import javax.servlet.http.HttpServletRequest;
public class RoleRedirectAction extends BaseAction{
public String defaultAfterLogin(HttpServletRequest request) {
if (request.isUserInRole("ROLE_ADMIN")) {
return "redirect:/<url>";
}
return "redirect:/<url>";
}
}
Thanks a lot.
EDIT 1
I also tried the following annotation
#Action(value="/default",results={#Result(name="success",location="/querySessions")})
EDIT 2
My final solution looks like the following. I am not sure if it is the best approach, but it works:
public class StartPageRouter extends SimpleUrlAuthenticationSuccessHandler {
#Autowired
private UserService userService;
protected final Logger logger = Logger.getLogger(this.getClass());
private RequestCache requestCache = new HttpSessionRequestCache();
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
//default path for ROLE_USER
String redirectPath = <url>;
if (authorities != null && !authorities.isEmpty()) {
Set<String> roles = getUserRoles(authorities);
if (roles.contains("ROLE_ADMIN"))
redirectPath = <url>;
else if (roles.contains("ROLE_INSTRUCTOR"))
redirectPath = <url>;
}
getRedirectStrategy().sendRedirect(request, response, redirectPath);
}
public void setRequestCache(RequestCache requestCache) {
this.requestCache = requestCache;
}
private Set<String> getUserRoles(Collection<? extends GrantedAuthority> authorities) {
Set<String> userRoles = new HashSet<String>();
for (GrantedAuthority authority : authorities) {
userRoles.add(authority.getAuthority());
}
return userRoles;
}
}
EDIT 3
There are even better solutions here:
http://oajamfibia.wordpress.com/2011/07/07/role-based-login-redirect/#comment-12
Assuming that you mean that you want to redirect users to different start pages depending on their assigned roles then you can try this. Note that I do all this outside of Struts.
First create your own class that extends Springs SimpleUrlAuthenticationSuccessHandler and override the onAuthenticationSuccess() method. The actual redirect is performed within the onAuthenticationSuccess() method by the line getRedirectStrategy().sendRedirect(request,response,);
So all you need is a means of substituting your own url's.
So, for example I have
package com.blackbox.x.web.security;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import com.blackbox.x.entities.UserDTO;
import com.blackbox.x.services.UserService;
public class StartPageRouter extends SimpleUrlAuthenticationSuccessHandler {
#Autowired
UserService userService;
#Autowired
LoginRouter router;
protected final Logger logger = Logger.getLogger(this.getClass());
private RequestCache requestCache = new HttpSessionRequestCache();
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication) throws IOException,
ServletException {
requestCache.removeRequest(request, response);
User user = (User) authentication.getPrincipal();
UserDTO userDTO = userService.find(user.getUsername());
getRedirectStrategy().sendRedirect(request, response, router.route(userDTO));
}
public void setRequestCache(RequestCache requestCache) {
this.requestCache = requestCache;
}
}
where LoginRouter is my own class that takes the logged in user and, from the assigned roles determines which URL the user should be directed to.
You then configure Spring Security to use your version using the
authentication-success-handler-ref="customTargetUrlResolver"/>
and
<beans:bean id="customTargetUrlResolver" class="com.blackbox.x.web.security.StartPageRouter"/>
in your security context xml file.