- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个看起来像这样的解决方案:
IdentitySErvice4 和 WCF 服务都在使用功能证书。客户端正在使用从 Windows 应用商店加载的客户端证书。客户端服务通过第三方软件从智能卡安装到 Windows 应用商店。如果卡被移除,则证书将从商店中移除。
流程如下所示:
1 客户端从商店加载证书并将其绑定(bind)到 takeenhandler,如下所示:
public override TokenClient GetTokenClient(string host, string port)
{
var certificate = SmartCardHandler.GetInstance().Result.CurrentCertificate();
if (certificate == null)
throw new Exception("Certificate is missing");
var handler = new WebRequestHandler();
handler.ServerCertificateValidationCallback = PinPublicKey;
var url = $"https://{host}:{port}/connect/token";
handler.ClientCertificates.Add(certificate);
return new TokenClient(url, ClientTypes.Siths, "secret", handler);
}
token = await tokenClient.RequestCustomGrantAsync(ClientTypes.Siths, "MyApp.wcf offline_access");
2. 客户端将请求发送到 IdentityServices,IdentityServices 读取客户端证书并使用它进行身份验证并生成返回的客户端 token 。
3.客户端使用客户端证书创建到服务的 WCF channel , token 也像这样附加到该 channel
private async Task<ChannelFactory<T>> CreateChannelFactory(LoginTypeBase loginType, MyAppToken token)
{
var service = await _ConsulService.GetServiceBlocking(loginType.MyAppServicesToUse, forceRefresh: true, token: new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token);
if (service == null)
throw new MyAppServiceCommunicationException();
var cert = loginType.ClientCertificate;
var uri = loginType.GetMyAppClientServiceURL(service.Address, service.Port);
var header = AddressHeader.CreateAddressHeader(nameof(MyAppToken), nameof(MyAppToken), token);
var endpointAddress = new EndpointAddress(uri, header);
ServiceEndpoint serviceEndpoint = null;
if (loginType.LoginType == LoginType.SmartCard || loginType.LoginType == LoginType.UsernamePasswordSLL)
{
var binding = new NetHttpsBinding("netHttpsBinding");
binding.Security.Mode = BasicHttpsSecurityMode.Transport;
if (loginType.LoginType == LoginType.SmartCard)
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
else
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
serviceEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(T)), binding, endpointAddress);
}
else
{
var binding = new NetHttpBinding("netHttpBinding");
serviceEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(T)), binding, endpointAddress);
}
serviceEndpoint.EndpointBehaviors.Add(new ProtoEndpointBehavior());
serviceEndpoint.EndpointBehaviors.Add(new CustomMessageInspectorBehavior());
var v = new ChannelFactory<T>(serviceEndpoint);
if (loginType.LoginType == LoginType.SmartCard)
{
v.Credentials.ClientCertificate.Certificate = cert;
//v.Credentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindByThumbprint, cert.Thumbprint);
}
return v;
}
}
4. 客户端将第一条消息发送到 WCF 服务。当消息被转发到 WCF 服务并根据 IdentityService4 验证 token 时,第三方软件将作出 react 并要求客户端证书的 pin。
真正的代理用于在需要时切换到另一个服务。在这种情况下,它只有一个在线 WCF 服务的 URL。
public override IMessage Invoke(IMessage msg)
{
var methodCall = (IMethodCallMessage)msg;
var method = (MethodInfo)methodCall.MethodBase;
var channel = GetChannel(false);
var retryCount = 3;
do
{
try
{
var result = method.Invoke(channel, methodCall.InArgs);
var returnmessage = new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
return returnmessage;
}
catch (Exception e)
{
if (e is TargetInvocationException && e.InnerException != null)
{
if (e.InnerException is FaultException)
return new ReturnMessage(ErrorHandler.Instance.UnwrapAgentException(e.InnerException), msg as IMethodCallMessage);
if (e.InnerException is EndpointNotFoundException || e.InnerException is TimeoutException)
channel = GetChannel(true);
}
retryCount--;
}
} while (retryCount > 0);
throw new Exception("Retrycount reached maximum. Customproxy Invoke");
}
5 客户端每 30 分钟刷新一次客户端 token
private async Task RefreshToken(LoginTypeBase loginType)
{
if (_MyAppToken == null)
return;
var tokenClient = await GetTokenClient(loginType);
var result = !string.IsNullOrEmpty(_refreshToken) ? await tokenClient.RequestRefreshTokenAsync(_refreshToken, _cancelToken.Token) : await tokenClient.RequestCustomGrantAsync("siths", cancellationToken: _cancelToken.Token);
if (string.IsNullOrEmpty(result.AccessToken))
throw new Exception($"Accesstoken har blivit null försökte refresha med {tokenClient.ClientId} {_refreshToken} {DateTime.Now}");
_MyAppToken.Token = result.AccessToken;
_refreshToken = result.RefreshToken;
}
这一切在开始时都很好,但是在随机调用之后它会失败,有时是它无法联系的 WCF 服务,此时 IdentityService 可能仍然能够与之通信。异常在上面第 4 点所示的代码中抛出,如下所示:
e.ToString() "System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority '139.107.245.141:44310'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.\r\n at System.Net.HttpWebRequest.GetResponse()\r\n at System.ServiceModel.Channels.HttpChannelFactory
1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan
1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)\r\n at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)\r\n at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)\r\n at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)\r\n at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)\r\n at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)\r\n\r\nException rethrown at [0]: \r\n at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)\r\n at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)\r\n at myapp.ServiceContracts.ImyappClientService.LogData(GeneralFault generalFault)\r\n --- End of inner exception stack trace ---\r\n
timeout)\r\n --- End of inner exception stack trace
---\r\n\r\nServer stack trace: \r\n at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException
webException, HttpWebRequest request, HttpAbortReason abortReason)\r\n
at
System.ServiceModel.Channels.HttpChannelFactory
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)\r\n at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)\r\n at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)\r\n at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)\r\n at myapp.Client.Main.Classes.Service_Management.CustomProxy`1.Invoke(IMessage msg) in C:\myapp\Produkter\myapp Utveckling\Solution\myapp.Client.Main\Classes\Service Management\CustomProxy.cs:line 74" string
有时它会首先使 WCF 服务失败,然后再次工作然后再次失败(完全相同的 vall),而当 IdentityService4 连接开始失败时,它每次都会失败并出现此异常:
token.Exception.ToString() "System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.\r\n at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)\r\n at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)\r\n --- End of inner exception stack trace ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Net.Http.HttpClient.d__58.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at IdentityModel.Client.TokenClient.d__26.MoveNext()" string
此代码用于在客户端测试 IdentityService 连接
就是 token 。将持有上面异常的异常。
公共(public)静态异步任务 LoginSiths() { 尝试 { 变种主机=“139.107.245.141”; 变量端口 = 44312; var url = $"https://{host}:{port}/connect/token";
var handler = new WebRequestHandler();
handler.ServerCertificateValidationCallback = PinPublicKey;
handler.ClientCertificates.Add(SmartCardHandler.GetInstance().Result.CurrentCertificate());
var client = new TokenClient(url, ClientTypes.Siths, "secret.ro101.orbit", handler);
TokenResponse token = await client.RequestCustomGrantAsync(ClientTypes.Siths, "orbit.wcf offline_access");
if (token.IsError)
MessageBox.Show("Failed!");
else
MessageBox.Show("Success!");
}
catch (Exception ex)
{
MessageBox.Show("Exception : " + ex.ToString());
}
}
唯一的出路是重启客户端(不需要重启任何服务)。客户端重新启动后,它可以像以前一样再次登录并进行调用。
如果我将它添加到我的客户端的开头:
ServicePointManager.MaxServicePointIdleTime = 1;
然后我会在登录后几乎立即遇到问题(此时变化缓慢)。
有什么方法可以知道为什么我会收到 SSL 异常?
Note, this post have been updated 2017-04-07 01:00, this is to give a more collected picture of what's going on. The problem really consisted of two problems, one is still active and is explained above, the other was due to a bug in IdentityService4 that we found a workaround for.
最佳答案
如果您的问题出在客户端,我建议您对 ServicePointManager
使用 AppDomain
隔离,而不是一些反射 hack(它伤害了我的眼睛:) - 类似于.NET https requests with different security protocols across threads 的例子
即:
public class Client : MarshalByRefObject {
public string GetResponse(string address) {
// you can get crazy with ServicePointManager settings here
// + actually do the request
}
}
public sealed class Isolated<T> : IDisposable where T : MarshalByRefObject {
private AppDomain _domain;
public Isolated() {
_domain = AppDomain.CreateDomain("Isolated:" + Guid.NewGuid(), null,
AppDomain.CurrentDomain.SetupInformation);
var type = typeof(T);
Value = (T)_domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
}
public T Value { get; private set; }
public void Dispose() {
if (_domain == null) return;
AppDomain.Unload(_domain);
_domain = null;
}
}
并将通信包含在类似的内容中:
using (var isolated = new Isolated<Client>()) {
string response = isolated.Value.GetResponse(url);
}
关于c# - 带有客户端证书的 WCF 应用程序在一段时间后失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43113440/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!