I want to add a client name parameter to my URL, so when i receive a link like :
http://localhost:8080/client1 i want to test if my client is present in database, if so i want that the client receive the content of my site like if he call :
http://localhost:8080/
I tried to do this with a wrapper like indicated here :
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ChangeURIPathFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(ChangeURIPathFilter.class);
RequestWrapper modifiedRequest = null;
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void destroy() {}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String contextPath = ((HttpServletRequest) request).getContextPath();
String requestURI = httpRequest.getRequestURI();
modifiedRequest = new RequestWrapper(httpRequest, "/");
chain.doFilter(modifiedRequest, response);
}
class RequestWrapper extends HttpServletRequestWrapper {
private String originalValue;
public RequestWrapper(HttpServletRequest request) {
super(request);
}
#Override
public String getRequestURI() {
String originalURI = super.getRequestURI();
String s = super.getRequestURI();
if (StringUtils.equals(s, originalValue)) return originalValue
.replaceAll("client1", "");
else return s;
}
public RequestWrapper(HttpServletRequest request, String newValue) {
super(request);
this.originalValue = request.getRequestURI();
}
}
}
But all my tests failed. Can any one help me to resolve this ?
Thanks
Related
Is there a way to add a filter/interceptor to static resources served from META-INF/resources?
I seem have tried all the possible options: #ServerResponseFilter, ContainerResponseFilter,WriterInterceptor however all these functions are called only for #Path or #Route...
Is there anything similar to #RouteFilter but for response?
Those are the only ones available:
public interface ClientRequestFilter {
void filter(ClientRequestContext requestContext) throws IOException;
}
public interface ClientResponseFilter {
void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) throws IOException;
}
public interface ContainerRequestFilter {
void filter(ContainerRequestContext requestContext) throws IOException;
}
public interface ContainerResponseFilter {
void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException;
}
public interface ReaderInterceptor {
Object aroundReadFrom(ReaderInterceptorContext context)
throws java.io.IOException, javax.ws.rs.WebApplicationException;
}
public interface WriterInterceptor {
void aroundWriteTo(WriterInterceptorContext context)
throws java.io.IOException, javax.ws.rs.WebApplicationException;
}
You could try with ClientResponseFilter and see:
In the Client API, a ClientRequestFilter is executed as part of the
invocation pipeline, before the HTTP request is delivered to the
network.
ClientResponseFilter is executed upon receiving a server response,
before control is returned to the application.
https://quarkus.io/specs/jaxrs/2.1/index.html#filters_and_interceptors
There seem to be nothing built-in to modify the response of a static content for now but nothing stops you from serving content in a dynamic way:
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
#Path("/")
#Produces(MediaType.TEXT_HTML)
public class FrontendController {
#GET
public Response index() throws IOException {
try (var index = getClass().getResourceAsStream(FrontendConstants.INDEX_RESOURCE)) {
if (index == null) {
throw new IOException("index.html file does not exist");
}
//modify index
return Response
.ok(index)
.cacheControl(FrontendConstants.NO_CACHE)
.build();
}
}
#GET
#Path("/{fileName:.+}")
public Response staticFile(#PathParam("fileName") String fileName) throws IOException {
try (var file = FrontendController.class.getResourceAsStream(FrontendConstants.FRONTEND_DIR + "/" + fileName)) {
if (file == null) {
return index();
}
var contentType = URLConnection.guessContentTypeFromStream(file);
return Response
.ok(
new String(file.readAllBytes(), StandardCharsets.UTF_8),
contentType == null ? MediaType.TEXT_PLAIN : contentType
)
.cacheControl(FrontendConstants.NO_CACHE)
.build();
}
}
}
How to access request headers in implementation of WriterInterceptor interface in JAX-RS?
context.getHeaders(); //This line gives a set of response headers(not request headers) in the WriterInterceptor implementation.
Complete code below:
public class GzipFilterWriterInterceptor implements WriterInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(GzipFilterWriterInterceptor.class);
#Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
MultivaluedMap<String,Object> headers = context.getHeaders();
headers.add("Content-Encoding", "gzip");
final OutputStream outputStream = context.getOutputStream();
context.setOutputStream(new GZIPOutputStream(outputStream));
context.proceed();
}
}
You can just inject HttpHeaders. It will be a thread-local proxy when it's injected, so it's thread safe.
#Context
private HttpHeaders headers;
It has methods
String getHeaderString(String name)
List<String> getRequestHeader(String name)
MultivaluedMap<String,String> getRequestHeaders()
UPDATE (test)
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
import java.io.IOException;
import java.util.logging.Logger;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* Run like any other JUnit test. Only one required dependency:
*
* <dependency>
* <groupId>org.glassfish.jersey.test-framework.providers</groupId>
* <artifactId>jersey-test-framework-provider-inmemory</artifactId>
* <scope>test</scope>
* <version>${jersey.version}</version>
* </dependency>
*/
public class HeadersTest extends JerseyTest {
#Path("hello")
public static class HelloResource {
#GET
public String get() {
return "Hello";
}
}
#Override
public ResourceConfig configure() {
return new ResourceConfig(HelloResource.class)
.register(HeaderWriter.class)
.register(new LoggingFilter(Logger.getAnonymousLogger(), true));
}
#Provider
public static class HeaderWriter implements WriterInterceptor {
#Context
private HttpHeaders headers;
#Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
context.proceed();
final String header = headers.getHeaderString("X-Request-Header");
context.getHeaders().add("X-Response-Header", header);
}
}
#Test
public void doit() {
final Response response = target("hello").request()
.header("X-Request-Header", "BooYah")
.get();
assertThat(response.getHeaderString("X-Response-Header"), is("BooYah"));
}
}
You can implement below code to ,see working example at http://jerseyexample-ravikant.rhcloud.com/rest/jws/say/Hello
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
#Provider
public class SecurityInterceptor implements ContainerRequestFilter, ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext reqCtx, ContainerResponseContext respCtx) throws IOException {
long startTime=0;
System.out.println("Adding ProcessingTime in response headers");
if(reqCtx.getHeaderString("startTime")!=null)
startTime = Long.parseLong(reqCtx.getHeaderString("startTime"));
respCtx.getHeaders().add("ProcessingTime",
String.valueOf(System.currentTimeMillis() - startTime) + " millisecs");
}
#Override
public void filter(ContainerRequestContext reqCtx) throws IOException {
System.out.println("Adding start time in request headers");
reqCtx.getHeaders().add("startTime", String.valueOf(System.currentTimeMillis()));
}
}
#Provider
public class GzipFilterWriterInterceptor implements WriterInterceptor
{
private static final Logger LOG = LoggerFactory.getLogger(GzipFilterWriterInterceptor.class);
// use a context injection
#Context
private HttpHeaders httpHeaders;
#Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException
{
MultivaluedMap<String,Object> headers = context.getHeaders();
headers.add("Content-Encoding", "gzip");
// do stuff with headers
if ("Basic Ym9iOnBhc3N3b3Jk".equals(httpHeaders.getRequestHeader("Authorization").get(0)))
{
//do stuff here, but be careful about the indexoutofbounds...
}
final OutputStream outputStream = context.getOutputStream();
context.setOutputStream(new GZIPOutputStream(outputStream));
context.proceed();
}
}
The context injection will be injected per request, see the javadocs.
Probably not best solution, but you can have your interceptor implementing ReaderInterceptor. There you can get headers and save them in ThreadLocal variable so you can access then in WriterInterceptor
Also if you have annotation based configuration you can try to inject ContainerRequestContext with a #Context annotation
I am working with embedded Jetty and I want to add a servlet filter to check for authentication before each request. I tried following this example but it looks like the signature has changed.
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.0.4.v20130625</version>
</dependency>
My Jetty starter looks like this:
public class JettyStarter {
public static void main( final String[] args ) throws Exception {
Server server = new Server(8080);
final ServletHolder servletHolder = new ServletHolder(new CXFServlet());
final ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
// context.addFilter(AuthenticationFilter.class, "/*", FilterMapping.REQUEST);
context.addServlet(servletHolder, "/platform/*");
context.addEventListener(new ContextLoaderListener());
context.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
context.setInitParameter("contextConfigLocation", Config.class.getName());
server.setHandler(context);
server.start();
server.join();
}
}
When I uncomment the line
// context.addFilter(AuthenticationFilter.class, "/*", FilterMapping.REQUEST);
I find that the signature has changed. So I want to take a small step back and ask, with embedded Jetty, how do I add a filter that runs at the beginning of the request and allows the request to continue only if some condition is met?
The beginning of the AuthenticationFilter class looks like this:
import javax.servlet.*;
import java.io.IOException;
public class AuthenticationFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {}
#Override
public void destroy() {}
}
You are probably looking for EnumSet.of(DispatcherType.REQUEST), included a full example below:
import java.io.IOException;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
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.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
public class JettyFilter {
public static void main(final String[] args) throws Exception {
Server server = new Server(8080);
ServletHandler handler = new ServletHandler();
server.setHandler(handler);
handler.addServletWithMapping(HelloServlet.class, "/*");
handler.addFilterWithMapping(HelloPrintingFilter.class, "/*",
EnumSet.of(DispatcherType.REQUEST));
server.start();
server.join();
}
public static class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("<h1>Hello SimpleServlet</h1>");
}
}
public static class HelloPrintingFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.print("hello from filter");
}
#Override
public void init(FilterConfig arg0) throws ServletException {
}
#Override
public void destroy() {}
}
}
How can I add http header to soap webservice using netbeans and glassfish?
My webservice class:
package com.service;
import com.model.Contact;
import com.model.Phonebook;
import java.util.ArrayList;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
#WebService(serviceName = "PhonebookService")
public class PhonebookService {
private Phonebook phonebook = new Phonebook();
#WebMethod(operationName = "insert")
public String insert(#WebParam(name = "contact") Contact contact) {
phonebook.add(contact);
return contact.getName() + " inserted";
}
#WebMethod(operationName = "update")
public String update(#WebParam(name = "contact") Contact contact) {
phonebook.update(contact);
return contact.getName() + " updated";
}
#WebMethod(operationName = "remove")
public String remove(#WebParam(name = "contact") Contact contact) {
phonebook.remove(contact);
return contact.getName() + " removed";
}
#WebMethod(operationName = "list")
public ArrayList<Contact> list() {
return phonebook.list();
}
}
I would like to add "Access-Control-Allow-Origin: *" header
How can I do it?
Searching over internet for hours, I ended up coding the following code which allow to add extra http headers. I am using it with netbeans generated webservice and built-in glassfish 3 server
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.*;
#WebFilter(urlPatterns = { "/*" })
public class CrossOriginResourceSharingFilter implements Filter {
public CrossOriginResourceSharingFilter() { }
#Override
public void init(FilterConfig fConfig) throws ServletException { }
#Override
public void destroy() { }
#Override
public void doFilter(
ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
((HttpServletResponse)response).addHeader(
"Access-Control-Allow-Origin", "*"
);
((HttpServletResponse)response).addHeader(
"Access-Control-Allow-Headers", "Content-Type, Authorization, Accept"
);
((HttpServletResponse)response).addHeader(
"Access-Control-Allow-Methods", "GET, POST, OPTIONS"
);
chain.doFilter(request, response);
}
}
I am attempting to add BASIC authentication to my RESTful web-service. Currently I have BASIC authentication for an Apache Tomcat 6.0 server, but I need to deploy my web-service on a WebSphere application server ver. 6.1 as well and I am having problems getting BASIC authentication running on WebSphere.
Is there a way in Java to check the authentication headers of an HTTP request and if the username/password provided (in Base64 encoding) doesn't match a known account force the user to enter in a new username/password?
I have tried implementing Spring Security, but since my project was made entirely without Spring it has been a huge pain trying to get it to work, and I am attempting to find a simple solution to my rather simple problem.
Technologies that I am currently using include: Java, Jersey/JAX-RS, Eclipse with Maven plugin.
You should be able to setup a servlet filter which gets executed before your REST handlers, inspects the "Authorization" request header, base 64 decodes it, extracts the username and password, and verifies. Something like this:
public void doFilter(ServletRequest req,
ServletResponse res,
FilterChain chain) {
if (request instanceof HttpServletRequest) {
HttpServletRequest request = (HttpServletRequest) req;
String authHeader = Base64.decode(request.getHeader("Authorization"));
String creds[] = authHeader.split(":");
String username = creds[0], password = creds[1];
// Verify the credentials here...
if (authorized) {
chain.doFilter(req, res, chain);
} else {
// Respond 401 Authorization Required.
}
}
doFilter(req, res, chain);
}
All servlet containers have a standard way to configure filter chains.
Complete implementation based on maerics answer.
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;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import sun.misc.BASE64Decoder;
public class AuthenticationFilter implements Filter {
private static final String AUTHORIZATION_HEADER_NAME = "Authorization";
private static final String WWW_AUTHENTICATE_HEADER_NAME = "WWW-Authenticate";
private static final String WWW_AUTHENTICATE_HEADER_VALUE = "Basic realm=\"Default realm\"";
private static final String BASIC_AUTHENTICATION_REGEX = "Basic\\s";
private static final String EMPTY_STRING = "";
private static final String USERNAME_PASSWORD_SEPARATOR = ":";
private static final BASE64Decoder DECODER = new BASE64Decoder();
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpServletResponse httpRes = (HttpServletResponse) res;
String authHeader = httpReq.getHeader(AUTHORIZATION_HEADER_NAME);
if (authHeader == null) {
this.requestAuthentication(httpRes);
return;
}
authHeader = authHeader.replaceFirst(BASIC_AUTHENTICATION_REGEX, EMPTY_STRING);
authHeader = new String(DECODER.decodeBuffer(authHeader));
if (StringUtils.countMatches(authHeader, USERNAME_PASSWORD_SEPARATOR) != 1) {
this.requestAuthentication(httpRes);
return;
}
String[] creds = authHeader.split(USERNAME_PASSWORD_SEPARATOR);
String username = creds[0];
String password = creds[1];
//TODO: implement this method
if (!authenticatedUser(username, password)) {
this.requestAuthentication(httpRes);
return;
}
chain.doFilter(req, res);
}
private void requestAuthentication(HttpServletResponse httpRes) {
httpRes.setHeader(WWW_AUTHENTICATE_HEADER_NAME, WWW_AUTHENTICATE_HEADER_VALUE);
httpRes.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
public void destroy() {
}
}