How to replace string values with "XXXXX" in java?

Viewed 5221

I want to replace particular string values with "XXXX". The issue is the pattern is very dynamic and it won't have a fixed pattern in input data.

My input data

https://internetbanking.abc.co.uk/personal/logon/login/?userId=Templ3108&password=Got1&reme

I need to replace the values of userId and password with "XXXX".

My output should be -

https://internetbanking.abc.co.uk/personal/logon/login/?userId=XXXX&password=XXXX&reme

This is an one off example. There are other cases where only userId and password is present -

userId=12345678&password=stackoverflow&rememberID=

I am using Regex in java to achieve the above, but have not been successful yet. Appreciate any guidance.

[&]([^\\/?&;]{0,})(userId=|password=)=[^&;]+|((?<=\\/)|(?<=\\?)|(?<=;))([^\\/?&;]{0,})(userId=|password=)=[^&]+|(?<=\\?)(userId=|password=)=[^&]+|(userId=|password=)=[^&]+

PS : I am not an expert in Regex. Also, please do let me know if there are any other alternatives to achieve this apart from Regex.

5 Answers

This may cover given both cases.


String maskUserNameAndPassword(String input) {
    return input.replaceAll("(userId|password)=[^&]+", "$1=XXXXX");
}

String inputUrl1 = 
    "https://internetbanking.abc.co.uk/personal/logon/login/?userId=Templ3108&password=Got1&reme";

String inputUrl2 = 
    "userId=12345678&password=stackoverflow&rememberID=";

String input = "https://internetbanking.abc.co.uk/personal/logon/login/?userId=Templ3108&password=Got1&reme";

String maskedUrl1 = maskUserNameAndPassword(inputUrl1);
System.out.println("Mask url1: " + maskUserNameAndPassword(inputUrl1));

String maskedUrl2 = maskUserNameAndPassword(inputUrl1);
System.out.println("Mask url2: " + maskUserNameAndPassword(inputUrl2));

Above will result:

Mask url1: https://internetbanking.abc.co.uk/personal/logon/login/?userId=XXXXX&password=XXXXX&reme
Mask url2: userId=XXXXX&password=XXXXX&rememberID=

I would rather use a URL parser than regex. The below example uses the standard URL class available in java but third party libraries can do it much better.

Function<Map.Entry<String, String>, Map.Entry<String, String>> maskUserPasswordEntries = e ->
        (e.getKey().equals("userId") || e.getKey().equals("password")) ? Map.entry(e.getKey(), "XXXX") : e;
Function<List<String>, Map.Entry<String, String>> transformParamsToMap = p ->
        Map.entry(p.get(0), p.size() == 1 ? "" : p.get(p.size() - 1));

URL url = new URL("https://internetbanking.abc.co.uk/personal/logon/login/?userId=Templ3108&password=Got1&reme");
String maskedQuery = Stream.of(url.getQuery().split("&"))
        .map(s -> List.of(s.split("=")))
        .map(transformParamsToMap)
        .map(maskUserPasswordEntries).map(e -> e.getKey() + "=" + e.getValue())
        .collect(Collectors.joining("&"));
System.out.println(url.getProtocol() + "://" + url.getAuthority() + url.getPath() + "?" + maskedQuery);

Output:

https://internetbanking.abc.co.uk/personal/logon/login/?userId=XXXX&password=XXXX&reme=

Use:

(?<=(\?|&))(userId|password)=(.*?)(?=(&|$))
  • (?<=(\?|&)) makes sure it’s preceded by ? or & (but not part of the match)
  • (userId|password)= matches either userId or password, then =
  • (.*?) matches any char as long as the next instruction cannot be executed
  • (?=(&|$)) makes sure the next char is either & or end of the string, (but not part of the match)

Then, replace with $2=xxxxx (to keep userId or password) and choose replaceAll.

Just use the methods replace/replaceAll from the String class, they support Charset aswell as regex.

String url = "https://internetbanking.abc.co.uk/personal/logon/login/?userId=Templ3108&password=Got1&reme";

url = url.replaceAll("(userId=.+?&)", "userId=XXXX&");
url = url.replaceAll("(password=.+?&)", "password=XXXX&");

System.out.println(url);

I'm not a regex expert either, but if you find it useful, I usually use this website to test my expressions and as a online Cheatsheet:

https://regexr.com

Related