Enable old TSL\SSL protocol on Java

It is always possible to face a legacy project and have to modify or update it. Usually, their stack is very old and outdated, like the project I worked on that last week, the database of this project was an old SQL Server, which used the TSL 1.0 protocol for secure communication! I had JDK 8 update 312 installed on my system, and on this version of Java, TSL 1.0 has been disabled for security reasons. The result was that the old Spring Boot project could not communicate with the database and showed the following error:


com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "The server selected protocol version TLS10 is not accepted by
client preferences [TLS12]". ClientConnectionId:38242ee7-8809-47a1-b020-2df5e3cc8683

To update one of the project services, I needed to run it on my system, and it wasn't possible to update the database. The next solution was to install an older version of JDK that was compatible with this protocol (!). But there is another way to enable this protocol on existing Java.

For this purpose, I used my old friend, Google, and looked for a solution to activate the TSL 1.0 protocol, which I found at the following address: https://www.qvera.com/kb/index.php/2689/how-to-re-enable-tlsv1-and-tlsv1-1-in-java-8

To enable this protocol, you need to go to the JAVA_HOME of your Java (path where Java is installed and includes the main program folders such as bin, bundle, etc.) and search for java.security file in the this path for editing.

Now look the file content for the jdk.tls.disabledAlgorithms value in the file, this key stores the values of the disabled algorithms, which will be reactivated in Java by deleting the algorithm name. For my project TSL1 should have been removed:


jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, include jdk.disabled.namedCurves

jjdk.tls.disabledAlgorithms value after modification:


jdk.tls.disabledAlgorithms=SSLv3, TLSv1.1, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, include jdk.disabled.namedCurves

You can now easily use the protocol in question. Note that do not use this method in any way for new versions of applications or new projects, as it involves very critical security risks.

Get user IP in Spring Boot

For security reasons, we need to get user IP. In a normal Spring Boot application that interacts with end-users directly (without proxy, load balance and etc.), We can simply get user IP from HttpServletRequest by getRemoteHost().

But in most cases, we need to put an Nginx or Apache in front of our application and route requests to it. In this case, HttpServletRequest.getRemoteHost() returns our proxy server IP. So we need to set user IP in a header of request in our proxy and then redirect it to our application. X-FORWARDED-FOR is used for this reason but there is more than one option:

  • X-Forwarded-For
  • Proxy-Client-IP
  • WL-Proxy-Client-IP
  • HTTP_X_FORWARDED_FOR
  • HTTP_X_FORWARDED
  • HTTP_X_CLUSTER_CLIENT_IP
  • HTTP_CLIENT_IP
  • HTTP_FORWARDED_FOR
  • HTTP_FORWARDED
  • HTTP_VIA
  • REMOTE_ADDR

We can put these options in the application properties file and then check them in our code like this one:


application:
  header-ip-candidates: X-Forwarded-For,Proxy-Client-IP,WL-Proxy-Client-IP,HTTP_X_FORWARDED_FOR,HTTP_X_FORWARDED,HTTP_X_CLUSTER_CLIENT_IP,HTTP_CLIENT_IP,HTTP_FORWARDED_FOR,HTTP_FORWARDED,HTTP_VIA,REMOTE_ADDR

@RestController
@RequestMapping("/ip")
public class IPResource {

    @Value("${application.header-ip-candidates}")
    private String[] headerCandidates;

    @GetMapping
    public ResponseEntity getHome() {
        if (RequestContextHolder.getRequestAttributes() == null) {
            return ResponseEntity.ok("0.0.0.0");
        }

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        for (String header: headerCandidates) {
            String ipList = request.getHeader(header);
            if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
                String ip = ipList.split(",")[0];
                return ResponseEntity.ok(ip);
            }
        }
        return ResponseEntity.ok(request.getRemoteAddr());
    }
}

Convert file to base64 on fron-end in VueJS

It's a normal task to upload a file from the front-end to the back-end. And every developer tried it. Posting a file with a form data type request is a normal way. But what if we want to show a image before upload it to the server? We have an image box and we want to show it to the user before save it.

I found a solution base on base64. I convert the image to base64 and assign it to a variable and connect the image box to present it. Also we can upload base64 to the server and there we convert it to binary image format and save it!

In VueJS, I using the watch to monitor changes on the image field that a user use to select a image, and after user choose a image, front-end app convert it to a base64 string and store it into another variable that connected to the image box.

Let check them in code. At first, I'll define two variable:

  1. image: connected to file input
  2. base64: to keep result of conversion
Then I set a watcher on image, to update base64 variable on image's changes:


    image: function (newVal, oldVal) {
      if(newVal) {
        this.createBase64Image(newVal);
      } else {
        this.base64 = null;
      }
    }

And at the end, I define a function to convert image to base64 and update base64 variable:


    createBase64Image: function(FileObject) {
      const reader = new FileReader();
      reader.onload = (event) => {
        this.base64 = event.target.result;
      }
      reader.readAsDataURL(FileObject);
    }

You can check out https://codepen.io/glinboy/pen/KKvEzjy for an online sample :)

Make rows clickable in VueJS table with ignore a column(s)

 As an old experience, I prefer user can select a row in table with click on it, instance of using a button in last column. In VueJS, we can easily add @click on the <tr> tag like it:

But what about last column buttons? for example, if we have a delete button and also an edit button at last column, to make user comfortable with our data table.

As a long search, I found out that we can easily use @click.stop on the <td> column's tag and then our buttons are free to run their function:

Please check out: https://codepen.io/glinboy/pen/YzxBQEN, for a simple sample :)

Get user roles from Keycloak in Spring/Jhipster

I faced a problem when I tried to use user roles on JHipster 5.x to limit access or filter results; Keycloak returns a token that includes user roles but under wrong path! Keycloak put user roles at realm_access.roles while Spring Security check roles at root of token playload.

I solve this issue in Keycloak and add user roles in roles of playload; Here I want share it with you.