如何在Android上使用Xamarin启用NTLM和TLS 1.2?
我正在使用Android上的Xamarin客户端应用程序,我需要TLS 1.2和NTLM。如何在Android上使用Xamarin启用NTLM和TLS 1.2?
到目前为止,我一直在使用常规System.Net.HttpClientHandler和它工作得很好 - 它看起来像这样:
new System.Net.Http.HttpClientHandler()
{
Credentials = credentials
};
但现在我有一个新的客户,我需要TLS 1.2。所以我做了针对Android的代码:
new Xamarin.Android.Net.AndroidClientHandler()
{
Credentials = credentials
};
与环境变量:
XA_HTTP_CLIENT_HANDLER_TYPE=Xamarin.Android.Net.AndroidClientHandler
现在,这种AndroidClientHandler工作尽可能的证书去。但我也需要NTLM才能工作。对我来说,似乎AndroidClientHandler只支持Basic和Digest身份验证方案(请参阅Xamarin.Android.Net.AuthenticationScheme)。
我也尝试过使用ModernHttpClient,但在我看来,它使用Mono的方式与System.Net.Http.HttpClientHandler一样,所以TLS 1.2在那里也不起作用。
在我看来,这应该是一个很常见的情况,但我仍然无法在网上找到相关示例。我希望我只是错过了一些明显的东西。你们怎么解决这个问题?
我相信这将是有益的你读通过:
/// <para>
/// The class supports pre-authentication of requests albeit in a slightly "manual" way. Namely, whenever a request to a server requiring authentication
/// is made and no authentication credentials are provided in the <see cref="PreAuthenticationData"/> property (which is usually the case on the first
/// request), the <see cref="RequestNeedsAuthorization"/> property will return <c>true</c> and the <see cref="RequestedAuthentication"/> property will
/// contain all the authentication information gathered from the server. The application must then fill in the blanks (i.e. the credentials) and re-send
/// the request configured to perform pre-authentication. The reason for this manual process is that the underlying Java HTTP client API supports only a
/// single, VM-wide, authentication handler which cannot be configured to handle credentials for several requests. AndroidClientHandler, therefore, implements
/// the authentication in managed .NET code. Message handler supports both Basic and Digest authentication. If an authentication scheme that's not supported
/// by AndroidClientHandler is requested by the server, the application can provide its own authentication module (<see cref="AuthenticationData"/>,
/// <see cref="PreAuthenticationData"/>) to handle the protocol authorization.</para>
/// <para>AndroidClientHandler also supports requests to servers with "invalid" (e.g. self-signed) SSL certificates. Since this process is a bit convoluted using
/// the Java APIs, AndroidClientHandler defines two ways to handle the situation. First, easier, is to store the necessary certificates (either CA or server certificates)
/// in the <see cref="TrustedCerts"/> collection or, after deriving a custom class from AndroidClientHandler, by overriding one or more methods provided for this purpose
/// (<see cref="ConfigureTrustManagerFactory"/>, <see cref="ConfigureKeyManagerFactory"/> and <see cref="ConfigureKeyStore"/>). The former method should be sufficient
/// for most use cases, the latter allows the application to provide fully customized key store, trust manager and key manager, if needed. Note that the instance of
/// AndroidClientHandler configured to accept an "invalid" certificate from the particular server will most likely fail to validate certificates from other servers (even
/// if they use a certificate with a fully validated trust chain) unless you store the CA certificates from your Android system in <see cref="TrustedCerts"/> along with
/// the self-signed certificate(s).</para>
这基本上说:它支持Basic
和Digest
认证。如果服务器请求的AndroidClientHandler
中不支持认证方案,则应用程序可以提供它自己的认证模块来处理协议授权。
然后,我们可以看到,RequestedAuthentication
属性将列出的关于服务器:支持的每个方案
/// <summary>
/// If the website requires authentication, this property will contain data about each scheme supported
/// by the server after the response. Note that unauthorized request will return a valid response - you
/// need to check the status code and and (re)configure AndroidClientHandler instance accordingly by providing
/// both the credentials and the authentication scheme by setting the <see cref="PreAuthenticationData"/>
/// property. If AndroidClientHandler is not able to detect the kind of authentication scheme it will store an
/// instance of <see cref="AuthenticationData"/> with its <see cref="AuthenticationData.Scheme"/> property
/// set to <c>AuthenticationScheme.Unsupported</c> and the application will be responsible for providing an
/// instance of <see cref="IAndroidAuthenticationModule"/> which handles this kind of authorization scheme
/// (<see cref="AuthenticationData.AuthModule"/>
/// </summary>
这就告诉我们,如果返回Unsupported
作为我们AuthenticationScheme
,然后我们需要提交我们自己的IAndroidAuthenticationModule
来应对挑战。
这里是AuthenticationScheme
的枚举:
namespace Xamarin.Android.Net
{
/// <summary>
/// Authentication schemes supported by <see cref="AndroidClientHandler"/>
/// </summary>
public enum AuthenticationScheme
{
/// <summary>
/// Default value used in <see cref="AuthenticationData.Scheme"/>
/// </summary>
None,
/// <summary>
/// <see cref="AndroidClientHandler"/> doesn't support this scheme, the application must provide its own value. See <see cref="AuthenticationData.Scheme"/>
/// </summary>
Unsupported,
/// <summary>
/// The HTTP Basic authentication scheme
/// </summary>
Basic,
/// <summary>
/// The HTTP Digest authentication scheme
/// </summary>
Digest
}
}
因此,我们必须通过具体的实现扩展这个接口来实现自定义IAndroidAuthenticationModule
:
然后你会将该实现传递给AuthenticationData.AuthModule
属性:
你会再传递到主客户端的PreAuthenticationData
财产。
我希望这有助于!
什么关于Xamarin.Forms? Droid版本无法连接到TLS 1.2网站。 加载图片:获取https://randomuser.me/api/portraits/med/men/85.jpg流的错误:System.Net.WebException:错误:SecureChannelFailure(验证或解密失败。)---> System.IO.IOException:验证或解密失败。 ---> System.IO.IOException:认证或解密失败。 ---> Mono.Security.Protocol.Tls.TlsException:认证或解密失败。 –
Xamarin Forms与底层的TLS API无关。您的握手与此服务器失败,因此您必须调查原因。我上面的答案是使用NTLM作为您的身份验证方案与新的AndroidClientHandler。 –
最近TLS 1.2来到Mono/Xamarin。您最近使用的构建版本是多久? http://tirania.org/blog/archive/2016/Sep-30.html – scotru
嗨scotru,并感谢您的答案!我正在使用Mono.Android运行时4.0.30319。我想这就是我用最新版本的Xamarin获得的。 – Christian
我不认为Miguel所引用的更新已经将它变成了Mono.Android运行时版本。它看起来像ModernHttpClient应该与TLS 1.2一起工作。 https://wolfprogrammer.com/2016/08/23/enabling-tls-1-2-in-xamarin-forms/ – scotru