站内搜索: 请输入搜索关键词
当前页面: 图书首页 > NET For Java Developers Migrating To C#

NET For Java Developers Migrating To C#

[ directory ] Previous Section Next Section

1.5 Security Management

Security in the .NET Framework can be defined both declaratively and programmatically. Declarative security enables a programmer to specify an assembly's security requirements directly in the metadata of that assembly's code. The permission requests and all other forms of declarative security are specified as custom attributes in code. Annotations of classes, properties, and methods are used to fine-tune permissions. Because declarative attributes become part of an assembly's metadata, the security needs of the assembly are more easily identified. Declarative checks are the solution of choice when the requested action and permission are known at compile time.

Programmatic security is implemented directly in code. Programmers take security actions programmatically, and the permission is either granted or denied based on the state of the security stack. When a method issues a demand to access a particular file, for example, that demand will fail if the caller of the method has not been granted the necessary permission.

1.5.1 Policy-Driven Security Based on Code Evidence

The .NET Framework introduces the concept of evidence-based security. Evidence refers to inputs to the security policy about the code. The assembly is the unit of code for which evidence is gathered. When an assembly is loaded, the CLR policy system determines which permissions are to be granted. It does this by gathering the assembly's evidence and evaluating it in the context of the security policy.

The CLR policy system then grants a set of permissions to the assembly based on the evaluated evidence and any permission requests that the assembly may make. An assembly can never be assigned more permissions than the policy system would grant it in the absence of any permission requests; the requests serve only to further limit the grants. Security policy consists of a number of customizable code groups that contain the permissions to be granted based on evidence. Code groups might describe the permissions available to assemblies acquired from a specific security zone, or those that are signed by a specific publisher, and so forth.

It is important to remember that you can submit anything as evidence梡rovided that the security policy has a use for it梑y defining a code group related to the evidence. The procedure for granting permission involves evaluating the evidence to determine which code groups are applicable at three levels: the enterprise, the machine, and the user. The policy evaluates these three levels in that order and then creates a permission set that is the intersection of all three. At runtime, permissions are evaluated based on the execution of code.

Here's an example. Let's say an assembly A3 provides its evidence, along with the evidence from the host plus any specific permission requests, to the policy evaluator. The evaluator then creates a set of permission grants G3 for assembly A3. Assembly A3 is called by A2, which in turn is called by assembly A1. The policy evaluator has permission grants G1 and G2 created for assemblies A1 and A2, respectively. When code in assembly A3 triggers a security check, then G1, G2, and G3 are all checked to see whether each has the permission requested in the security check. If any one of the grants does not include that permission, then the runtime throws a security exception. All the grants must contain the checked permission for that call to be successful.

Actions such as reading or writing files, displaying dialog boxes, and reading or writing environment variables are implemented using .NET Framework methods that are included within the framework security infrastructure. In this way, the .NET Framework can allow or disallow an action based on the security policy, without the need for any additional work by the programmer. Whereas authors of managed classes that expose protected resources must make appropriate security demands in their libraries, developers who use the .NET Framework class libraries to access a protected resource get the benefits of the code access security system "for free"; they do not have to make any explicit security calls.

1.5.2 Role-Based Security, Authentication, and Authorization

Code execution security is also enforced based on an authenticated identity or on the role associated with the context of the code's execution. The .NET Framework provides programmatic and declarative means to define the identities and principals that are the core of a role-based security system. Identities can map to the user logged in to the operating system or can be defined by the application. The corresponding principal encapsulates the identity, along with any related role information.

Authentication is the process of accepting credentials from a user and validating them against some authority. If the credentials are valid, the user is said to have an authenticated identity. Authorization is the process of determining whether that authenticated identity has access to a given resource. Authentication can be accomplished by either system or business logic and is available through a single API. The authentication API is fully extensible, so developers can use their own business logic as needed.

1.5.3 Isolated Storage

The .NET Framework provides a special facility, isolated storage, for storing data even when no file access is allowed. For example, when a managed control is downloaded from the Internet and run, it is given a limited set of permissions but not the right to read or write files. Isolated storage is a new set of types and methods supported by the .NET Framework for local storage. In essence, each assembly is given access to segregated storage on disk. No access to other data is allowed, and isolated storage is available only to the specific assembly for which it was created.

An application might use isolated storage to keep activity logs, save settings, or save state data to disk for later use. Because the location of isolated storage is predetermined, isolated storage provides a convenient way to specify unique space for storage without the need to determine file paths.

1.5.4 Cryptography

The .NET Framework provides a set of cryptographic objects that support encryption, digital signatures, hashing, and random-number generation, all of it implemented through well-known algorithms, such as RSA, DSA, Rijndael/AES, Triple DES, DES, and RC2, as well as the MD5, SHA1, SHA-256, SHA-384, and SHA-512 hash algorithms. The framework also supports the XML Digital Signature specification under development by the Internet Engineering Task Force (IETF) and the World Wide Web Consortium (W3C). The .NET Framework uses cryptographic objects to support internal services. The objects are also available as managed code to developers who require cryptographic support.

1.5.5 Security in Java

Java supports security at several levels. The Java language guarantees type safety and well-defined flow of execution. The JVM in turn executes only legitimate byte code through the byte code verifier. Access to system resources is mediated by the JVM and is checked in advance by a SecurityManager that restricts the actions of a piece of untrusted code to the bare minimum. JDK 1.3 employs an easily configurable security policy, an extensible access control structure, and the ability to create and handle new typed permissions without any extra programming from the user side.

The building block of the security system in Java is the protection domain: a set of objects that are accessible to accessors that have the required permissions. The protection domain concept serves as a convenient mechanism for grouping and isolating units of protection. For example, you can prohibit protection domains from interacting with one another so that any permitted interaction either must occur through trusted system code or must be explicitly allowed by the domains concerned.

Protection domains generally fall into two categories: system domains and application domains (see also Section 1.2.5). It is important that all protected external resources梥uch as the file system, the networking facility, and the screen and keyboard梑e accessible only via system domains. A domain conceptually encloses a set of classes whose instances are granted the same set of permissions. Protection domains are determined by the policy currently in effect. The Java application environment maintains a mapping from code (classes and instances) to their protection domains and then to their permissions.

A domain with fewer permissions cannot gain additional permissions as a result of being called by a domain with more permissions. This security policy is similar to the CLR security policy, in which less powerful assemblies cannot gain additional permissions merely by virtue of being coexecuted with more powerful assemblies. A thread of execution may occur completely within a single protection domain or may involve an application domain and also the system domain. The permission set of an execution thread is considered to be the intersection of the permissions of all protection domains traversed by the execution thread. During execution, when access to a critical system resource (such as file I/O and network I/O) is requested, the resource-handling code directly or indirectly invokes a special AccessController class method, which evaluates the request and decides whether it should be granted or denied.

Java provides a rich security API that allows for programmatic access to defining, accessing, and evaluating permissions of a piece of code. The security policy has a specific syntax for declarative definition of the security permissions. Java also has role-based security and APIs for cryptography, authentication, and authorization. The concept of keys, certificates, and signed code is common to both the CLR and the JVM. However, JDK 1.3 does not provide isolated storage.

    [ directory ] Previous Section Next Section