【ソフトウェア工学と実践】 (6) 台帳セキュリティ管理と特定取引の台帳セキュリティ

2021SC@SDUSC

1. 特定の取引慣行のための台帳セキュリティ マネージャーおよび台帳セキュリティ管理

1.ブロックチェーンベースのネットワークセキュリティメカニズムには、分散化、改ざん防止、トレーサビリティ、高信頼性、高可用性という特徴があり、ネットワークセキュリティの向上に役立ちます

2. ネットワークセキュリティは、ブロックチェーン(ブロックチェーン)技術を使用して、すべてのノードが操作に参加してデータを管理し、中央ノードの障害によるネットワークセキュリティ事故を回避する分散型分散システムアーキテクチャを確立できます。

3.ブロックチェーン技術をオフチェーンデータベースと組み合わせ、データとデータ権限を分離することで、データと権限を管理する分散型個人データ管理システムを実現できます。アプリケーションがユーザー データにアクセスする前に、ユーザーのアクセス許可を取得する必要があります。

4.デジタル署名は、ファイルまたはデータの完全性と出所を検証するために使用される技術であり、ファイルまたはデータが変更されておらず、否認できないことを保証します。

2. コード分析

1.インターフェース

元帳セキュリティマネージャー

次のコードは、指定されたエンド ユーザーとノード参加者に関連付けられたセキュリティ ポリシーを返します。
ndpoints はエンド ユーザーのアドレス リスト、
nodes はノード参加者のアドレス リストです。

SecurityPolicy getSecurityPolicy(Set<Bytes> endpoints, Set<Bytes> nodes);

このコードは、指定されたユーザーのロール権限を返すことができます。

UserRolesPrivileges getUserRolesPrivilegs(Bytes userAddress);

セキュリティポリシー

このインターフェイスは、特定のトランザクション リクエストの台帳セキュリティ ポリシーです。内部のコンテンツを確認できます。


トランザクションに署名したエンド ユーザーのアドレスのリスト

Set<Bytes> getEndpoints();

トランザクションに署名したノード参加者のアドレスのリスト

Set<Bytes> getNodes();

端末 ID が有効かどうかを確認し、そうでない場合は false を返し、そうでない場合は true を返します。

boolean isEndpointValid(MultiIDsPolicy midPolicy);

ノード ID が有効かどうかをチェックし、そうでない場合は false を返し、そうでない場合は true を返します。

boolean isNodeValid(MultiIDsPolicy midPolicy);

トランザクションに署名したエンド ユーザーを確認します。
チェックするパーミッション。midPolicy
は、複数の署名ユーザーのパーミッション ポリシーです。true
を返すと承認されたことを意味し、false を返すと承認されないことを意味します。

boolean isEndpointEnable(LedgerPermission permission, MultiIDsPolicy midPolicy);

トランザクションに署名したエンド ユーザーを確認します。midPolicy
は複数の署名ユーザーのアクセス許可ポリシーです。true
を返すと承認されたことを意味します。false を返すと承認されていないことを意味します。

boolean isEndpointEnable(TransactionPermission permission, MultiIDsPolicy midPolicy);

トランザクションに署名したノード参加者パーミッション
によってチェックされるパーミッションをチェックします。midPolicy
は、複数の署名ユーザーのパーミッション ポリシーです。
承認を示す場合は true を返します。承認されていないことを示す場合は false を返します。

boolean isNodeEnable(LedgerPermission permission, MultiIDsPolicy midPolicy);

トランザクションに署名したノード参加者を確認します;
パーミッション チェックするパーミッション;
midPolicy 複数の署名ユーザーのパーミッション ポリシー;
承認を示す場合は true を返し、承認されていないことを示す場合は false を返します。

boolean isNodeEnable(TransactionPermission permission, MultiIDsPolicy midPolicy);

端末 ID の正当性を確認します。

void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException;

ノード ID の正当性を確認します。

void checkNodeValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException;

トランザクションに署名したエンド ユーザーのパーミッション
によってチェックされるパーミッションを確認します。midPolicy
は、複数の署名ユーザーのパーミッション ポリシーです。

void checkEndpointPermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;

トランザクションに署名した端末アカウント {@linkTransactionRequest#getEndpointSignatures()}) がパラメーターで指定された権限に対して承認されているかどうかを確認します。承認されていない場合、メソッドは {@link LedgerSecurityException} 例外をスローします。

void checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy)
			throws LedgerSecurityException;

({@link TransactionRequest#getNodeSignatures()} から) トランザクションに署名したノード参加者が、パラメーターで指定された権限に対して承認されているかどうかを確認します。承認されていない場合、メソッドは {@link LedgerSecurityException} 例外をスローします。

void checkNodePermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;

({@link TransactionRequest#getNodeSignatures()} から) トランザクションに署名したノード参加者が、パラメーターで指定された権限に対して承認されているかどうかを確認します。承認されていない場合、メソッドは {@link LedgerSecurityException} 例外をスローします。

void checkNodePermission(TransactionPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;

2. クラス

SecurityContext

1. 最初のものはプライベート オブジェクトであり、policyHolder という名前の新しい SecurityPolicy オブジェクトが作成されます. 特定の検査ポリシーをカスタマイズするために、次のメソッドで上記のインターフェイスのメソッドをこのオブジェクトに追加できます

2. 2 番目の静的メソッドは、policyHolder に新しい検証メソッドを追加することです。

3. 3 つ目の方法は、policyHolder 内の特定の検証メソッドを削除することです。

4. 4 番目の方法は、新しく作成されたオブジェクトの検査ポリシーを取得して確認するのに適しています。

*1*
private static ThreadLocal<SecurityPolicy> policyHolder = new ThreadLocal<SecurityPolicy>();
*2*
	public static void setContextUsersPolicy(SecurityPolicy policy) {
    
    
		policyHolder.set(policy);
	}
*3*
public static SecurityPolicy removeContextUsersPolicy() {
    
    
		SecurityPolicy p = policyHolder.get();
		policyHolder.remove();
		return p;
	}
*4*	
public static SecurityPolicy getContextUsersPolicy() {
    
    
		return policyHolder.get();
	}

コンテキスト セキュリティ ポリシーを指定されたポリシーに切り替え、パラメーターで指定された Runnable} 操作を実行し、操作の完了後に元のコンテキスト ポリシーを復元します。

public static void switchContextUsersPolicy(SecurityPolicy contextUsersPolicy, Runnable runnable) {
    
    

	}

LegderSecurityManagerImpl

このクラスは台帳マネージャーとして理解できます

これらは以下で使用される隠しオブジェクトです。rolePrivilegeSettings
はロール権限の設定オブジェクトです。userPrivilegeSettings は
ユーザー権限の設定オブジェクトです。
次の 3 つはユーザー権限の構成です。
最後の 2 つはユーザー アカウント クエリです。

private RolePrivilegeSettings rolePrivilegeSettings;

	private UserAuthorizationSettings userRolesSettings;

	// 用户的权限配置
	private Map<Bytes, UserRolesPrivileges> userPrivilegesCache = new ConcurrentHashMap<>();

	private Map<Bytes, UserRoles> userRolesCache = new ConcurrentHashMap<>();
	private Map<String, RolePrivileges> rolesPrivilegeCache = new ConcurrentHashMap<>();

	private ParticipantCollection participantsQuery;
	private UserAccountSet userAccountsQuery;

このメソッドは、これに現在のオブジェクトの現在の状態の値を取得させるためのものです

public LedgerSecurityManagerImpl(RolePrivilegeSettings rolePrivilegeSettings, UserAuthorizationSettings userRolesSettings,
			ParticipantCollection participantsQuery, UserAccountSet userAccountsQuery) {
    
    
		this.rolePrivilegeSettings = rolePrivilegeSettings;
		this.userRolesSettings = userRolesSettings;
		this.participantsQuery = participantsQuery;
		this.userAccountsQuery = userAccountsQuery;
	}

put()このコードには、java.util.HashMap のメソッドであるメソッドがあり、その機能は、指定された値をこのマップ内の指定されたキーに関連付けることであることがわかります
この特定の機能を見てみましょう。メソッド, このメソッドは、アカウントのユーザー構成を取得し、それを対応するハッシュ アドレスに関連付けるために使用されます. ハッシュ値が null の場合、対応する値を格納するために新しいアドレスが割り当てられます.

public SecurityPolicy getSecurityPolicy(Set<Bytes> endpoints, Set<Bytes> nodes) {
    
    
		Map<Bytes, UserRolesPrivileges> endpointPrivilegeMap = new HashMap<>();
		Map<Bytes, UserRolesPrivileges> nodePrivilegeMap = new HashMap<>();

		for (Bytes userAddress : endpoints) {
    
    
			UserRolesPrivileges userPrivileges = getUserRolesPrivilegs(userAddress);
			endpointPrivilegeMap.put(userAddress, userPrivileges);
		}

		for (Bytes userAddress : nodes) {
    
    
			UserRolesPrivileges userPrivileges = getUserRolesPrivilegs(userAddress);
			nodePrivilegeMap.put(userAddress, userPrivileges);
		}

		return new UserRolesSecurityPolicy(endpointPrivilegeMap, nodePrivilegeMap, participantsQuery, userAccountsQuery);
	}

このメソッドは、最初にアカウントのユーザー アドレスを取得し、アドレスが null でない場合は、ユーザーの帳簿の情報を返します。次に、このメソッドはユーザー権限のテーブルを作成し、if ステートメントを使用して put() をネストします
。メソッドを使用してユーザーのロール リストを読み込みます;
次に、ユーザーの総合的な権限を計算し、for ステートメントを使用してロールの権限リストをたどり、1 つずつ出力します. この一連の操作が完了すると、ユーザーの権限はバインドされますユーザーとそれに記録された作成されたテーブル;
最後に、ロールに権限がない場合は、デフォルトのロール権限を付与します。

public UserRolesPrivileges getUserRolesPrivilegs(Bytes userAddress) {
    
    
		UserRolesPrivileges userPrivileges = userPrivilegesCache.get(userAddress);
		if (userPrivileges != null) {
    
    
			return userPrivileges;
		}

		UserRoles userRoles = null;

		List<RolePrivileges> privilegesList = new ArrayList<>();

		// 加载用户的角色列表;
		userRoles = userRolesCache.get(userAddress);
		if (userRoles == null) {
    
    
			userRoles = userRolesSettings.getUserRoles(userAddress);
			if (userRoles != null) {
    
    
				userRolesCache.put(userAddress, userRoles);
			}
		}

		// 计算用户的综合权限;
		if (userRoles != null) {
    
    
			String[] roles = userRoles.getRoles();
			RolePrivileges privilege = null;
			for (String role : roles) {
    
    
				// 先从缓存读取,如果没有再从原始数据源进行加载;
				privilege = rolesPrivilegeCache.get(role);
				if (privilege == null) {
    
    
					privilege = rolePrivilegeSettings.getRolePrivilege(role);
					if (privilege == null) {
    
    
						// 略过不存在的无效角色;
						continue;
					}
					rolesPrivilegeCache.put(role, privilege);
				}
				privilegesList.add(privilege);
			}
		}
		// 如果用户未被授权任何角色,则采用默认角色的权限;
		if (privilegesList.size() == 0) {
    
    
			RolePrivileges privilege = getDefaultRolePrivilege();
			privilegesList.add(privilege);
		}

		if (userRoles == null) {
    
    
			userPrivileges = new UserRolesPrivileges(userAddress, RolesPolicy.UNION, privilegesList);
		} else {
    
    
			userPrivileges = new UserRolesPrivileges(userAddress, userRoles.getPolicy(), privilegesList);
		}

		userPrivilegesCache.put(userAddress, userPrivileges);
		return userPrivileges;
	}

次は非表示のクラスです.まずメソッド ヘッダーを見てみましょう
.SecurityPolicy インターフェイスを呼び出していることがわかります.これはエンド ユーザーの権限リストであるため、ユーザーには公開されていません.

private class UserRolesSecurityPolicy implements SecurityPolicy 

上記と同様:
これらは以下で使用される隠しオブジェクトです;
rolePrivilegeSettings はロール権限の設定オブジェクトです;
userPrivilegeSettings はユーザー権限の設定オブジェクトです;
次の 3 つはユーザー権限の構成です;
最後の 2 つはユーザー アカウントのクエリです;
このメソッドはこれにより、現在のオブジェクトの現在の状態の値を取得できます。

public UserRolesSecurityPolicy(Map<Bytes, UserRolesPrivileges> endpointPrivilegeMap,
				Map<Bytes, UserRolesPrivileges> nodePrivilegeMap, ParticipantCollection participantsQuery,
				UserAccountSet userAccountsQuery) {
    
    
			this.endpointPrivilegeMap = endpointPrivilegeMap;
			this.nodePrivilegeMap = nodePrivilegeMap;
			this.participantsQuery = participantsQuery;
			this.userAccountsQuery = userAccountsQuery;
		}

This is a boolean method, and the return value is true or false. このメソッドは主に、エンドポイントが要求する権限を持っているかどうかを判断するために使用されます。
1試合と全試合の戻り値に分け、その中間値にある場合はエラーをスローします。

public boolean isEndpointEnable(LedgerPermission permission, MultiIDsPolicy midPolicy) {
    
    
			if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
    
    
				// 至少一个;
				for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
    
    
					if (p.getLedgerPrivilegesBitset().isEnable(permission)) {
    
    
						return true;
					}
				}
				return false;
			} else if (MultiIDsPolicy.ALL == midPolicy) {
    
    
				// 全部;
				for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
    
    
					if (!p.getLedgerPrivilegesBitset().isEnable(permission)) {
    
    
						return false;
					}
				}
				return true;
			} else {
    
    
				throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
			}
		}

このメソッドの後に、トランザクションであることを確認する方法と、アカウントの権限を確認する方法がありますが、コードは上記の実行プロセスと構造に似ていますが、詳細に進み、権限を確認する方法を見てみましょう。 、上記の方法のような 3 つの構造があるため、同じ方法と類似の方法、例としてそれらの 1 つだけを取り上げます。

このメソッドは、エンドポイントのパーミッションをチェックするために使用されます. 入力は、対応するエンドポイントのパーミッションをチェックするためのトランザクションパーミッションとマルチポリシーです.

public void checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy)
				throws LedgerSecurityException {
    
    
			if (!isEndpointEnable(permission, midPolicy)) {
    
    
				throw new LedgerSecurityException(String.format(
						"The security policy [Permission=%s, Policy=%s] for endpoints rejected the current operation!",
						permission, midPolicy));
			}
		}

This method is used to confirm whether the endpoint is valid, and the multipolicy parameter is passed in, and the method will verify one and all of it. トランザクションが有効かどうかを確認する同じ方法は、これと似ています。

public boolean isEndpointValid(MultiIDsPolicy midPolicy) {
    
    
			if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
    
    
				// 至少一个;
				for (Bytes address : getEndpoints()) {
    
    
					if (userAccountsQuery.contains(address)) {
    
    
						return true;
					}
				}
				return false;
			} else if (MultiIDsPolicy.ALL == midPolicy) {
    
    
				// 全部;
				for (Bytes address : getEndpoints()) {
    
    
					if (!userAccountsQuery.contains(address)) {
    
    
						return false;
					}
				}
				return true;
			} else {
    
    
				throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
			}
		}

これは、検査エンドポイントの許可ドメインです。

public void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException {
    
    
			if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
    
    
				// 至少一个;
				for (Bytes address : getEndpoints()) {
    
    
					if (userAccountsQuery.contains(address)) {
    
    
						return;
					}
				}
				throw new UserDoesNotExistException("All endpoint signers were not registered!");
			} else if (MultiIDsPolicy.ALL == midPolicy) {
    
    
				// 全部;
				for (Bytes address : getEndpoints()) {
    
    
					if (!userAccountsQuery.contains(address)) {
    
    
						throw new UserDoesNotExistException("The endpoint signer[" + address + "] was not registered!");
					}
				}
				return;
			} else {
    
    
				throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
			}
		}

おすすめ

転載: blog.csdn.net/weixin_45932150/article/details/121176684