IE使用NTLM身份验证时随机发送空POST主体(使用angular to Spring)

时间:2016-12-01 18:36:36

标签: angularjs spring internet-explorer authentication ntlm

我们看到IE 11中缺少POST的看似随机调用的问题。进一步检查后,来自浏览器的请求包括NTLM协商令牌。我们也经常在GET上看到这个标记,但它们不受身体问题的影响,因为他们没有身体问题。 Chrome和FF没有这个问题。

进一步的调查显示,如果我们的会话超时并且浏览器被重新刷新,那么我们将在此之后以大约1-2分钟的间隔始终看到此问题。我的理解是,如果IE"期望" 401,然后它将不包括POST主体,因为期望再次发生NTLM握手。

我们有一个角度应用程序(当前混合了Angular 1和2,但在此之前发生了1)。角度应用程序使用对我们的Spring启动应用程序进行restful webservice调用。我们使用华夫饼为NTLM auth

// Shiro-Waffle / Security
'com.github.dblock.waffle:waffle-parent:1.7.3',
'com.github.dblock.waffle:waffle-shiro:1.7.3',
'org.apache.shiro:shiro-core:1.2.3',
'org.apache.shiro:shiro-web:1.2.3',

https://blogs.msdn.microsoft.com/ieinternals/2010/11/21/challenge-response-authentication-and-zero-length-posts/

我有一个糟糕的解决方法,我将在下面作为答案发布,但我根本不喜欢它。

2 个答案:

答案 0 :(得分:7)

好的,我发现了一个注册表黑客。基本上,IE主动发送NTLM凭证,而不从服务器发送401。发送" pre auth" IE将省略POST主体(如果请求是POST。)如果会话已经有效并且服务器已经授权您,则它允许请求通过而没有正文并且将导致服务器上的错误(假设正文是你的POST需要。)

因此,正常的NTLM协商看起来像

  • 来自客户的请求(使用POST正文) - >服务器返回401 www-authenticate:negotiate,www-authenticate:NTLM
  • 客户端发送 使用NTLM令牌的附加请求(没有帖子正文) - >服务器返回401 NTLM令牌
  • 客户端发送第3个会话请求(使用POST正文)并返回服务器 200

通过此优化

  • 客户端需要401并发送NTLM令牌(没有身体) - >服务器返回401服务器令牌
  • 客户端发送第2个会话请求(带正文) - >服务器返回200

出现问题

  • 客户需要401并发送NTLM令牌(无主体) - >服务器处理请求并收到内部错误(可能是500)

要添加的注册表项会阻止此"优化"

HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Internet Settings/ 
Add the following registry value: 
Value Name: DisableNTLMPreAuth
Data Type: REG_DWORD
Value: 1

或者将这些条目保存到您计算机上的.reg文件中,然后双击它

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\]
"DisableNTLMPreauth"=dword:00000001

我不确定为什么IE认为它必须重新验证,但是从广泛的测试看起来,一旦IE有会话超时或会话失效并且它从服务器获得401,它想要重新每隔1-2分钟后验证一次。这可能与您在身份验证时所处的URL有关,因为您可能不在根。我提供的第一个链接谈论了很多关于IE浏览器URL的挑剔以及它如何猜测应该授权什么以及什么不应该基于路径。

相关文章:

Zero Length POSTS

NTLM Pre-Auth

NTLM Pre-Auth

NTLM Pre-Auth jcifs

答案 1 :(得分:0)

我创建了一个shiro过滤器,我将其作为链中的最后一个过滤器(Groovy)

CPP coding guidelines
MEMORY MANAGEMENT

BUFFER OVERRUNS

STATIC BUFFER OVERRUNS

A static buffer overrun occurs when a buffer, which has been declared on the stack, is written to with more data than it was allocated to hold. The less apparent versions of this error occur when unverified user input data is copied directly to a static variable, causing potential stack corruption.

HEAP OVERRUNS

Heap overruns, like static buffer overruns, can lead to memory and stack corruption. Because heap overruns occur in heap memory rather than on the stack, some people consider them to be less able to cause serious problems; nevertheless, heap overruns require real programming care and are just as able to allow system risks as static buffer overruns.
Soulflower - Oil and Handmade Organic Soap
Perfect Remedy For All Skin & Hair Problems. Buy Now!

ARRAY INDEXING ERRORS

Array indexing errors also are a source of memory overruns. Careful bounds checking and index management will help prevent this type of memory overrun.
1. Use memcpy_s instead of memcpy
2. In memcpy_s destination size should be more than or equal to source size
3. If destination size is less than source size, relevant handling to be implemented. e.g.
a. creating fatal error log and throwing exception
b. copying truncated data

MEMORY LEAKS

It is the responsibility of each application to “free” dynamically requested memory when it is finished using it. When an application dynamically allocates memory, and does not free that memory when it is finished using it, that program has a memory leak.
1. Differentiate between delete of object and delete [] of array of objects.
Incorrect
char* myCharArray = new char[BUFF_SIZE];
delete myCharArray;
Correct
char* myCharArray = new char[BUFF_SIZE];
delete [] myCharArray;
2. While deleting check for NULL. If not NULL, delete and set to NULL
Correct
If(ptrData!= NULL)
{
delete ptrData;
ptrData=NULL;
}

3. Check size of STL container before iterating over its elements.

4. If STL containers contain pointers. Iterate over elements and delete each pointer individually. And clear container after this.
Incorrect

std::list<StructImageList*> listFinalImageIds //allocation and appending of pointers to list. ………

m_listFinalImageIds.clear();

Correct

std::list<StructImageList*> listFinalImageIds //allocation and appending of pointers to list. …… //clean up after list use is completed.

if(!m_listFinalImageIds.empty())

{ for(std::list<StructImageList*>::iterator it = m_listFinalImageIds.begin(); it != m_listFinalImageIds.end(); it++){ StructImageList* pData = *(it);

if(pData!= NULL) {

delete pData; pData = NULL;

}

}

m_listFinalImageIds.clear();
5. Use of BSTR. use smart pointer _bstr_t for handling of BSTRs.

https://msdn.microsoft.com/en-us/library/zthfhkd6.aspx


more at : 

}

我们的NegotiateAuthenticationFilter扩展了waffle.shiro.negotiate.NegotiateAuthenticationFilter并且非常直接。

这会看到空体POST请求到来(原谅请求?.request垃圾 - 不准备好)并拒绝访问,从而给IE提供了它所期望的内容。由于我们拒绝访问,因此401会进行并且握手开始。然后,当200呈现时,IE释放身体,我们是AOK。但这可以作为一种解决方案。