Mask certain string attributes in Java during logging? - java

Is there a way I can mask certain string variables of a class like password, etc which will prevent during logging? Like overriding toString() method in such way it does not print in logs.
For instance, we have a class Employee with following fields:
public class Employee {
private String username;
**private String password; //mask this field**
private String city;
}
During logging like
LOGGER.INFO("printing object:"+employee);
Here in logging, I'm trying to print the whole object, Employee here and my requirement is it does not print out masked field, password at all and whereas logging of rest of the fields are fine.

First obvious option is to override toString(), example:
public class Employee {
private String username;
private String password;
private String city;
#Override
public String toString() {
return "username=" + username + " city=" + city;
}
public static void main(String[] args) {
System.out.println(new Employee().toString());
}
}
You can also replace password string from logging, for example
String maskedPassword = s.replaceAll("password=[^&]*", "password=***");
In you use jersey you can add logging filter with such replacement.

Create a class called MaskedString that is basically just a replacement for String but has a toString method that doesn't output the actual password:
public class MaskedString(){
private String maskedString;
MaskedString(){
maskedString = "";
}
MaskedString(String string){
maskedString = string;
}
public String getActualString(){
return maskedString;
}
public String setString(String string){
maskedString = string;
}
public String toString(){
return "Not the actual string!";
}
}

If you are using lombok, try the exclude option for ToString.
#Data
#ToString(exclude = {"password"})
public class Employee {
private String username;
private String password;
private String city;
}

Related

vavr add nested validations with validations combine

I have an input object as
class Person {
private String name;
private String email;
private String phone;
private Address address;
public static class Address {
private String city;
private String pincode;
private String street;
private AddrDetails details;
public static class AddrDetails {
private String state;
private String country;
}
}
}
I am using vavr Validations to validate the input
public static Validation<Seq<ConstraintViolation>, PersonDetailsModel> validatePerson(PersonDetailsRequest request) {
Validation
.combine(
validateName("name", request.getName()),
validateEmail("email", request.getEmail()),
validatePhone("phone", request.getPhone()),
validateAddress(request.getAddress())
).ap((name, email, phone, address) -> new PersonDetailsModel(name, email, phone, address);
}
public static Validation<Seq<ConstraintViolation>, Person.Address> validateAddress(
Person.Address request) {
return Validation
.combine(..
).ap((..) -> new Person.Address(..);
}
In the second function, it returns Seq of ConstraintViolation while validatePerson expects only ConstraintViolation which is why it is failing although I have to add one more level of nesting of validations for AddrDetails. How to handle nested objects validations with this approach.
I am not sure about how shall I go ahead?
In our project we call .mapError(Util::flattenErrors) after .ap. I have the feeling that there is a better way, but this at least solves the nesting.
The method in the Util class looks like this :
public static Seq<ConstraintViolation> flattenErrors(final Seq<Seq<ConstraintViolation>> nested) {
return nested
.flatMap(Function.identity())
.distinct(); // duplicate removal
}

Morphia - custom field with custom reader and writer

I want to add a custom type of field that will have a default behaviour.
my purpose is to handle all type of secret fields:
for example:
I have password field on user class, and I want password field to be encrypted on some way, so instead of:
#Entity
public static class User {
String name;
String pwd;
String pwdToken
public User() {
}
public User( string name, string password ) {
super();
this.pwd = password;
}
}
and then managing the decrypt and encrypt from outside - service or controller
I would have something like that:
#Entity
public static class User {
String name;
SecretField pwd;
public User() {
}
public User( string name, string password ) {
super();
this.name = name;
// this.pwd.set(password)
}
}
public final class SecretField implements Serializable {
private static final long serialVersionUID = 1L;
private String encryptedContent;
private String token;
public SecretField(String content) {
this.token = generateToken();
this.encryptedContent = decrypt(content, this.token);
}
// when especially called the decrypted pwd will be returned
public decrypt(){
decrypt(encryptedContent, token)
}
//here I should override the default output object - return this.encryptedContent instead of whole object
//???
}
This way, every time I have a secret field I can just use this class and the encrypting will be done automatically, And I won't need to manage the on each controller seperatly.
On update and insert, the password will be sent as decrypted string from client and on get the enrypted string will be returned.
Is it possible with morphia?
You can write a custom codec in 2.0 to do that for you. Prior to that you could write a life cycle event handler to do that. The docs for that can be found at https://morphia.dev

Why in my code do I have this inheritance problem? Create an object passing a specialized type instead of declared abstract super type

Working on a Java application I am finding the following problem related to inheritance.
I have the following situation:
1) I defined an abstract class named TrendFromExcelAbstract. This class contains some basic fields common to other classes which extend it and represent different tabs of an Excel file (but this is not important now):
public abstract class TrendFromExcelAbstract {
private Long id;
private String date;
private String time;
private String excelDocumentName;
private String excelDocumentSheet;
public TrendFromExcelAbstract() {
super();
}
public TrendFromExcelAbstract(Long id, String date, String time, String excelDocumentName,
String excelDocumentSheet) {
super();
this.id = id;
this.date = date;
this.time = time;
this.excelDocumentName = excelDocumentName;
this.excelDocumentSheet = excelDocumentSheet;
}
................................................................
................................................................
GETTER AND SETTER METHODS
................................................................
................................................................
}
Then I have a class named CompVibrAndTempDTO extending the previous abstract class:
public class CompVibrAndTempDTO extends TrendFromExcelAbstract {
// Temperature reading point
private String tempReadingPointA;
private String tempReadingPointB;
private String tempReadingPointC;
private String tempReadingPointD;
private String tempReadingPointE;
private String tempReadingPointF;
private String tempReadingPointG;
private String tempReadingPointH;
private String tempReadingPointI;
private String tempReadingPointJ;
private String tempReadingPointK;
private String tempReadingPointL;
private String tempReadingPointM;
private String tempReadingPointN;
private String tempReadingPointO;
private String tempReadingPointP;
// Vibration reading point
private String vibrReadingPointA;
private String vibrReadingPointB;
private String vibrReadingPointC;
private String vibrReadingPointD;
private String vibrReadingPointE;
private String vibrReadingPointF;
private String vibrReadingPointG;
private String vibrReadingPointH;
private String vibrReadingPointI;
private String vibrReadingPointJ;
private String vibrReadingPointK;
private String vibrReadingPointL;
public CompVibrAndTempDTO() {
super();
}
public CompVibrAndTempDTO(Long id, String date, String time, String excelDocumentName, String excelDocumentSheet,
String tempReadingPointA, String tempReadingPointB, String tempReadingPointC, String tempReadingPointD,
String tempReadingPointE, String tempReadingPointF, String tempReadingPointG, String tempReadingPointH,
String tempReadingPointI, String tempReadingPointJ, String tempReadingPointK, String tempReadingPointL,
String tempReadingPointM, String tempReadingPointN, String tempReadingPointO, String tempReadingPointP,
String vibrReadingPointA, String vibrReadingPointB, String vibrReadingPointC, String vibrReadingPointD,
String vibrReadingPointE, String vibrReadingPointF, String vibrReadingPointG, String vibrReadingPointH,
String vibrReadingPointI, String vibrReadingPointJ, String vibrReadingPointK, String vibrReadingPointL) {
........................................................................................................................
........................................................................................................................
........................................................................................................................
}
........................................................................................................................
........................................................................................................................
GETTER AND SETTER METHODS
........................................................................................................................
........................................................................................................................
}
Then I have another DTO class named ExcelTabGeneralInfoDTO like this:
public class ExcelTabGeneralInfoDTO {
private String excelDocumentName;
private String excelSheetName;
private List<TrendFromExcelAbstract> trendOfTabList;
public ExcelTabGeneralInfoDTO() {
super();
}
public ExcelTabGeneralInfoDTO(String excelDocumentName, String excelSheetName,
List<TrendFromExcelAbstract> trendOfTabList) {
super();
this.excelDocumentName = excelDocumentName;
this.excelSheetName = excelSheetName;
this.trendOfTabList = trendOfTabList;
}
..................................................................
..................................................................
GETTER AND SETTER METHODS
..................................................................
..................................................................
}
As you can see this class contains this list field:
private List<TrendFromExcelAbstract> trendOfTabList;
The idea is that this field represents a list of any objects that derive from TrendFromExcelAbstract
The problem is that in another class I am trying to do something like this:
public List<ExcelTabGeneralInfoDTO> getCompVibrAndTempTab() {
List<CompVibrAndTempDTO> tabTrendList = excelRepo.findCompVibrAndTempTab();
String excelDocumentName;
String excelSheetName;
if(tabTrendList.size() >=0 ) {
excelDocumentName = tabTrendList.get(0).getExcelDocumentName();
excelSheetName = tabTrendList.get(0).getExcelDocumentSheet();
}
ExcelTabGeneralInfoDTO result = new ExcelTabGeneralInfoDTO(excelDocumentName, excelSheetName, tabTrendList);
return result;
}
So basically at this line:
ExcelTabGeneralInfoDTO result = new ExcelTabGeneralInfoDTO(excelDocumentName, excelSheetName, tabTrendList);
I am trying to create a new ExcelTabGeneralInfoDTO, passing to it the tabTrendList list having type List.
I get the following error message:
Description Resource Path Location Type
The constructor ExcelTabGeneralInfoDTO(String, String, List<CompVibrAndTempDTO>) is undefined ExcelServiceImpl.java /energy-prg-be/src/main/java/com/springboot/excelapi/services line 425 Java Problem
Description Resource Path Location Type
Type mismatch: cannot convert from List<ExcelTabGeneralInfoDTO> to List<CompVibrAndTempDTO> ExcelResource.java /energy-prg-be/src/main/java/com/springboot/excelapi/resources line 167 Java Problem
My idea is that I can use the more general type (ExcelTabGeneralInfoDTO) and then pass the child type (CompVibrAndTempDTO). But it seems that my assumption is false. What is wrong? What am I missing? Why can't I do something like this? How can I fix it?
ExcelTabGeneralInfoDTO does not have a defined constructor for List<CompVibrAndTempDTO>, only for List<TrendFromExcelAbstract>. Try declaring tabTrendList as a List<TrendFromExcelAbstract> and see if it works.

calling a function containg enum in java

I have defined a class
class Prop{
public static enum property{
NAME,
CITY,
ADDRESS;
}
private String NAME;
private String CITY;
private String ADDRESS;
public String getValue(property pro){
switch(pro){
case NAME:
return NAME;
case CITY:
return CITY;}
return null;}
}
class CallPro{
private String name;
name=Prop.getValue("");
}
I am not exactly getting how to call getValue from class CallPro.
Basically what parameters should be passed to get the desired value.
I am a beginner in java
To run this program you need a public static void main(String[]) method first. That's your entry point into any Java program. Since, you want to assign the values inside callPro, add the main() method there.
Next, you want to call getProperty() which is an instance method belonging to class prop, so you'll need to create an instance of it first using the new constructor() syntax.
class callPro {
private static String name;
private static String city;
private static String address;
public static void main(String[] args) {
// create prop instance
prop property = new prop();
// call prop's method getValue()
name = property.getValue(prop.property.CITY);
city = property.getValue(prop.property.NAME);
address = property.getValue(prop.property.ADDRESS);
// New York, John, Central Park
System.out.println(name + ", " + city + ", " + address);
}
}
Notice, how I had to make callPro's members static to be able to access them inside the main() method because that's static too. Also, note how I referenced the Enums: className.enumType.enumValue.
To be able to see the values print from the main() method, you'll also need to provide values for your prop class members as
private String NAME = "John";
private String CITY = "New York";
private String ADDRESS = "Central Park";
public String getValue(property pro) {
switch (pro) {
case NAME:
return NAME;
case CITY:
return CITY;
case ADDRESS:
return ADDRESS;
}
return null;
}
Yes, you can loop through an enum's values and retrieve your properties in a loop as
prop property = new prop();
for (prop.property prop : prop.property.values()) {
System.out.println(property.getValue(prop));
}
enumType.values() returns an enumType[] of all enumValues which can be used with a for-each loop as shown above.

Convert Userdefined Object to a String Object

I have a user defined class, say
import java.util.Calendar;
public class Employee{
private String name;
private int age;
private Calendar dob;
private Address address;
private boolean married;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Calendar getDob() {
return dob;
}
public void setDob(Calendar dob) {
this.dob = dob;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public boolean isMarried() {
return married;
}
public void setMarried(boolean married) {
this.married = married;
}
}
class Address{
private int doorNo;
private String streetName;
private String city;
public int getDoorNo() {
return doorNo;
}
public void setDoorNo(int doorNo) {
this.doorNo = doorNo;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
I am creating an object of Employee and populating it with setters. I have to represent the above object to string (encrypted or human-readable) and parse back to get similar object. Actually, I want to save the string equivalent of java object in a file and to read back them to get a java object. I know we have object writing, but they are sensitive to edit. I would prefer if a java object can be converted to String of human readable form. Thanks.
To keep your flattened object human readable and hand editable consider encoding your object into a JSON string using one of the popular JSON libraries. Same JSON library will also provide you APIs to decode a JSON string into your object.
One of the popular JSON library is Gson. Here's an use example: Converting JSON to Java
You should override toString() to convert instances of your class to string. As for recreating instances based on their string representation you can define a static factory method for this.
public class Employee {
...
#Override
public String toString() {
...
}
public static Employee fromString(String str) {
...
}
}
You use these methods like this:
To obtain string representation of an instance to string:
Employee john = ...
String johnString = john.toString();
Note that your toString() method will also be called implicitly whenever there is a need to obtain string representation of one of the instances.
To recreate an instance from string:
Employee john = Employee.fromString(johnString);
If you often need to store instances of the class in a file and read them back, you may also consider serialization. See documentation for Serializable interface as well as ObjectInputStream and ObjectOutputStream. You may also want to familiarize yourself with caveats surrounding serialization by reading the last chapter ("Serialization") in Effective Java, second edition. Most importantly be aware that the serialized form of your class becomes part of your public API.
You might be looking for the toString method:
Returns a string representation of the object. In general, the
toString method returns a string that "textually represents" this
object. The result should be a concise but informative representation
that is easy for a person to read. It is recommended that all
subclasses override this method.
In your case you would be doing something of the sort (to be added in each of your classes):
#Override
public String toString()
{
return "Name = " + name + ...
}
The string can be of any format you wish. To save the object, all that you need to do is to write the text that the toString method returns to a file.
To read them back, however, you will have to implement your own logic. On the other hand, what you can do, is to use something such as XStream (instructions here) which will automatically convert your object to XML.
XML is human readable so that your users can modify whatever they need. Once this is done, you can re-use XStream to read back your object.
Try this
Employee em = new Employee;
//Your code
str obj= JavaScriptSerializer.Serialize();
// whenever you want to get object again
Employee emp = (Employee)JavaScriptSerializer.Deserialize();

Categories