Tomcat HTTPS only except 1 endpoint - java

I already configured my Connector in the server.xml with the redirection from 8080 to 8443, and set the security-constraint in web.xml with the appropriate sub-tags. It redirects properly, but I would like to ignore the HTTP access and use only HTTPS. So I do not need redirection or smthing like that. An external service requires HTTP access for an endpoint, I would like to enable only that endpoint over HTTP.
I tried to remove the Connector with 8080 port, but with this approach there is no chance to get the request over http.

If you disable http conection you will not have an access to your application over http.
So you can implement a filter that checks if the protocol of current request is HTTP and endpoint URL is allowed otherwise block the request.
In your web.xml you can declare following filter:
<filter>
<filter-name>blockHttpFilter</filter-name>
<filter-class>com.example.BlockHttpFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>urlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Implementation may be following:
public class BlockHttpFilter implements Filter {
private ServletContext context;
public void init(FilterConfig fConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if(req.isSecure() && checkHttpEnpointPath(req)){
chain.doFilter(request, response);
} else {
HttpServletResponse res = (HttpServletResponse)response;
res.sendError(403);
}
}
public void destroy() {
//we can close resources here
}
}

Related

Doing CORS manually

I'm trying to debug my web app,
I have a POST request. (using ajax, with xhrFields: { withCredentials: true } ). dataType is 'application/json', my server is tomcat and i set my "Access-Control-Allow-Origin" header manually to "http://localhost:8080".
other headers:
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Headers", "x-request-verification-token");
Cant get this to work. this is the error i get:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/MysServlet. (Reason: CORS header 'Access-Control-Allow-Origin' does not match 'http://localhost:8080').
thanks ahead!
If you want a configuration that apply to all your requests add in your web.xml the following filter:
<filter>
<filter-name>originfilter</filter-name>
<filter-class>it.damore.web.ApiOriginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>originfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
This is the ApiOriginFilter class:
public class ApiOriginFilter implements javax.servlet.Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type");
chain.doFilter(request, response);
}
public void destroy() {
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}

POST to GET Redirection

On jsp page After session expiration if a user performs some DB operations the Post url HTTP status shows as 302 which should redirect to my logout Page but as it's a GET call to logout it is not being redirected.
How to redirect from POST Http status 302 to GET or what can be the other way to achieve this?
Some comments/suggestion:
When the server responds with HTTP 302 additionally it also sends a Location header which browser reads and makes another GET request.
This is how it typically works. So please make sure that when you send HTTP 302 you also send a Location header in response and then rest of the things will be handled by the browser.
Please note that here I have take liberty to assume that you can change server side code which sends HTTP 302. Let me know if its otherwise.
You can use Session Filter like :
public class SessionFilter implements Filter {
private ArrayList<String> urlList;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String url = request.getServletPath();
boolean allowedRequest = false;
if(urlList.contains(url)) {
allowedRequest = true;
}
if (!allowedRequest) {
HttpSession session = request.getSession(false);
if (null == session) {
response.sendRedirect("index.jsp");
}
}
}
chain.doFilter(req, res);
}
}
and by making an entry in webl.xml
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>
net.viralpatel.servlet.filter.SessionFilter
</filter-class>
<init-param>
<param-name>avoid-urls</param-name>
<param-value>index.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Or hide the details via placing following entry in web.xml:
<error-page>
<error-code>302</error-code>
<location>/302ErrorPage.jsp</location>
</error-page>

How JSP page should check authentication

I am new to web programming. I am asking a common pattern to do things like checking authentication. Here is the scenario:
The website has a login page for visitors. It will take username and encrypted password and sent them to server, then get either a error code (username/password doesn't match)or an auth key from the server. When the user logged in successfully, I want the website automatically jump to the main.jsp page that presents the main functionality of the website.
In this case, I want main.jsp check the user authentication. That is, I don't want such thing happens like user can directly open www.example.com/main.jsp, and if they did thing like this, I want to redirect them to login page.
So how could I pass authentication information across page, and how could I prevent user from directly accessing the main.jsp without login? Do I need to use session or anything?
you could try using filters:
Filter can pre-process a request before it reaches a servlet,
post-process a response leaving a servlet, or do both.
Filters can intercept, examine, and modify requests and responses.
NOTE: be sure to add a session attribute once your user is logged in, you can use that session attribute on the filter
on your login.jsp add:
session.setAttribute("LOGIN_USER", user);
//user entity if you have or user type of your user account...
//if not set then LOGIN_USER will be null
web.xml
<filter>
<filter-name>SessionCheckFilter</filter-name>
<filter-class>yourjavapackage.SessionCheckFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionCheckFilter</filter-name>
<!--url-pattern>/app/*</url-pattern-->
<url-pattern>/main.jsp</url-pattern> <!-- url from where you implement the filtering -->
</filter-mapping>
SessionCheckFilter.java
public class SessionCheckFilter implements Filter {
private String contextPath;
#Override
public void init(FilterConfig fc) throws ServletException {
contextPath = fc.getServletContext().getContextPath();
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain fc) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
if (req.getSession().getAttribute("LOGIN_USER") == null) { //checks if there's a LOGIN_USER set in session...
res.sendRedirect(contextPath + "/login.jsp"); //or page where you want to redirect
} else {
String userType = (String) req.getSession().getAttribute("LOGIN_USER");
if (!userType.equals("ADMIN")){ //check if user type is not admin
res.sendRedirect(contextPath + "/login.jsp"); //or page where you want to
}
fc.doFilter(request, response);
}
}
#Override
public void destroy() {
}
}
How JSP page should check authentication
It shouldn't. You should use Container Managed Authentication, and define the login/security in web.xml via URL patterns.
Added by Glen Best:
E.g. Add something like this to web.xml:
<security-constraint>
<display-name>GET: Employees Only</display-name>
<web-resource-collection>
<web-resource-name>Restricted Get</web-resource-name>
<url-pattern>/restricted/employee/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>Employee</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
This also works for me
<filter>
<filter-name>SessionCheckFilter</filter-name>
<filter-class>yourjavapackage.SessionCheckFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionCheckFilter</filter-name>
<!--url-pattern>/app/*</url-pattern-->
<url-pattern>/main.jsp</url-pattern> <!-- url from where you implement the filtering -->
</filter-mapping>
public class SessionCheckFilter implements Filter {
private String contextPath;
#Override
public void init(FilterConfig fc) throws ServletException {
contextPath = fc.getServletContext().getContextPath();
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain fc) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
if (req.getSession().getAttribute("LOGIN_USER") == null) { //checks if there's a LOGIN_USER set in session...
req.getRequestDispatcher("login.jsp").forward(req, resp); //or page where you want to redirect
} else {
String userType = (String) req.getSession().getAttribute("LOGIN_USER");
if (userType.equals("ADMIN")){ //check if user type is admin
fc.doFilter(request, response); it redirected towards main.jsp
}
}
}
#Override
public void destroy() {
}
}
How about using:
String username = request.getRemoteUser();

Session Filter redirect trouble

I have problems with AccessFilter in java web. When I am calling /main.jspx it redirect to the login.jsp. But when I am trying to log-in some error appeared
public class AccessFilter implements Filter {
private FilterConfig filterConfig;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpSession session = ((HttpServletRequest) request).getSession();
HttpServletResponse res = (HttpServletResponse) response;
Client client = (Client) session.getAttribute("client");
if (client != null) {
chain.doFilter(request, response);
} else {
RequestDispatcher dispatcher = request.getRequestDispatcher(
ConfigurationManager.getInstance().getProperty(ConfigurationManager.LOGIN_PAGE_PATH));
dispatcher.forward(request, response);
}
}
#Override
public void destroy() {
this.filterConfig = null;
}
}
web.xml:
<filter>
<filter-name>AccessFilter</filter-name>
<filter-class>ua.kpi.shop.filter.AccessFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AccessFilter</filter-name>
<url-pattern>/jsp/main.jspx</url-pattern>
<url-pattern>/jsp/pokemons.jspx</url-pattern>
</filter-mapping>
Error:
HTTP Status 404 - /PokemonsShop/login.jspx
type Status report
message /PokemonsShop/login.jspx
description The requested resource is not available.
filterConfig.getServletContext().getRequestDispatcher takes the absolute path as opposed to request-getRequestDispatcher. Though whether that is the solution I cannot say.
Two things came into my head when seeing your message:
1) Did you check whether the client object is null or not ? May be when executing the login action (method) you are not setting correctly the client into session ?
2) In the server error, it says "not found /PokemonsShop/login.jspx" but in your filter mapping you are mentioning /jsp/xxx. Would it be because your login page is under the folder jsp and you are redirecting (in the filter) to /PokemonsShop/login.jspx, which should be under webapp root folder to be accessible.
Hope one of them be of help

java Filter class doFilter() is not being invoked

Hi there, I have created a Filter class and configure the web.xml as below:
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>my.web.auth.LoginFilter</filter-class>
<init-param>
<param-name>test-param</param-name>
<param-value>This param is for testing</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/html/test/*</url-pattern>
</filter-mapping>
When I access the URL http://{myJBoss}/html/test/index.htm ,
LoginFilter's init() is called but not the doFilter()
Here is the excerpt of my Filter class:
public void init(FilterConfig config) throws ServletException {
log.debug("[201207bb] init"); //******This line can be seen in log file
this.config = config;
String testParam = config.getInitParameter("test-param");
log.debug("test-param="+testParam); //******* This is output correctly too
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
log.debug("[201207bb] doFilter"); //*****This line didn't appear in log file
HttpServletRequest request = (HttpServletRequest) req;
//Get the IP address of client machine.
String ipAddress = request.getRemoteAddr();
//Log the IP address and current timestamp.
log.debug("IP "+ipAddress + ", Time " + new Date().toString());
chain.doFilter(req, res);
}
Does anyone has any idea why is this so?
I have tried on a jsp too, same result.
Problem solved.
url-pattern is incorrectly set.
init() is being called doesn't mean the url-pattern is set up correctly.

Categories

Resources