Execute jsp in Spring controller and get response html - java

How can I execute a JSP in controller and get html response in Sring variable without using HtmlServletRequestWrapper
following is my code, i am trying to hit jsp get response html str and pass that html string to itext to generate pdf.
#RequestMapping(value = "/dosomething", method = RequestMethod.GET)
public void dosomething(HttpServletRequest request, HttpServletResponse response) throws IOException {
// setup your Cookie here
response.setCookie(cookie)
request.getRequestDispatcher("/WEB-INF/jsp/account_summary.jsp").include(request, response)
}

Edit:
I ended up writing this bean (using HtmlServlet*Response*Wrapper :-)), I hope it could be useful for someone
(thanks to: Reading ServletOutputStream to String)
(The viewResolver is autowired so it needs to be defined inside the the servlet context)
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
public class InternalRenderer {
private final static String ENCODE = "UTF-8";
#Autowired
private ViewResolver viewResolver;
public String evalView(HttpServletRequest request, HttpServletResponse response, Model model, Locale locale, String viewName) throws Exception {
CustomHttpServletResponse customResponse = new CustomHttpServletResponse(response);
View view = viewResolver.resolveViewName(viewName, locale);
if(view != null){
view.render(fillModelMap(model), request, customResponse);
OutputStream os = customResponse.getOutputStream();
return os.toString();
}
throw new Exception("no view found");
}
private Map<String, Object> fillModelMap(Model model) {
if(model == null)
return new HashMap<String,Object>();
return model.asMap();
}
class CustomServletOutPutStream extends ServletOutputStream {
private StringBuilder stringBuilder = new StringBuilder();
#Override
public String toString() {
return stringBuilder.toString();
}
#Override
public void write(int b) {
stringBuilder.append(b);
}
#Override
public void write(byte b[], int off, int len) throws IOException {
stringBuilder.append(new String(b, off, len, ENCODE));
}
}
class CustomHttpServletResponse extends HttpServletResponseWrapper {
private ServletOutputStream outputStream;
private PrintWriter printWriter;
public CustomHttpServletResponse(HttpServletResponse response) throws UnsupportedEncodingException {
super(response);
this.outputStream = new CustomServletOutPutStream();
this.printWriter = new PrintWriter(new OutputStreamWriter(outputStream, ENCODE));
}
#Override
public ServletOutputStream getOutputStream() {
return this.outputStream;
}
#Override
public PrintWriter getWriter() throws IOException {
return this.printWriter;
}
}
}
and you can call it like
#Autowired
InternalRenderer internalRenderer;
#RequestMapping(value = "/internalRender")
public void internalRender(HttpServletRequest request, HttpServletResponse response, Model model, Locale locale) throws Exception {
String evalView = internalRenderer.evalView(request, response, model, locale, "index");
logger.debug("evalView: " + evalView);
//TODO: use the generated code to create the pdf and return it
}
old response:
You could call /doSomething, getting back the generated html and pass it to another controller as a parameter to make it create the pdf and get it back as a final result (if it is strictly necessary generate the pdf from the html, maybe it's better to generate the pdf using the raw data)
call /doSomething (using ajax?)
get the generated html back
call /createPdf passing the generated html as a paramter
get the generated pdf back

I found a simpler way
1 just add dependency
testCompile group: 'org.springframework', name: 'spring-mock', version: '2.0.8'
2 and then use
View resolvedView = this.viewResolver.resolveViewName("viewname", locale);
MockHttpServletResponse mockResp = new MockHttpServletResponse();
resolvedView.render(model, request, mockResp);
System.out.println("rendered html : " + mockResp.getContentAsString());

Related

Why does RestTemplate not urlencode the '+' symbol but urlencodes everything else?

I've found a strange problem where the urlencoding behaves inconsistently.
UPDATE
There are differences between Spring MVC versions 4.3 and 5.1:
// FAIL in MVC 4.x
#Test
public void test2() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x/y");
Assert.assertEquals("http://localhost/expr=x%2Fy", savedUri.toString());
}
// FAIL in MVC 4 or 5
#Test
public void test3() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x+y");
Assert.assertEquals("http://localhost/expr=x%2By", savedUri.toString());
}
// ok in MVC 4.x, FAIL in MVC 5
#Test
public void test4() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x+y");
Assert.assertEquals("http://localhost/expr=x+y", savedUri.toString());
}
This may have been part of a larger ref*ctoring of Spring MVC, as it also manifests in a totally different place here
Question Details
My question is best illustrated by the following self-contained test. Don't be intimidated by the ClientHttpRequestFactory - the important part are the last 2 test methods.
package com.stackoverflow.questions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URI;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.io.output.WriterOutputStream;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;
public class RestTemplateTest {
StringWriter stringWriter = new StringWriter();
WriterOutputStream writerOutputStream = new WriterOutputStream(stringWriter);
HttpHeaders headers = new HttpHeaders();
URI savedUri;
ClientHttpRequestFactory rf = new ClientHttpRequestFactory() {
#Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
savedUri = uri;
return new ClientHttpRequest() {
#Override
public OutputStream getBody() throws IOException {
return writerOutputStream;
}
#Override
public HttpHeaders getHeaders() {
return headers;
}
#Override
public URI getURI() {
return uri;
}
#Override
public String getMethodValue() {
return httpMethod.name();
}
#Override
public ClientHttpResponse execute() throws IOException {
writerOutputStream.close();
return new ClientHttpResponse() {
#Override
public HttpHeaders getHeaders() {
return new HttpHeaders();
}
#Override
public InputStream getBody() throws IOException {
return new ReaderInputStream(new StringReader("test"));
}
#Override
public String getStatusText() throws IOException {
return "OK";
}
#Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
#Override
public int getRawStatusCode() throws IOException {
return 200;
}
#Override
public void close() {
}
};
}
};
}
};
RestTemplate rt = new RestTemplate(rf);
#Test
public void test1() {
String resp = rt.getForObject("http://whatever", String.class);
Assert.assertEquals("test", resp);
}
#Test
public void test2() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x/y");
Assert.assertEquals("http://localhost/expr=x%2Fy", savedUri.toString());
}
#Test
public void test3() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x+y");
Assert.assertEquals("http://localhost/expr=x%2By", savedUri.toString());
}
}
What's happening:
division symbol / is properly encoded to a %2F - test2() passes
addition symbol + is NOT encoded to a %2B - it remains + and test3() fails
What should happen:
test3() should pass. The + should be encoded to %2B because + is a special character in URLs and is interpreted as a white space by many server-side web frameworks.
What is going on here and is there a generic fix?
There's uncertainty whether + should be encoded or not. Older RFCs say yes, newer ones say maybe.
Try setting the encoding mode as follows:
DefaultUriBuilderFactory builderFactory = new DefaultUriBuilderFactory();
builderFactory.setEncodingMode(EncodingMode.VALUES_ONLY);
restTemplate.setUriTemplateHandler(builderFactory);
See SPR-19394 and SPR-20750 for discussion.

Cannot properly read reqest body in interceptor - Spring BOOT 2.0.4

I have a problem with reading request body in interceptor. Both getReader() and getInputStream() causing problems.
My interceptor:
public class MyInterceptor extends HandlerInterceptorAdapter {
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)
throws Exception {
// TODO Auto-generated method stub
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
// TODO Auto-generated method stub
}
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestBody = httpRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
//or
// String requestBody = new BufferedReader(new InputStreamReader(httpRequest.getInputStream()))
// .lines().collect(Collectors.joining("\n"));
//some logic...
return true;
}
Both approaches failing because probably spring uses such resource somewhere internally.
First causess java.lang.IllegalStateException: getReader() has already been called for this request and other Required request body is missing: org.springframework.http.ResponseEntity...
I have tried some workarounds with wrappers without an effect. I think its because I cannot pass wrapper down like in filters(i dont want to use filter cause I have common exception managager(#ControllerAdvice).
Is this a known issue? Is there any workaround for this?
Finally I have figured it out so I will leave here some simple but useful advice for others.
I have used a request wrapper but to make it work properly I have added a filter with highest order to wrap every request into wrapper at the beginning, before interceptor is executed. Now it works well ;)
Here's most important code - filter to wrap every request into multi read wrapper(interceptor looks almost the same as above and wrapper is not invented by me, found on stack and I found it as most clear and readable):
import lombok.SneakyThrows;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalWrapFilter implements Filter {
#Override
#SneakyThrows
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
MultiReadRequest wrapper = new MultiReadRequest((HttpServletRequest) request);
chain.doFilter(wrapper, response);
}
#Override
public void destroy() {
}
class MultiReadRequest extends HttpServletRequestWrapper {
private String requestBody;
#SneakyThrows
public MultiReadRequest(HttpServletRequest request) {
super(request);
requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody.getBytes());
return new ServletInputStream() {
#Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
#Override
public boolean isReady() {
return true;
}
#Override
public void setReadListener(ReadListener readListener) {
}
#Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
#Override
#SneakyThrows
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream(), StandardCharsets.UTF_8));
}
}
}

request.getRequestURI always returns "/error"

In a webapp I'm building using Spring Boot & MVC and am trying to deny access to for all URL's except /signin for users that are not logged in. To achieve this I've setup an implementation of HandlerInterceptor where the preHandler should route all non-valid requests to the /signin page.
The setup:
LoginViewController
package com.controller;
import com.model.UserDao;
import com.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
#Controller
#RequestMapping(value = "/signin")
#SessionAttributes("username")
public class LoginViewController {
#Autowired
private UserService userService;
#RequestMapping(method = RequestMethod.GET)
public ModelAndView showLoginForm(){
return new ModelAndView("login");
}
#RequestMapping(method = RequestMethod.POST)
public ModelAndView verifyLogin(HttpServletRequest request, HttpSession session) {
ModelAndView modelAndView;
String username = request.getParameter("username");
// if login fails, set reload login page
if (userService.verifyUserLogin(username,request.getParameter("password")) == null){
modelAndView = new ModelAndView("login");
modelAndView.addObject("login_failed", true);
} else {
modelAndView = new ModelAndView("index");
session.setAttribute("username", username);
}
return modelAndView;
}
}
AccessInterceptor
package com.spring.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import java.util.ArrayList;
public class AccessInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println(request.getRequestURI());
try {
if (!request.getRequestURI().endsWith("/signin")) {
if (request.getSession()
.getAttribute("username") == null) {
response.sendRedirect(request.getContextPath() + "/signin");
return false;
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return true;
}
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("Post-handle");
}
#Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("After completion handle");
}
}
WebApplicationConfig
package com.spring;
import com.spring.interceptor.AccessInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
#Configuration
#EnableWebMvc
public class WebApplicationConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(
new AccessInterceptor()).
addPathPatterns("/**").
excludePathPatterns("/signin/**").
excludePathPatterns("/static/**");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
WebApplicationInitializer
package com.spring;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
public class MyWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(WebApplicationConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext =
new AnnotationConfigWebApplicationContext();
dispatcherContext.register(MyWebAppInitializer.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcherServlet", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
dispatcher.addMapping("*.css");
dispatcher.addMapping("*.eot");
dispatcher.addMapping("*.svg");
dispatcher.addMapping("*.ttf");
dispatcher.addMapping("*.woff");
dispatcher.addMapping("*.map");
dispatcher.addMapping("*.js");
dispatcher.addMapping("*.ico");
}
}
Now the problem is that the System.out.println(request.getRequestURI()) in AccessInterceptor always prints /error. So the request is always redirected even when calling /signin. Another interesting thing is that no CSS or other static resources are rendered, even with the dispacher mapping configured.
Any Ideas?
if you missing your payload, the api url couldn't recognize. at least put something
I also met this problem,in WebLogIntercept(your MyWebAppInitializer) class
I solved this problem using the following code
add this two func
private Class getClassByName(Class classObject, String name){
Map<Class,List<Field>> fieldMap = new HashMap<>();
Class returnClass = null;
Class tempClass = classObject;
while (tempClass != null) {
fieldMap.put(tempClass,Arrays.asList(tempClass .getDeclaredFields()));
tempClass = tempClass.getSuperclass();
}
for(Map.Entry<Class,List<Field>> entry: fieldMap.entrySet()){
for (Field f : entry.getValue()) {
if(f.getName().equals(name)){
returnClass = entry.getKey();
break;
}
}
}
return returnClass;
}
private Object findCoyoteRequest(Object request) throws Exception {
Class a = getClassByName(request.getClass(),"request");
Field request1 = a.getDeclaredField("request");
request1.setAccessible(true);
Object b = request1.get(request);
if(getClassByName(b.getClass(),"coyoteRequest") == null){
return findCoyoteRequest(b);
}else{
return b;
}
and use this code
Object a = findCoyoteRequest(request);
Field coyoteRequest = a.getClass().getDeclaredField("coyoteRequest");
coyoteRequest.setAccessible(true);
Object b = coyoteRequest.get(a);
Field uriMB = b.getClass().getDeclaredField("uriMB");
uriMB.setAccessible(true);
MessageBytes c = (MessageBytes)uriMB.get(b);
System.out.println(c.getString());
c.getString() is realuri
my english is not good,Hope useful
Disabling CFR worked for me
See https://www.baeldung.com/spring-security-csrf
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
I have the same function to implement as you. And I finally found that there was nothing wrong with this function. The "/error" request actually exists, maybe sent by the servlet container or whatever(i don't know). It exists to show you the exception on the browser.
When I put "/error" to my white-list(I also put paths like "/login" which don't need the authority), the e.printStackTrace(); information just show on the browser.
sometimes,you can try rebuild project,here is my code:
if(request.getRequestURI().startsWith("/user/")) {return true;}
it always return "/error"

To send get request to Web API from Java Servlet

Common question
Is is possible to send get reguest from Java servlet's doGet method ? I need to check some "ticket" against my Web API .NET service, so can I call to this service from my custom servlet in the doGet method ?
public class IdentityProviderServlet extends HttpServlet {
...
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
...
// make request to Web API and save received user name to response
...
}
Details
We have web-app (.NET, MVC5) that is used TIBCO Spotfire 7.0 as engine of analysis reports.
To allow our users to see reports inside web-app we use Spotfire WebPlayer (IIS web app) and JavaScript API. We authenticate our users in web app and then they are allowed to get request to WebPlayer leveraging JS API. In order to use already authenticated users we implemented custom authentication at WebPlayer based on keys-tickets as described here. Thus we created .NET assembly that is loaded by Spotfire WebPlayer and calls overridden function. In this function we call Web API service to validate user and get valid spotfire username, then I create IIdentity with received username.
When new version of TIBCO Spotfire 7.5 released we discovered that they removed support of custom authentication, because they changed architecture and now they support "external authentication". This approach could be implemented as as Java servlet that is used to authenticate user and then spotfire:
Retrieves the user name from the getUserPrincipal() method of
javax.servlet.http.HttpServletRequest
All this forced us to re-write our logic in Java. However we don't want to change overall workflow of our authentication and we want to stick to already working ticketing schema. I'm new to Java servlets, so my goal to implement the same authentication based on servlet. They have example where servlet class has methods doGet and doPost (link to zip with example). My assumption here that I can implement my own doGet and send request to Web API to validate ticket and get back username.
Does it make sense ?
Finally I end up with this code. I implemented simple filter instead of servlet.
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import java.io.*;
import org.json.*;
public class Authenticator implements IAuthenticator {
#Override
public IIdentity doAuthentication(String pathToAuthIdentity) throws IOException {
try {
// Create an instance of HttpClient.
HttpClient httpClient = HttpClients.createDefault();
// Create a method instance.
HttpGet get = new HttpGet(pathToAuthIdentity);
HttpResponse response = httpClient.execute(get);
int internResponseStatus = response.getStatusLine().getStatusCode();
if(200 == internResponseStatus)
{
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
String userName = null;
try {
JSONObject obj = new JSONObject(result.toString());
userName = obj.getString("SpotfireUser");
} catch (JSONException ex) {
}
return new Identity(userName);
}else
{
return new AIdentity(null);
}
} catch (IOException ex) {
throw ex;
}
}
public class AIdentity implements IIdentity
{
private final String UserName;
public AIdentity(String userName)
{
this.UserName = userName;
}
#Override
public String getName() {
return UserName;
}
}
}
And that's how I use this class
import java.io.IOException;
import java.security.Principal;
import javax.servlet.http.*;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class SpotfireAuthFilter implements Filter {
private static final String AUTHENTICATION_SERVICE_URL_PARAM = "AUTHENTICATION_SERVICE_URL";
private static final String COOKIE_NAME_PARAM = "COOKIE_NAME";
private ServletContext context;
private String[] SpotfireTicketNames = null;
private String[] AuthServiceBaseURLs = null;
private IAuthenticator AuthService;
#Override
public void init(FilterConfig fc) throws ServletException {
context = fc.getServletContext();
if(null == fc.getInitParameter(AUTHENTICATION_SERVICE_URL_PARAM)
|| null == fc.getInitParameter(COOKIE_NAME_PARAM) )
{
throw new ServletException("Can't read filter initial parameters");
}
AuthServiceBaseURLs = fc.getInitParameter(AUTHENTICATION_SERVICE_URL_PARAM).split(",");
SpotfireTicketNames = fc.getInitParameter(COOKIE_NAME_PARAM).split(",");
AuthService = new Authenticator();
if(SpotfireTicketNames.length != AuthServiceBaseURLs.length)
{
throw new ServletException(
String.format("Count of '%s' parameter don't equal '%s' parameter",
COOKIE_NAME_PARAM,
AUTHENTICATION_SERVICE_URL_PARAM));
}
}
#Override
public final void doFilter(
ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain chain) throws ServletException
{
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
try
{
doFilter(request, response, chain);
}
catch (IOException | RuntimeException e)
{
// Not possible to authenticate, return a 401 Unauthorized status code without any WWW-Authenticate header
sendError(response, 401, "Unauthorized");
}
}
#Override
public void destroy() {
// do nothing
}
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException
{
String url = getAuthServiceURL(request);
if(null != url)
{
IIdentity identity = AuthService.doAuthentication(url);
if(null != identity)
{
String userName = identity.getName();
if(null != userName && !userName.equalsIgnoreCase(""))
{
Principal principal = createPrincipal(userName);
// Pass on the request to the filter chain and the authentication framework
// should pick up this priincipal and authenticate user
chain.doFilter(new WrappedHttpServletRequest(request, principal), response);
}
else
{
throw new IOException("Authentication failed");
}
}else
{
throw new IOException("Can't authenticate user by url " + url);
}
}
else
{
throw new IOException("Can't find ticket to authenticate user.");
}
// Done!
return;
}
private void sendError(HttpServletResponse response, int statusCode, String message) {
try {
response.sendError(statusCode, message);
} catch (IOException e) {
}
}
private String getAuthServiceURL(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
for(int i =0; i< cookies.length; ++i)
{
for(int j =0; j< SpotfireTicketNames.length; ++j)
{
if(cookies[i].getName().equalsIgnoreCase(SpotfireTicketNames[j]))
{
return String.format(AuthServiceBaseURLs[j], cookies[i].getValue());
}
}
}
return null;
}
private Principal createPrincipal(String username)
{
// check does username contain domain/email/display name
return new APrincipal(username);
}
/**
* A wrapper for {#link HttpServletRequest} objects.
*/
private static class WrappedHttpServletRequest extends HttpServletRequestWrapper {
private final Principal principal;
public WrappedHttpServletRequest(HttpServletRequest request, Principal principal) {
super(request);
this.principal = principal;
}
#Override
public Principal getUserPrincipal() {
return this.principal;
}
} // WrappedHttpServletRequest
}
public class APrincipal implements Principal {
private final String _username;
public APrincipal(String username) {
_username = username;
}
#Override
public String getName() {
return _username;
}
}
And these initial parameters
You can use the library Apache HTTP Components
Short example for doGet() (I didn't compile it):
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
{
String url="http://your.server.com/path/to/app?par1=yxc&par2=abc");
HttpGet get=new HttpGet(url);
httpClient = HttpClients.createDefault();
// optional configuration
RequestConfig config=RequestConfig.custom().setSocketTimeout(socketTimeoutSec * 1000).build();
// more configuration
get.setConfig(config);
CloseableHttpResponse internResponse = httpClient.execute(get);
int internResponseStatus = internResponse.getStatusLine().getStatusCode();
InputStream respIn = internResponseEntity.getContent();
String contentType = internResponseEntity.getContentType().getValue();
// consume the response
}

Java servlet: How to remove header "referer" on redirect?

Is it possible remove header Referer when you execute redirect on java servlet?
kind of
response.setHeader("Referer", null);
response.sendRedirect(url)
Also I tried filter. It even doesnt call setHeader or addHeader methods on response. It looks like i cannot change existing filters. Found such article http://sandeepmore.com/blog/2010/06/12/modifying-http-headers-using-java/
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
#Component
public class HeaderFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
filterChain.doFilter(new HeaderHttpRequestWrapper(request), new HeaderHttpResponsetWrapper(response));
}
private static class HeaderHttpRequestWrapper extends HttpServletRequestWrapper {
public HeaderHttpRequestWrapper(HttpServletRequest request) {
super(request);
}
#Override
public String getHeader(String name) {
if ("Referer".equalsIgnoreCase(name))
return "";
return super.getHeader(name);
}
}
private static class HeaderHttpResponsetWrapper extends HttpServletResponseWrapper {
public HeaderHttpResponsetWrapper(HttpServletResponse response) {
super(response);
}
#Override
public void sendRedirect(String location) throws IOException {
// TODO Auto-generated method stub
super.sendRedirect(location);
}
#Override
public void addHeader(String name, String value) {
if ("Referer".equalsIgnoreCase(name))
return;
super.addHeader(name, value);
}
#Override
public void setHeader(String name, String value) {
if ("Referer".equalsIgnoreCase(name))
return;
super.setHeader(name, value);
}
}
}
The referer header is not set on the response at all. It's set on the request. With a redirect you're basically instructing the client to create a brand new request all on its own. That request is created on the client side, not on the server side.
The real technical problem is that you can't change the request headers from the server side at all. Response headers, however, are surely modifiable in server side as it's actually the server itself who creates them.
Your closest bet is to redirect to a proxy, which happens to be your own or the one you have full control over, and let the proxy in turn strip the request header. Or, just let the servlet itself act as proxy.
You can't delete response headers by the standard Servlet API. Your can prevent the header from being set by creating a Filter which replaces the ServletResponse with a custom HttpServletResponseWrapper implementation which skips the setHeader()'s job whenever the header name is Content-Disposition.
here is the similar question:
How do delete a HTTP response header?
Seems it's not possible to remove header
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<script>window.location.href='" + url + "';</script>");
out.close();
Since Referer is added by the browser, you can use js redirect.

Categories