not необходимо поместить реализацию в файл заголовка, см. альтернативное решение в конце этого ответа.
В любом случае причина, по которой ваш код не работает, что при создании экземпляра шаблона компилятор создает новый класс с заданным аргументом шаблона. Например:
template
struct Foo
{
T bar;
void doSomething(T param) {/* do stuff using T */}
};
// somewhere in a .cpp
Foo f;
При чтении этой строки компилятор создаст новый класс (назовем его FooInt
), что эквивалентно следующему:
struct FooInt
{
int bar;
void doSomething(int param) {/* do stuff using int */}
}
Следовательно, компилятор должен иметь доступ к реализации методов, чтобы создать экземпляр с аргументом шаблона (в данном случае int
). Если эти реализации не были в заголовке, они не были бы доступны, поэтому компилятор не смог бы создать экземпляр шаблона.
Общим решением для этого является запись объявления шаблона в заголовок файла, затем реализовать класс в файле реализации (например, .tpp) и включить этот файл реализации в конец заголовка.
// Foo.h
template
struct Foo
{
void doSomething(T param);
};
#include "Foo.tpp"
// Foo.tpp
template
void Foo::doSomething(T param)
{
//implementation
}
Таким образом, реализация по-прежнему отделена от объявления, но доступен компилятору.
Другое решение состоит в том, чтобы сохранить реализацию отдельно и явно создать все экземпляры шаблона, которые вам понадобятся:
// Foo.h
// no implementation
template struct Foo { ... };
//----------------------------------------
// Foo.cpp
// implementation of Foo's methods
// explicit instantiations
template class Foo;
template class Foo;
// You will only be able to use Foo with int or float
Если мое объяснение isn ' t достаточно ясно, вы можете взглянуть на C ++ Super-FAQ по этому вопросу .
Это может произойти, если вы запускаете клиент и сервер на одном компьютере. Когда вы используете IE для общения с машиной, на которой запущен tomcat, убедитесь, что это разные машины.
Кроме того, вам необходимо убедиться, что серверный компьютер присоединен к домену, указанному в keytab (testdomain.ourcompany.co.uk), иначе вы можете вернуться к NTLM. Ваш keytab все еще может работать, даже если ваш сервер находится на машине, не присоединенной к домену (вы увидите красивую расшифровку keytab, которую вы показали), но IE может запутаться и не сделать правильные вещи.
AD действительно любит говорить arcfour-hmac только для Server 2003, поэтому вам нужно убедиться, что вы правильно настроили это в вашем файле krb5.ini.
Вы можете правильно создать keytab следующим образом:
C:\>ktpass -princ HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK -mapuser ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK -crypto RC4-HMAC-NT -ptype K
RB5_NT_PRINCIPAL -pass * -out ourweb.keytab
Targeting domain controller: test-dc.ourcompany.co.uk
Using legacy password setting method
Successfully mapped HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK to ourweb.testdomain.ourcompany.co.uk.
Key created.
Output keytab to ourweb.keytab:
Keytab version: 0x502
keysize 75 HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK ptype 1 (KRB5_NT_PRINCIPAL)
vno 3 etype 0x17 (RC4-HMAC) keylength 16 (0x0fd0e500225c4fca9a63a9998b17ca32)
Я не видел, чтобы вы установили файл krb5.ini. Вам нужно будет правильно установить это на вашем сервере (расположение по умолчанию C: \ WINDOWS \ krb5.ini):
[domain_realm]
.testdomain.ourcompany.co.uk = TESTDOMAIN.OURCOMPANY.CO.UK
testdomain.ourcompany.co.uk = TESTDOMAIN.OURCOMPANY.CO.UK
[libdefaults]
default_realm = TESTDOMAIN.OURCOMPANY.CO.UK
permitted_enctypes = aes128-cts aes256-cts arcfour-hmac-md5
default_tgs_enctypes = aes128-cts aes256-cts arcfour-hmac-md5
default_tkt_enctypes = aes128-cts aes256-cts arcfour-hmac-md5
[realms]
VERDAD.LOCAL = {
kdc = test-dc.ourcompany.co.uk
admin_server = test-dc.ourcompany.co.uk
default_domain = TESTDOMAIN.OURCOMPANY.CO.UK
}
Вам также может потребоваться установить следующие свойства (если вы пытаетесь запустить это из IDE):
<systemProperties>
<java.security.krb5.kdc>test-dc.ourcompany.co.uk</java.security.krb5.kdc>
<java.security.krb5.realm>TESTDOMAIN.OURCOMPANY.CO.UK</java.security.krb5.realm>
</systemProperties>
Я использовал плагин org.codehaus.mojo для maven, который устанавливает их в файле pom следующим образом:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<configuration>
<server>tomcat-development-server</server>
<port>8080</port>
<path>/SecurityTest</path>
<systemProperties>
<java.security.krb5.kdc>test-dc.ourcompany.co.uk</java.security.krb5.kdc
<java.security.krb5.realm>TESTDOMAIN.OURCOMPANY.CO.UK</java.security.krb5.realm>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>