In my application, I added secure flags to the session header using this solution: https://stackoverflow.com/a/16616225
I experienced the following problem:
It works when I deploy to the remote machine. I can connect to it, no problems!
It does not work on my local, because http://localhost:7001 is no longer valid, I need to use HTTPS connection (https://localhost:7001).
The question is that can I enable or know that I am deploying on my local and I will use HTTP connection instead of HTTPS? Like writing a switch case so that when I deploy it locally, I won't use HTTPS and when I deploy to remote server, I will use HTTPS?
public class SecurityFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
// wrap the response
HttpServletResponse response = new SecureCookieSetter((HttpServletResponse)res);
// touch the session, so that it is added to the response header
((HttpServletRequest)req).getSession();
response.setHeader("Set-Cookie", "JSESSIONID=" + ((HttpServletRequest)req).getSession().getId() + ";Path=/");
HttpServletResponse response = (HttpServletResponse)res;
chain.doFilter(req, response);
}
#Override
public void destroy() {
}
}
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>package.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
You get rely on request.getScheme() to know whether it's HTTP or HTTPS.
But, a better solution will be to make your local server takes HTTPS connections. This can easily be done by adding a self signed certificate to your local domain. You can go to this site and generate a self-signed certificate. This can then be placed either on the web server or on the application server.
Related
How can i create a full web application with Java and React without having to create a rest API, not even a private API with username:password authentication.
I want it to be as it is created with JSP.
Is it possible call Java methods with react locally ?
Or even creating a restfull API that can only be called locally
Thank you
I don't think it's possible to communicate with Java in a client library such as React without having to create a HTTP API.
But you could make one and add a bit of extra layer of security to ensure that only your application could call your Java API by checking the remote address of each call and verifying that's the caller is indeed your server.
You can do this in Java using the getRemoteAddr() method from the HttpServletRequest object.
The best way to do this is to create a filter class that map all the API links and verify the remote address in each calls and then decide if it should allow it or not.
Here's an example:
import javax.servlet.*;
public class RequestFilter implements Filter{
public void init(FilterConfig config) throws ServletException {}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
String callerIp = request.getRemoteAddr();
if(callerIp.equalsIgnoreCase("MY-SERVER-IP-ADDRESS")) {
chain.doFilter(req, res);
}
else {
((HttpServletResponse)res).sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied !");
return;
}
}
public void destroy() {}
}
Replace "MY-SERVER-IP-ADDRESS" with your server ip.
And to map all the calls, set the filter tag in your web.xml as follows:
<filter>
<filter-name>RequestFilter</filter-name>
<filter-class>com.myPackage.requestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
This should satisfy your need, but if you found another way please share it with us.
the first request is no, as far as I'm aware. But as for the local rest api, I know most web servers can check CORS headers and restrict to only serve certain origins on answering requests. So whichever JRE Web Server you're using, check it's API for accessing the origin in the request header, and route those to the rest code.
I'm working with a Spring microservice protected with Spring Security SSO login (Using Cloudfoundry UAA).
Microservice when deployed on Cloud is accessible via HTTPS URL. Since HTTPS URL is of the ELB (Load balancer/web server), actual request to microservice from ELB comes on HTTP. So Spring when redirecting the user to login page produces HTTP URL instead of HTTPS URL in 302 Location header.
Following is the flow
Browser
->(https://mymicroservice.com) Unauthenticated request (Load balancer)
->(http://internal_lan_ip:someport) Microservice
-> 302 Location http://mymicroservice.com/login
-> Browser http://mymicroservice.com/login (failed)
In short it goes from HTTPS -> HTTP -> 302 HTTP (failed as ELB doesn't serve on HTTP)
Following is what I have tried
x-forwarded-proto
Since load balancer is also not populating x-forwarded-proto correctly to HTTPS, instead it gives me HTTP, I can't use Spring's support for it.
Require channel HTTPS
It also doesn't work, as it results in infinite redirections from Spring as Spring never receives an HTTPS request from ELB, despite correctly having produced HTTPS redirect URL.
Interceptor/Filter
Use a ServletFilter to check response header Location and if present replace http:// with https://.
Frankly last option is my final option as I do not control the ELB configuration.
Now issue is that I'm unable to intercept the response after spring redirects to /login URL which in turn should redirect to SSO URL.
I have tried various combinations of Interceptors (postHandle, afterCompletion), using Spring security to inject it at various locations in the filter chain and finally setting the filter order to lowest. None of these intercept unauthenticated request after redirection.
#Component
#Order(Ordered.LOWEST_PRECEDENCE)
class RedirectUrlProtocolUpdaterFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String locationHeader = response.getHeader("Location");
System.out.println("############ inside interceptor");
for(String name: response.getHeaderNames()) {
System.out.println(name + " : " + response.getHeader(name));
}
if(locationHeader != null && locationHeader.startsWith("http://")) {
System.out.println("###################### setting location header");
locationHeader = locationHeader.replaceAll("http://", "https://");
response.setHeader("Location", locationHeader);
}
filterChain.doFilter(request, response);
}
}
How do I correctly intercept the /login redirection by Spring Security in a filter/interceptor and update Location header to include correct protocol?
Any hint is appreciated.
If you want to update Location header info you can try to use an HttpResponseInterceptor.
This is an example of use from google HttpResponseInterceptor:
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/http/HttpResponseInterceptor
Other option is from Apache:
https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/class-use/HttpResponseInterceptor.html
SpringFramework provides the HandlerInterceptor. This will intercept all http request, but can be used to constantly check for authentication and authorization. You will have to provide implementations for 3 methods (if you don't use them just implement an empty method). You can then put your code in the preHandle method.
public class AuthenticationInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
}
#Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
#Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
I am making simple web app project in maven spring mvc with hibernate .I have set all controllers and all work fine .Now I am gonna make restriction for users who haven't logged in .I don't wanna let them to go inside before logging in.And also After they log out ,they should be thrown out.How can I do this ?
You can use a Servlet filter. This is an object that can intercept HTTP requests targeted at your web application.
A servlet filter can intercept requests both for servlets, JSP's, HTML files or other static content, as illustrated in the diagram below.
In order to create a servlet filter you must implement the javax.servlet.Filter interface.
public class SimpleServletFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
}
public void destroy() {
}
}
When a HTTP request arrives at your web application which the filter intercepts, the filter can inspect the request URI, the request parameters and the request headers, and based on that decide if it wants to block or forward the request to the target servlet, JSP etc.
It is the doFilter() method that does the interception. Here is a sample implementation:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
String myParam = request.getParameter("myParam");
if(!"blockTheRequest".equals(myParam)){
filterChain.doFilter(request, response);
}
}
Notice how the doFilter() method checks a request parameter, myParam, to see if it equals the string "blockTheRequest". If not, the request is forwarded to the target of the request, by calling the filterChain.doFilter() method. If this method is not called, the request is not forwarded, but just blocked.
The servlet filter above just ignores the request if the request parameter myParam equals "blockTheRequest". You can also write a different response back to the browser. Just use the ServletResponse object to do so, just like you would inside a servlet.
You need to configure the servlet filter in the web.xml file of your web application, before it works. Here is how you do that:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>servlets.SimpleServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>*.simple</url-pattern>
</filter-mapping>
With this configuration all requests with URL's ending in .simple will be intercepted by the servlet filter. All others will be left untouched.
I have a servlet filter written for my app engine project.
It is being called from the local development machine.
But it is not called when I put the code in Google App Engine live server.
Can anybody explain why?
This is how it is mapped in web.xml
<filter>
<filter-name>ErrorHandlerFilter</filter-name>
<filter-class>com.fms.advocacy.filters.ErrorHandlerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ErrorHandlerFilter</filter-name>
<url-pattern>/_ah/api/*</url-pattern>
</filter-mapping>
And this is the filter.
public class ErrorHandlerFilter implements Filter {
private static final Logger log = Logger.getLogger(ErrorHandlerFilter.class.getName());
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.warning("Entered ErrorHandlerFilter!!");
}
}
PS: I am using Google Cloud Endpoint for coding my APIs
The issue was with the <url-pattern>/_ah/api/*</url-pattern>.
In server the url is changed to <url-pattern>/_ah/spi/*</url-pattern>
Now it is working.
We have a Java EE 6 web application with JSF 2.0 running on Glassfish 3.1.
There we encountered a strange bug: the Mime type of the response header send by Glassfish to the client depends on the order of the allowed Mime types in the request header send by the Browser. So in some cases (depending on the browser), the Mime type of the response is wrong, resulting in a broken html page.
But it would take pretty long to explain that thing. So to workaround this problem we now want to do just one thing:
Force the response header type for the whole web-application to "text/html".
Currently, we do that with a Servlet Filter configured in the Web.xml:
#WebFilter("/BaseFilter")
public class BaseFilter implements Filter {
public BaseFilter() {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
response.setContentType("text/html;charset=UTF-8");
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
configuration in web.xml:
<filter>
<filter-name>BaseFilter</filter-name>
<filter-class>com.company.web.filter.BaseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BaseFilter</filter-name>
<url-pattern>/*</url-pattern>
<!-- these patterns should match cached resources -->
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
So my question is, is there a better way to enforce a specific response header, especially by just configuring it instead of implementing a ServletFilter?
Is there a Glassfish option to do that?
You can specify it in the default template by the contentType attribute of the <f:view>.
<f:view contentType="text/html">