Tôi có một máy chủ HTTP đơn giản xác thực khách hàng bằng giao thức Thương lượng. Nó sử dụng các cuộc gọi SSPI để có được các thông tin máy chủ và thiết lập bối cảnh bảo mật. Máy chủ nằm trong miền và đang chạy thay mặt cho người dùng miền. Mọi thứ hoạt động tốt và tôi nhận được phản hồi HTTP 200 nếu tôi khởi động máy chủ ở chế độ bảng điều khiển. Tuy nhiên khi tôi chạy nó như một dịch vụ tôi nhận được lỗi SEC_E_INVALID_HANDLE. Đây là những gì xảy ra khi tôi bắt đầu nó ở chế độ điều khiển:AcceptSecurityContext không thành công khi ứng dụng đang chạy dưới dạng dịch vụ
1.Client gửi yêu cầu HTTP GET http://localhost:8082
2.Server đáp ứng với WWW-Authenticate: Negotiate tiêu đề.
3.Client gửi Authorization header và bao gồm các dữ liệu sau:
60 73 06 06 2B 06 01 05 05 02 A0 69 30 67 A0 30 `s..+..... i0g 0
30 2E 06 0A 2B 06 01 04 01 82 37 02 02 0A 06 09 0...+....7.....
2A 86 48 82 F7 12 01 02 02 06 09 2A 86 48 86 F7 *H÷......*H÷
12 01 02 02 06 0A 2B 06 01 04 01 82 37 02 02 1E ......+....7...
A2 33 04 31 4E 54 4C 4D 53 53 50 00 01 00 00 00 ¢3.1NTLMSSP.....
97 B2 08 E2 04 00 04 00 2D 00 00 00 05 00 05 00 ².â....-.......
28 00 00 00 06 01 B1 1D 00 00 00 0F 50 41 43 45 (.....±.....PACE
4D 42 4C 41 48 MBLAH
4.Server đáp ứng với HTTP 401 lỗi và thương lượng tiêu đề khiến để tiếp tục:
A1 81 CE 30 81 CB A0 03 0A 01 01 A1 0C 06 0A 2B ¡Î0Ë ....¡...+
06 01 04 01 82 37 02 02 0A A2 81 B5 04 81 B2 4E ....7...¢µ.²N
54 4C 4D 53 53 50 00 02 00 00 00 08 00 08 00 38 TLMSSP.........8
00 00 00 15 C2 89 E2 B0 3B BE 20 45 33 FD 92 80 ....Ââ°;¾ E3ý
04 E7 01 00 00 00 00 72 00 72 00 40 00 00 00 06 .ç[email protected]
01 B1 1D 00 00 00 0F 42 00 4C 00 41 00 48 00 02 .±.....B.L.A.H..
00 08 00 42 00 4C 00 41 00 48 00 01 00 0A 00 50 ...B.L.A.H.....P
00 41 00 43 00 45 00 4D 00 04 00 10 00 62 00 6C .A.C.E.M.....b.l
00 61 00 68 00 2E 00 63 00 6F 00 6D 00 03 00 1C .a.h...c.o.m....
00 50 00 61 00 63 00 65 00 6D 00 2E 00 62 00 6C .P.a.c.e.m...b.l
00 61 00 68 00 2E 00 63 00 6F 00 6D 00 05 00 10 .a.h...c.o.m....
00 62 00 6C 00 61 00 68 00 2E 00 63 00 6F 00 6D .b.l.a.h...c.o.m
00 07 00 08 00 5D B3 C5 9A 0F 17 D1 01 00 00 00 .....]³Å..Ñ....
00 .
5.Client gửi Authorization tiêu đề:
A1 77 30 75 A0 03 0A 01 01 A2 5A 04 58 4E 54 4C ¡w0u ....¢Z.XNTL
4D 53 53 50 00 03 00 00 00 00 00 00 00 58 00 00 MSSP.........X..
00 00 00 00 00 58 00 00 00 00 00 00 00 58 00 00 .....X.......X..
00 00 00 00 00 58 00 00 00 00 00 00 00 58 00 00 .....X.......X..
00 00 00 00 00 58 00 00 00 15 C2 88 E2 06 01 B1 .....X....Ââ..±
1D 00 00 00 0F C0 BD 0C 5B F5 F9 35 FE 78 6D 08 .....À½.[õù5þxm.
BF 7B D9 CC E3 A3 12 04 10 01 00 00 00 F5 17 A7 ¿{ÙÌã£.......õ.§
50 2D 22 9A 84 00 00 00 00 P-"....
6.Server trả lời bằng HTTP 200 và ne phần đầu gotiate:
A1 1B 30 19 A0 03 0A 01 00 A3 12 04 10 01 00 00 ¡.0. ....£......
00 43 87 E0 88 C1 36 E3 A9 00 00 00 00 .CàÁ6ã©....
Bây giờ nếu tôi chạy các ứng dụng như một dịch vụ tôi sẽ nhận được phản ứng gần như giống hệt nhau, nhưng AcceptSecurityContext sẽ thất bại trên bướC# 6 và trả về lỗi SEC_E_INVALID_HANDLE. Tôi tự hỏi tại sao nó sẽ thất bại nếu tôi chạy cùng một ứng dụng và chỉ định cùng một người dùng như một bản ghi dịch vụ đăng nhập? Có thể nào đó bằng cách nào đó liên quan đến sự cô lập phiên 0? Ngoài ra còn có một cách để khắc phục sự cố tốt hơn, tôi không thấy bất kỳ thông báo lỗi nào trong trình xem sự kiện và lỗi xử lý không hợp lệ không nói nhiều về những gì bị thiếu.
Đây là mã máy chủ để xác thực:
public static WinAuthResult Authenticate(string clientId, byte[] clientTokenBytes, string securityPackage, ILogger logger)
{
if (clientTokenBytes == null || clientTokenBytes.Length == 0)
{
ClearContext(clientId);
throw new Win32Exception(Secur32.SEC_E_INVALID_TOKEN);
}
var serverCredExpiry = new Secur32.SECURITY_INTEGER();
var serverCredHandle = new Secur32.SecHandle();
var acquireResult = Secur32.AcquireCredentialsHandle(null, securityPackage, Secur32.SECPKG_CRED_INBOUND, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero, out serverCredHandle, out serverCredExpiry);
if (acquireResult != Secur32.SEC_E_OK)
throw new Win32Exception(acquireResult);
var oldContextExists = contexts.ContainsKey(clientId);
var oldContextHandle = GetContextHandle(clientId);
var newContextHandle = new Secur32.SecHandle();
var clientToken = new Secur32.SecBufferDesc(clientTokenBytes);
var outputToken = new Secur32.SecBufferDesc(61440);
var contextAttributes = (uint)0;
var outputCresExpiry = new Secur32.SECURITY_INTEGER();
int acceptResult;
if (!oldContextExists)
{
acceptResult = Secur32.AcceptSecurityContext(
ref serverCredHandle,
IntPtr.Zero,
ref clientToken,
0,
Secur32.SECURITY_NATIVE_DREP,
ref newContextHandle,
ref outputToken,
out contextAttributes,
out outputCresExpiry);
}
else
{
acceptResult = Secur32.AcceptSecurityContext(
ref serverCredHandle,
ref oldContextHandle,
ref clientToken,
0,
Secur32.SECURITY_NATIVE_DREP,
ref newContextHandle,
ref outputToken,
out contextAttributes,
out outputCresExpiry);
}
if (acceptResult == Secur32.SEC_E_OK)
{
ClearContext(clientId);
return new WinAuthResult(false, outputToken.GetSecBufferByteArray());
}
else if (acceptResult == Secur32.SEC_I_CONTINUE_NEEDED)
{
contexts[clientId] = newContextHandle;
return new WinAuthResult(true, outputToken.GetSecBufferByteArray());
}
else
{
ClearContext(clientId);
throw new Win32Exception(acceptResult);
}
}
Trong cả hai trường hợp tôi đang cố gắng để truy cập trang web từ cùng một máy mà máy chủ đang chạy và với người sử dụng cùng một tên miền. Ngoài ra tôi đang sử dụng cùng một tên miền người dùng để chạy giao diện điều khiển ứng dụng và cửa sổ dịch vụ. Vấn đề này không thể sao chép được trên Windows Server 2003, điều này khiến tôi nghĩ rằng đó là một cái gì đó liên quan đến các tính năng bảo mật mới.
Cảm ơn bạn đã phản hồi. Ban đầu tôi đã sao chép vấn đề này với bộ lọc Tomcat + Waffle và sau đó quyết định tạo một ví dụ nhỏ trên C# với máy chủ HTTP tự viết chỉ trích xuất các tiêu đề của khách hàng và thực hiện các cuộc gọi đến SSPI. Trong cả hai trường hợp, tôi nhận được cùng một hành vi - AcceptSecurityContext không thành công khi ứng dụng đang chạy dưới dạng dịch vụ. Thật không may tôi không thể sử dụng các thiết lập nâng cao IIS vì cuối cùng tôi cần phải làm cho nó làm việc cho Tomcat. – username
Về bản cập nhật. Giao thức thương lượng không nhất thiết phải sử dụng Kerberos và tôi nghĩ NTLM của tôi được sử dụng khi tôi đăng nhập từ cùng một máy chủ (khi tôi thử nghiệm các công cụ khác mà họ đã đưa ra kết quả tương tự và báo cáo NTLM). Tôi không gặp bất kỳ vấn đề gì nếu tôi đăng nhập từ xa hoặc cố gắng sử dụng địa chỉ IP hoặc chạy nó như một ứng dụng giao diện điều khiển. Trường hợp duy nhất không hoạt động là chạy ứng dụng này như một dịch vụ. Có vẻ như có những hạn chế hoặc đặc quyền nhất định đối với các dịch vụ mà tôi cần phải thay đổi. – username
Bản cập nhật cuối cùng của bạn đã giải quyết được sự cố của tôi. Cảm ơn bạn rất nhiều! – username