mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-28 05:57:47 +08:00
reuse usertokenpolicy used in connect for Reconnect / "ReactivateSession" (#3581)
* reuse usertokenpolicy * change assert not null to assert ignore when null * reportauditevent -> Utils.Clone(session?.IdentityToken?.Token) * use standard credentials * only assign to endpoint when not null, in UpdateSession -> also update m_userTokenSecurityPolicyUri, change endpoint configuration only on cloned object * keep using m_userTokenSecurityPolicyUri in Encrypt * use 'cleaner clone'
This commit is contained in:
@@ -1283,6 +1283,8 @@ namespace Opc.Ua.Client
|
|||||||
previousServerNonce,
|
previousServerNonce,
|
||||||
m_endpoint.Description.SecurityMode);
|
m_endpoint.Description.SecurityMode);
|
||||||
|
|
||||||
|
m_userTokenSecurityPolicyUri = tokenSecurityPolicyUri;
|
||||||
|
|
||||||
// sign data with user token.
|
// sign data with user token.
|
||||||
SignatureData userTokenSignature = identityToken.Sign(
|
SignatureData userTokenSignature = identityToken.Sign(
|
||||||
dataToSign,
|
dataToSign,
|
||||||
@@ -2324,7 +2326,7 @@ namespace Opc.Ua.Client
|
|||||||
UserTokenPolicy identityPolicy = endpoint.FindUserTokenPolicy(
|
UserTokenPolicy identityPolicy = endpoint.FindUserTokenPolicy(
|
||||||
m_identity.TokenType,
|
m_identity.TokenType,
|
||||||
m_identity.IssuedTokenType,
|
m_identity.IssuedTokenType,
|
||||||
endpoint.SecurityPolicyUri);
|
m_userTokenSecurityPolicyUri ?? endpoint.SecurityPolicyUri);
|
||||||
|
|
||||||
if (identityPolicy == null)
|
if (identityPolicy == null)
|
||||||
{
|
{
|
||||||
@@ -2337,18 +2339,21 @@ namespace Opc.Ua.Client
|
|||||||
}
|
}
|
||||||
|
|
||||||
// select the security policy for the user token.
|
// select the security policy for the user token.
|
||||||
string? tokenSecurityPolicyUri = identityPolicy.SecurityPolicyUri;
|
if (m_userTokenSecurityPolicyUri == null)
|
||||||
if (string.IsNullOrEmpty(tokenSecurityPolicyUri))
|
|
||||||
{
|
{
|
||||||
tokenSecurityPolicyUri = endpoint.SecurityPolicyUri;
|
string? tokenSecurityPolicyUri = identityPolicy.SecurityPolicyUri;
|
||||||
|
if (string.IsNullOrEmpty(tokenSecurityPolicyUri))
|
||||||
|
{
|
||||||
|
tokenSecurityPolicyUri = endpoint.SecurityPolicyUri;
|
||||||
|
}
|
||||||
|
m_userTokenSecurityPolicyUri = tokenSecurityPolicyUri;
|
||||||
}
|
}
|
||||||
m_userTokenSecurityPolicyUri = tokenSecurityPolicyUri;
|
|
||||||
|
|
||||||
// validate server nonce and security parameters for user identity.
|
// validate server nonce and security parameters for user identity.
|
||||||
ValidateServerNonce(
|
ValidateServerNonce(
|
||||||
m_identity,
|
m_identity,
|
||||||
m_serverNonce,
|
m_serverNonce,
|
||||||
tokenSecurityPolicyUri,
|
m_userTokenSecurityPolicyUri,
|
||||||
m_previousServerNonce,
|
m_previousServerNonce,
|
||||||
m_endpoint.Description.SecurityMode);
|
m_endpoint.Description.SecurityMode);
|
||||||
|
|
||||||
@@ -2357,7 +2362,7 @@ namespace Opc.Ua.Client
|
|||||||
identityToken.UpdatePolicy(identityPolicy);
|
identityToken.UpdatePolicy(identityPolicy);
|
||||||
SignatureData userTokenSignature = identityToken.Sign(
|
SignatureData userTokenSignature = identityToken.Sign(
|
||||||
dataToSign,
|
dataToSign,
|
||||||
tokenSecurityPolicyUri);
|
m_userTokenSecurityPolicyUri);
|
||||||
|
|
||||||
// encrypt token.
|
// encrypt token.
|
||||||
identityToken.Encrypt(
|
identityToken.Encrypt(
|
||||||
|
|||||||
@@ -1072,7 +1072,7 @@ namespace Opc.Ua.Server
|
|||||||
e.SetChildValue(
|
e.SetChildValue(
|
||||||
systemContext,
|
systemContext,
|
||||||
BrowseNames.UserIdentityToken,
|
BrowseNames.UserIdentityToken,
|
||||||
Utils.Clone(session?.IdentityToken.Token),
|
Utils.Clone(session?.IdentityToken?.Token),
|
||||||
false);
|
false);
|
||||||
|
|
||||||
server.ReportAuditEvent(systemContext, e);
|
server.ReportAuditEvent(systemContext, e);
|
||||||
|
|||||||
@@ -956,6 +956,65 @@ namespace Opc.Ua.Client.Tests
|
|||||||
Utils.SilentDispose(session2);
|
Utils.SilentDispose(session2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Open a session on a channel using a usertokenpolicy from another endpoint, then reconnect (activate)
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
[Order(260)]
|
||||||
|
[TestCase(SecurityPolicies.Basic256Sha256, SecurityPolicies.Basic128Rsa15)]
|
||||||
|
public async Task ReconnectSession_ReuseUsertokenPolicyAsync(
|
||||||
|
string securityPolicy, string userTokenPolicy)
|
||||||
|
{
|
||||||
|
|
||||||
|
UserIdentity userIdentity = new UserIdentity("user1", "password"u8);
|
||||||
|
|
||||||
|
// the first channel determines the endpoint
|
||||||
|
ConfiguredEndpoint endpoint = await ClientFixture
|
||||||
|
.GetEndpointAsync(ServerUrl, securityPolicy, Endpoints)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
if (endpoint == null)
|
||||||
|
{
|
||||||
|
NUnit.Framework.Assert.Ignore(
|
||||||
|
$"No endpoint found for {securityPolicy}");
|
||||||
|
}
|
||||||
|
endpoint = new ConfiguredEndpoint(
|
||||||
|
null,
|
||||||
|
(EndpointDescription)endpoint.Description.MemberwiseClone(),
|
||||||
|
endpoint.Configuration);
|
||||||
|
endpoint.Description.SecurityMode = MessageSecurityMode.Sign;
|
||||||
|
ConfiguredEndpoint tokenPolicyEndpoint = await ClientFixture
|
||||||
|
.GetEndpointAsync(ServerUrl, userTokenPolicy, Endpoints)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
Assert.NotNull(tokenPolicyEndpoint);
|
||||||
|
|
||||||
|
UserTokenPolicy identityPolicy = endpoint.Description.FindUserTokenPolicy(
|
||||||
|
userIdentity.TokenType,
|
||||||
|
userIdentity.IssuedTokenType,
|
||||||
|
tokenPolicyEndpoint.Description.SecurityPolicyUri);
|
||||||
|
if (identityPolicy == null)
|
||||||
|
{
|
||||||
|
NUnit.Framework.Assert.Ignore(
|
||||||
|
$"No UserTokenPolicy found for {userIdentity.TokenType}" +
|
||||||
|
$" / {userIdentity.IssuedTokenType}");
|
||||||
|
}
|
||||||
|
userIdentity.PolicyId = identityPolicy.PolicyId;
|
||||||
|
|
||||||
|
// the active channel
|
||||||
|
ISession session1 = await ClientFixture.ConnectAsync(endpoint, userIdentity)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
Assert.NotNull(session1);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await session1.ReconnectAsync(null, null).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
session1.DeleteSubscriptionsOnClose = true;
|
||||||
|
await session1.CloseAsync(1000).ConfigureAwait(false);
|
||||||
|
Utils.SilentDispose(session1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Open a session on a channel, then recreate using the session as a template,
|
/// Open a session on a channel, then recreate using the session as a template,
|
||||||
/// verify the renewUserIdentityHandler is brought to the new session and called
|
/// verify the renewUserIdentityHandler is brought to the new session and called
|
||||||
|
|||||||
Reference in New Issue
Block a user