How can I test a URL is SSL secured - java

I'm new to IT industry. Test scenario is like I need to test whether my application's login page is SSL secured or not?
In general sometime we used to visit some websites where it shows a pop-up for SSL security. So I need to test the same scenario in my application.
I have small web application where I have login.html page. Basically, I'm able to start my web application using Maven and server used is Tomcat. Command I'm using to start is mvn tomcat7:run and URL using http://localhost:8080/login.html. It works perfectly.
But I want to change my URL from http to https and when I access my URL, i.e to https://localhost:8080/login.html, then it should pop-up with SSL security alert and I should accept it.
If my question is still not clear then feel free to comment.
After searching on net I have done some workarounds but its not working out. What I have tried:
My HTML page
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Login App</h1>
<div id="emptyDiv"></div>
<div id="description"></div>
<!--container start-->
<div id="container">
<div id="container_body" style="background-color:#BBD700;float:center;">
<!--Form start-->
<div id="form_name">
<div class="firstnameorlastname">
<form >
<div id="errorBox"></div>
First Name : <input id="firstName" type="text" name="Name" value="" >
Last name : <input id="lastName" type="text" name="LastName" value="" >
</div>
<div id="email_form">
Email Id: <input style="position:right" type="text" name="Email" value="" >
</div>
<input id="sub_form" type="submit" value="Submit">
</form>
</div>
<!--form ends-->
</div>
</div>
<!--container ends-->
</body>
</html>
web.xml
<pre><code><!DOCTYPE web-app PUBLIC <span style="color: red;">"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"</span> <span style="color: red;">"http://java.sun.com/dtd/web-app_2_3.dtd"</span>>
<web-app>
<!-- <security-constraint>
<web-resource-collection>
<web-resource-name>MyEducationApp</web-resource-name>
<url-pattern>/login.html</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Non-SecureResource</web-resource-name>
<url-pattern>/login.html</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint> -->
<display-name>Login WebApp</display-name>
</web-app>
</span></code></pre>
Maven Plugin used
<!-- Maven Tomcat Plugin -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<url>https://localhost:8080/manager/text</url>
<server>localhost</server>
<path>/</path>
<username>admin</username>
<password>aRfalah</password>
</configuration>
<executions>
<execution>
<id>tomcat7-run</id>
<goals>
<goal>run-war-only</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<fork>true</fork>
</configuration>
</execution>
<execution>
<id>tomcat7-shutdown</id>
<goals>
<goal>shutdown</goal>
</goals>
<phase>post-integration-test</phase>
</execution>
</executions>
</plugin>

SSL/TLS encryption for your web site is nothing you can do in your web application. It's done via your web server's configuration.
See Apache Tomcat 7, SSL Configuration HOW-TO.
Additional info (repeated from my comment to the OQ, since comments are not that prominent and editable):
You don't have to buy a certificate from one of the certification authorities (CA) to obtain a certificate.
StartSSL offers 1-year SSL/TLS + S/MIME for free. On a different domain they offer now:
No offer any more:
Notice to all StartCom subscribers
StartCom CA is closed since Jan. 1st, 2018 that don’t issue any new certificate from StartCom name roots.
If you want to buy trusted SSL certificate and code signing certificate, please visit https://store.wotrus.com.
If you want to apply free email certificate, please visit https://www.mesince.com to download MeSince APP to get free email certificate automatically and send encrypted email automatically.
But there may be other companies meanwhile.
You can easily create your own certificates with OpenSSL (thus being your own CA) and associate this certificate with your https:// site. If your visitors accept your certificate in the dialog that pops up in their browser it is stored in their browser's certificate store and the dialog will not appear again until the certificate's expiration date is reached.

This is what you need to do:
Generate a self signed certificate and install the same in Tomcat (Gerold Broser's post has the link)
By default, the SSL port is disabled in Tomcat, enable it (same link as bove)
Change your URL to https://local_host:8443/login.html (default SSL port for Tomcat)
Make the request through your browser, you should see a page/message, depending on the browser, telling you that the certificate is not OK
If you want this page to be only accessed through SSL, look at Tim Funk's post and edit the web.xml of the application.

The normal practice is to check via request.isSecure() whether the request came in via https or not. If not then send a redirect to the browser to the same URL but prefixed with https protocol.
Here is an example servlet filter to do this:
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 java.io.IOException;
public class SecurityFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse servletResponse = (HttpServletResponse) response;
if (!request.isSecure()) {
HttpServletRequest servletRequest = (HttpServletRequest) request;
String target = "https://" + request.getLocalName() + servletRequest.getRequestURI();
servletResponse.sendRedirect(target);
return;
}
// tell the browser to use only https for accessing this domain for the next 30 days
servletResponse.addHeader("Strict-Transport-Security", "max-age=" + (30 * 24 * 60 * 60));
chain.doFilter(request, response);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// not needed
}
#Override
public void destroy() {
// not needed
}
}
To enable the filter globally add the following to you web.xml:
<filter>
<filter-name>securityFilter</filter-name>
<filter-class>SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The line servletResponse.addHeader("Strict-Transport-Security", ... is optional. If you put it into the code, your browser will never try to connect to http again for the next 30 days but will use https itself. That happens if your browser supports the HSTS standard RFC6797. That makes sense if your application should be accessible via https solely. However, I think it is only possible with the standard https port 443. See next.
There is a tiny pitfall in your current tomcat configuration. It is not possible to run http and https on the same port. You need to have two separate connectors one for http and one for https.
To make this happen add to the maven tomcat plugin configuration:
<!-- Maven Tomcat Plugin -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<httpsPort>8443</httpsPort>
. . .
You also need to add the correct protocol for the redirect target in the SecurityFilter code (or make it an parameter):
String target = "https://" + request.getLocalName() + ":8443" + servletRequest.getRequestURI();
The port 8080 and 8443 are only for experimental local web servers, real applications should be on port 80 and 443.
That's it. Have fun and good luck!

To require HTTPS and have your servlet engine automatically redirect to https, you are on the right track with transport-guarantee
So you will probably want
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Context</web-resource-name>
<url-pattern>/login.html</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
The above will only redirect /login.html for your webapp to https. Add more url-pattern as needed.
More details:
http://wiki.apache.org/tomcat/FAQ/Security#Q4 and
http://marc.info/?l=tomcat-user&m=104951559722619&w=2

From the original question above:
Command I'm using to start is mvn tomcat7:run and URL using
http://localhost:8080/login.html. It works perfectly. But i want to
change my URL from http to https and when I access my URL i.e
https://localhost:8080/login.html
Are you sure about 'http://localhost:8080' and 'https://localhost:8080'?
This basically means that you are requesting both SSL and non SSL traffic from same port. Normally Tomcat does HTTP from 8080 and HTTPS from 8443.
Most of the answers here would work for you but first be sure to see if you have enabled the SSL connector in server.xml.

Related

In a GlassFish web application, HTTP to HTTPS redirection works only the first time the http link is accessed in Internet Explorer

We have a GlassFish 4.1 web-application with SSL and port unification configured in domain.xml.
We cannot use built-in authentication mechanisms like BASIC, FORM, CERT-CLIENT. Instead, we use a custom login form (using the Stripes framework - https://github.com/StripesFramework).
We want to redirect all http requests to https, but in IE11 it does not work as expected: the HTTP link is converted into an HTTPS link only on the first access in the browser. Then if the HTTP link is used again in the same browser page, it is no longer replaced with HTTPS.
The issue only appears in Internet Explorer (we're using version 11).
We have tried putting this code in web.xml, as specified in the docs (https://docs.oracle.com/cd/E19226-01/820-7627/bncbk/index.html):
<security-constraint>
<display-name>Require HTTPS</display-name>
<web-resource-collection>
<web-resource-name>EntireApplication</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
It works as expected the first time an http link pointing to the app login page is accessed, that is the URL prefix correctly changes from http to https before the page is displayed: http://webapp:8090/ctx_root/ to https://webapp:8090/ctx_root/.
But if afterwards I remove the s from the https prefix in the URL bar (only in IE11), and I press Enter, the http:// prefix is no longer replaced with https:// and the user gets a non-secure version of the login page, with some warnings in the Console: "HTTP security is compromised by http://webapp:8090/ctx_root/js/main.js". However, if the SSL state is cleared in the browser before the second try, the page is again redirected to HTTPS accordingly.
This doesn't happen in Chrome, where each and every time the link changes correctly from http to https.
This is the content of domain.xml:
<network-config>
<protocols>
<protocol name="http-listener-1">
<http encoded-slash-enabled="true" default-virtual-server="server">
<file-cache></file-cache>
</http>
</protocol>
<protocol name="http-listener-2" security-enabled="true">
<http encoded-slash-enabled="true" default-virtual-server="server">
<file-cache></file-cache>
</http>
<ssl ssl3-enabled="false" classname="com.sun.enterprise.security.ssl.GlassfishSSLImpl" cert-nickname="mycert"></ssl>
</protocol>
....
<protocol name="http-redirect">
<http-redirect secure="true"></http-redirect>
</protocol>
<protocol name="pu-protocol-http">
<port-unification>
<protocol-finder protocol="http-listener-2" classname="org.glassfish.grizzly.config.portunif.HttpProtocolFinder" name="http-finder"></protocol-finder>
<protocol-finder protocol="http-redirect" classname="org.glassfish.grizzly.config.portunif.HttpProtocolFinder" name="http-redirect"></protocol-finder>
</port-unification>
</protocol>
</protocols>
<network-listeners>
<network-listener protocol="pu-protocol-admin" port="4848" name="admin-listener" thread-pool="admin-thread-pool" transport="tcp"></network-listener>
<network-listener protocol="pu-protocol-http" port="8090" name="http-listener-1" thread-pool="http-thread-pool" transport="tcp"></network-listener>
</network-listeners>
<transports>
<transport name="tcp"></transport>
</transports>
</network-config>
Any idea why HTTP to HTTPS redirection works only the first time the http link is accessed? Could it be an IE11 or firewall issue?

Single Sign on implementation in Tomcat

I have three jsf web application deployed on tomcat web server with SSL/TLS enabled. Now I want to build some kind of SSO authentication with particular roles. In tomcat conf/server.xml there is line:
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
so I got idea that tomcat maybe have his own SSO implementation. Does anyone know where to find more information about this or some code examples?
Thanks in advance
After many hours of research I found solution, so I will post it here in case someone need SSO authentication in tomcat.
First of all open conf/server.xml file in tomcat installation directory and add following line:
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
</Host>
By doing this, you have opened SSO valve. Next, you need to set up roles in tomcat. That is done by editing conf/tomcat-users.xml. Scroll to the bottom and add roles, something like this:
<role rolename="CUSTOMER"/>
<role rolename="ADMIN"/>
Now, if you want plain text authentication you can add users also by adding :
<user username="admin" password="admin" roles="ADMIN"/>
<user username="customer" password="customer" roles="CUSTOMER"/>
or, if you have database you can set up connection with database server in conf/server.xml, I'm using MySQL:
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/databaseName?user=serverUsername&password=serverPassword"
userTable="usersTable" userNameCol="usernameColumnName" userCredCol="passwordColumnName"
userRoleTable="roleTable" roleNameCol="roleColumnName"/>
Note: You need to provide connection driver in tomcat lib directory.
More info on: https://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html#JDBCRealm
Finally in your web app or apps, find web.xml and add security constrains:
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Context</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>this is ignored currently</realm-name>
</login-config>
<security-role>
<role-name>ADMIN</role-name>
</security-role>
Note: if you have custom Login page you can edit <login-config> tag and change to following:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>file</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
Cheers.
Apache 9 Single Sign On Valve documentation is here: https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html.
Since you mentioned JSF (I'm not sure if you are using PrimeFaces & OmniFaces), maybe you are struggling also with log out/session time out. Specially if end user has open multiple windows/tabs and multiple applications (you mentioned you have three JSF apps), then
OmniFaces FacesExceptionFilter and
OmniFaces FullAjaxExceptionHandler
would be helpful for you. I can also recommend the best JSF book I've ever read
The Definitive Guide to JSF in Java EE 8 written by BalusC (JSF expert, author of OmniFaces, etc.).

404 Not Found Error on GET/POST Request from Client to Java Servlet

I am receiving a 404 error (in the web browser console) upon sending a GET request from an html page via jquery to my java servlet .class file.
I honestly don't know what I should be doing after creating the core files in my IntelliJ maven-webapp project:
pom.xml, MyTestServlet.class, web.xml, index.html, do.js
I am building my project to a folder called "target" via:
Build > Build Artifacts >> All Artifacts > Build
And then, I take all the files in target and upload them to my department's server, but when I navigate to index.html and click the button, it returns a 404 error on the GET request instead of printing out the text specified in the servlet.
Here is the file structure of the project:
Here is the file structure of the result:
"MyTestServlet.java" File (the Java Servlet):
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by isardar on 7/11/2017.
*
* GOAL FOR THIS TEST:
*
* make a servlet that sends data to client and client should receive/process the data
*
*/
//#WebServlet("/MyTestServlet") <-- idk what i'm doing
public class MyTestServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String text = "some text boiii";
response.setContentType("text/plain"); // Set content type of the response so that jQuery knows what it can expect.
response.setCharacterEncoding("UTF-8"); // You want world domination, huh?
response.getWriter().write(text); // Write response body.
}
}
"index.html" File:
<!DOCTYPE html>
<html lang="en">
<head>
<title>SO question 4112686 - Copied & Tweaked Version</title>
<link rel="stylesheet" href="style.css"/>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="do.js"></script>
</head>
<body>
<button id="somebutton">press here</button>
<div id="somediv"></div>
</body>
</html>
"do.js" File:
/**
* Created by isardar on 7/11/2017.
*/
$(document).on("click", "#somebutton", function() { // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
$.get("WEB-INF\\classes\\ServerTest.class", function(responseText) { // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response text...
$("#somediv").text(responseText); // Locate HTML DOM element with ID "somediv" and set its text content with the response text.
});
});
"web.xml" File:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>ServletTest</servlet-name>
<servlet-class>MyTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletTest</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
"pom.xml" File:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ServletTest4</groupId>
<artifactId>ServletTest4</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>ServletTest4 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- a default maven-web-app dependency for some reason... -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0-b07</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>ServletTest4</finalName>
</build>
</project>
Can someone guide me as to what I should change to make this work, I feel I am quite close to a solution here? Also let me know if there are better ways about going about this problem, I have briefly heard of web servlet 3.0 but could not find any good resources on it for IntellliJ and Maven. Thanks!
After you make sure your application is running under an application server (Tomcat, JBoss, etc). Your requests should be redirected to the correct path, which should be something like: localhost:8080/ProjectName/WebServletName.
You are using the get request to directly access the servlet file, but it works under the HTTP protocol. So it should be accessed in that way
Its something to do with your servlet not being identified when the server starts. It looks to be an issue related to Servlet may not be in right directory or package. Or you have to also provide package name for your servlet in "web.xml" file
As CrazyCoder pointed out, my problem was at "jquery.get(..." in the "do.js" file. It should be:
$.get("WEB-INF\\classes\\MyTestServer.class"...
Instead of:
$.get("WEB-INF\\classes\\ServerTest.class"...
It's just a simple typo!

How to create login page that uses websphere repositories?

I want to create a simple JSP/Servlet login page that authenticate using websphere ldap repository.
All examples I've found looks very complex, with hundreds of lines of code just to authenticate.
Is this really so complex?
Does anyone have a simple example or article that explains how to authenticate a user/pass against a ldap repository already configured as websphere federated repository?
I really appreciate any help.
Thanks
This is quit simple in reality. You need following pieces:
1) Login page with form that points to j_security_check
See this page for details Customizing web application login
Very simplified example is like this:
<form method="POST" action="j_security_check">
<input type="text" name="j_username">
<input type="text" name="j_password" autocomplete="off">
<\form>
2) Security configured in web.xml
Something like this:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Example Form-Based Authentication</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login.jsp</form-error-page>
</form-login-config>
</login-config>
plus security constraint:
<security-constraint>
<display-name>allResources</display-name>
<web-resource-collection>
<web-resource-name>allResources</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>users</role-name>
</auth-constraint>
</security-constraint>
3) Application security enabled on the application server and user registry configured.
That's it.

JSF life after logout

I'm using form based authentication.
I have a logout link which looks like:
<h:commandLink action="#{loginBean.logout}">
<h:outputText value="logout" />
</h:commandLink></div>
And the corresponding logout method:
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "/view/index?faces-redirect=true"; // Redirect added as per BalusC's suggestion.
}
After hitting the logout link I'm returned to the front page, but seemingly without CSS. When I hit a button to run a search I get the following error:
javax.faces.application.ViewExpiredException: viewId:/view/index.jsf - View /view/index.jsf could not be restored.
And yet the CSS is actually under /resources which shouldn't require authentication as I understand my web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>fizio</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Unprotected area</web-resource-name>
<url-pattern>/resources/*</url-pattern>
</web-resource-collection>
</security-constraint>
From this state I seem to be able to login again and see some data between occasional view-could-not-be-restored errors, but no CSS. It's all a bit broken really. Any suggestions would be appreciated.
ETA: Login form:
<form method="POST" action="j_security_check">
<label for="j_password">Username:</label> <input type="text" name="j_username" />
<br />
<label for="j_password">Password:</label> <input type="password" name="j_password" /> <input type="submit" value="Login" />
</form>
You need to redirect after invalidate. Otherwise the page is been shown in midst of the "invalidated" session. Add faces-redirect=true to the outcome to trigger the redirect.
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "/index?faces-redirect=true";
}
The redirect will cause the webbrowser to fire a new GET request after the POST response and in turn cause the server to create a brand new session. This way the views will work as intended.
As to the CSS resources, they apparently still need a login. The "Unprotected area" constraint which you have there is not going to work. Remove it and change the URL-pattern of your main security constraint to for example /app/* or whatever a common path of the secured area is.

Categories

Resources