Как сравнить объект String с литералом, используя шестнадцатеричные значения - PullRequest
0 голосов
/ 26 сентября 2018

Приведенный ниже код получает имя пользователя из системы, используя метод аутентификации Windows NTLM, мне нужно сравнить имя пользователя (current_user_eid).

Применение метода intern () для предустановленного значения, похоже, работает для инициализированных значений.

Сравнение строк между литеральной строкой и строкой объекта дает мне вывод false, но на экране они дают одинаковый вывод.

<%@ page import="sun.misc.BASE64Encoder" %>
<%
String auth = request.getHeader("Authorization");
String current_user_eid= null;
if (auth == null) {
        response.setStatus(response.SC_UNAUTHORIZED);
        response.setHeader("WWW-Authenticate", "NTLM");
        return;
}
if (auth.startsWith("NTLM")) { 
    byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
    int off = 0, length, offset;

    if (msg[8] == 1) { 
        off = 18;
        byte z = 0;
        byte[] msg1 =
            {(byte)'N', (byte)'T', (byte)'L', (byte)'M', (byte)'S',
            (byte)'S', (byte)'P', z,
            (byte)2, z, z, z, z, z, z, z,
            (byte)40, z, z, z, (byte)1, (byte)130, z, z,
            z, (byte)2, (byte)2, (byte)2, z, z, z, z, // 
            z, z, z, z, z, z, z, z};

        response.setStatus(response.SC_UNAUTHORIZED);
        response.setHeader("WWW-Authenticate", "NTLM " + new sun.misc.BASE64Encoder().encodeBuffer(msg1).trim());
        return;
    } 
    else if (msg[8] == 3) { 
        off = 30;
        length = msg[off+17]*256 + msg[off+16];
        offset = msg[off+19]*256 + msg[off+18];
        current_user_eid = new String(msg, offset, length);
    } 
    else
        return;

    length = msg[off+1]*256 + msg[off];
    offset = msg[off+3]*256 + msg[off+2];
    current_user_eid = new String(msg, offset, length);
    length = msg[off+9]*256 + msg[off+8];
    offset = msg[off+11]*256 + msg[off+10];
    current_user_eid = new String(msg, offset, length); //current system user name "yaseer"

    // String Comparison starts here....

    String hard_str = new String("yaseer"); // 
    String hard_str_in=hard_str.intern();

    String eid_str=new String(current_user_eid.toString()); //passing the fetched username which is yaseer
    String eid_str_in = eid_str.intern(); // system username 

    String comp_str = "yaseer"; // String for comparison

    System.out.println(hard_str_in == comp_str); // give true

    System.out.println(eid_str_in == comp_str); // gives false


if(eid_str_in .equals(comp_str ))
{
    System.out.println("true");
}
else
{
    System.out.println("false");
}
}
%>

Может кто-нибудь помочь мне справиться с этим?

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Правильное использование String:

Charset charset = StandardCharsets.ISO_8859_1;
...
    current_user_eid = new String(msg, offset, length, charset);
} 
else
    return;

length = msg[off+1]*256 + msg[off];
offset = msg[off+3]*256 + msg[off+2];
current_user_eid = new String(msg, offset, length, charset);
length = msg[off+9]*256 + msg[off+8];
offset = msg[off+11]*256 + msg[off+10];
current_user_eid = new String(msg, offset, length, charset);
//current system user name "yaseer"

// String Comparison starts here....

String hard_str = "yaseer"; // 

String eid_str = current_user_eid; //passing the fetched username which is yaseer
String eid_str_in = eid_str.intern(); // system username 

String comp_str = "yaseer"; // String for comparison

System.out.println(hard_str_in == comp_str); // give true

System.out.println(eid_str_in == comp_str); // gives false
System.out.println(eid_str_in.equals(comp_str));
// gave true ("on screen"), expected to give false

Последние две строки дали бы разные результаты, если я вас правильно понял.

Это не должно быть так для ясного ASCII "ясера"(при условии, что вы не работаете на AS / 400 с EBCDIC с неправильными кодировками исходного кода / java-кода).

Однако я видел, что current_user_eid назначается дважды, первый раз с 6 байтами, что может соответствоватьв "yaseer" с 6 буквами.

Итак, я предполагаю, что второй current_user_eid является путаницей.

Сброс строки для ее значения:

System.out.println(Arrays.toString(eid_str_in.toCharArray()));

В остальном: .intern() больше не является чем-то, что можно использовать по эффективности;следовательно, также не ==.В более ранних версиях интернированные константы переходили к «генерации постоянной памяти» ограниченного размера, что имело свои недостатки, если слишком много и слишком часто интернировалось.

Байты всегда преобразуются в Unicode String.char с (UTF-16), возможно, с использованием Charset по умолчанию для платформы.Так что лучше явно указать Charset, даже Charset.defaultCharset(), поскольку в нем явно указывается зависимость от платформы.

0 голосов
/ 26 сентября 2018

1) Строковые литералы будут храниться в пуле констант String.Здесь значение не может быть продублировано.Например, если вы пытаетесь создать две переменные с одинаковыми значениями, второе значение переменной не может быть сохранено в SCP, вместо этого он получит адрес первого значения.

2) Но с использованием new String twoобъект будет создан, даже если оба объекта имеют одинаковые значения.

Пример:

public class TestFile {

    public static void main(String[] args) {
        String name1 = "AAA";
        String name2 = name1.intern();

        String name3 = new String("AAA");
        String name4 = name3.intern();

        System.out.println(name1 == name2); // true
        System.out.println(name2 == name4); // true

        System.out.println(name3 == name4); // false
        System.out.println(name3.equals(name4));
    }   
}

1) Здесь name1 и name2 оба являются литералами.поэтому сравнение будет True.

2) name3 - это объект, но мы используем intern (), поэтому получим значения объекта, которые будут храниться в name4 как литерал.так что сравнение будет True.

3) Но имя3 и имя4 совместно будут False.потому что name3 является объектом, а name4 является буквальным.но это будет верно, если вы используете .equals ().

...