Java EE is an industrial standard programming platform that makes cross-cutting concerns like security and transaction into standard services to free developers from muddy infrastructure coding jobs. The security services in Java EE enable developers to build strong and elaborate protections for their applications with minimum effort. Apart from Java EE, Spring is a fantastic and popular open source framework designed on top of the Java EE standard that addresses the missing or problematic pieces from earlier versions of the Java EE specification (1.0-1.4). Spring's features and value plus the fact that a Spring container can live in a Web server without a heavy-weight application container contribute to its continued dominance in the application framework market. Acegi designed for Spring provides flexible, powerful, and comprehensive security beyond what's available in the Java EE standard. The two independent security systems are discussed and compared from different angles in this article to help developers build strong, efficient, and elegant security solutions for their applications.
In reality, building a secure application is an enterprise-wide concern that can't be accomplished solely through Web developers' efforts. Collaborations from database specialists, network engineers, and Web server administrators are necessary. However, for this article's purposes, I focus our discussion on the Web developer's point of view.
Enterprise security
The purpose of enterprise security is to authenticate users and authorize access to different application functions and associated data. In many corporations, user demographics and security information are stored in a single repository in the form of LDAP, or lightweight directory access protocol, (perhaps federated) or a relational database to facilitate single sign-on (SSO). Security in the Java EE 5 specification addresses common and abstract application security concerns by leaving concrete implementations to server vendors. Security solutions using the standard Java EE security services are described as container-managed security (CMS) with portability across different Java EE platforms. Server vendors usually offer proprietary security extensions for issues not covered by the specification.
Independent from standard Java EE security, Acegi is an open source security system that provides a rich list of security services for applications that use Spring. Acegi security is described as portable at the WAR (Web archive) level, instead of the API level adopted by Java EE, because the Acegi runtime is deployed as part of the application inside a war file.
Both Acegi and the new Java EE 5 security benefit from Java 5 annotations, aspect-oriented programming (AOP), and dependency injection technologies, which make security programming less intrusive, less code intensive, and more configuration-based, and essentially promote POJO-style (plain-old Java object) programming. Desirable security solutions may be quickly and easily developed on top of these standardized security services with minimal programming efforts.
A pure home-grown security system is often vulnerable with security holes. For example, some developers use a login page to guard their applications and expect users to visit the login page before they go any further. Unfortunately, users can easily bypass that login screen, which usually leads to error situations. A home-grown security system may be necessary if special security needs are required, in which case, you should extend the standard security services offered by Java EE or Acegi, instead of starting from scratch.
Authentication in Java EE
The first thing that happens when a user interacts with a secured Web site is authentication. The Java EE specification declares four different login methods for authentication, form, basic, digest, and client-certification (X509). Basic and form are the most commonly used, while client-certification is more for B2B communications, where the client and sever are required to exchange trusted X509 certificates to enable mutual HTTPS communication.
Form-based login allows you to control the look and feel of a login Web screen that an HTTP browser presents to the user. The login HTML form has a predefined action j_securitycheck
, and input fields j_username
and j_password
.
Basic is a simple login mechanism defined in the HTTP protocol that displays a login pop-up window whenever an HTTP status code 401 is received. The browser constructs an authentication token with the base64-encoded value of username:password
and places it in the request message's HTTP header.
The digest-based login is basically a replacement of basic, in that a password is transmitted in a digested form calculated by one-way hash functions, like SHA2 or MD5, which is safer than the base64-encoded password value in basic. Note that base64 is not an encryption scheme, since anybody can decode the value back to the original clear text.
You should set up the login method for a Web application by configuring the web.xml deployment descriptor, which is explained in more detail in the Java EE 5 Tutorial.
Concrete implementations of authentication are created by server vendors as custom programming modules usually called authentication providers. Authentication providers communicate with backend datastores to prove the identities of users (or system processes). Almost all vendors offer LDAP and Java Database Connectivity (JDBC) authentication providers to authenticate users stored in LDAP or relational databases. Some may also support Windows NT authentication, and SSO authentications such as SAML (Security Assertion Markup Language), SiteMinder, and CAS as vendor-proprietary security extensions. These authentication providers may work with the four standard login methods, or they may delegate the login process to some centralized login Web sites. In Java EE, configuring those vendor-proprietary authentication providers extends beyond the scope of application programming. Therefore, the settings are stored in custom configuration files outside application war or ear files. Bear in mind that using any bizarre authentication provider not widely accepted by vendors undermines the portability of the application.
Unlike Java EE, Spring and Acegi are concrete implementations of their own APIs. Spring de facto promotes the WAR-level portability of Web applications, such that the war files may deploy and run out-of-box immediately without any external configurations required. In another words, all the configurations are defined inside the application war files.
Authentication in Acegi
Acegi offers flexible and comprehensive authentication services implemented through servlet filters for applications using Spring. Besides the common form, basic, digest, and client-certification login methods, Acegi also supports anonymous, remember-me, and redirect for SSO authentications that happen on some centralized login Web sites.
Web applications usually have both protected and unprotected URLs, and anonymous users can gain access to unsecured resources without authentication. However, you may picture this scenario differently in Acegi. Anonymous authentication in Acegi allows you to associate anonymous users with a specific user identity and role, so that programming access control is unanimous across protected and unprotected resources.
Remember-me authentication in Acegi enables a Web site to remember a user's identity between Web sessions. A long-duration cookie is sent—with the value of a digested identity and password—to the browser so the cookie will be detected during future sessions, causing automated login to take place, a desirable feature for many commercial Web sites.
Single sign-on is often an enterprise security requirement that applies to all applications inside a corporation. It may even happen across boundaries of corporations. Most SSO solutions such as CAS, SiteMinder, and SAML work similarly. In a simple SSO scenario, a request to access a secured URL from an unauthenticated user is redirected to a centralized Web site for login (the login page might be local). After a successful login, each subsequent user request will be associated with an authentication token. When the user navigates to a different Web site where the user's security context is not yet established, the server sends the token to the centralized authentication server for verification and retrieves the identity (and perhaps authorities) belonging to that user. This process is transparent to the user, as no further login is required.
Acegi defines a rich list of authentication providers: in-memory, JDBC, LDAP, JAAS, run-as, SiteMinder, and CAS. The in-memory authentication provider allows you to declare test user-accounts in Spring configuration files during the development phase of your applications. JDBC and LDAP authentication providers work the same as in Java EE platforms. The JAAS authentication provider delegates authentication requests to the Java Authentication and Authorization Service enclosed in Java SE. SiteMinder and CAS authentication providers handle SSO authentication requests.
Run-as is indeed an authorization feature, rather than an authentication provider. As an authorization configuration option in Java EE, run-as temporarily replaces the original security roles of the principal (user) for the duration of a method invocation, while in Acegi, the role specified by run-as is an add-on to the principal's original roles. Run-as in Java EE is particularly useful in Java Message Service, since the security identity of a JMS message sender is never propagated to a receiver. Run-as enables you to encapsulate JMS message processing as part of the secured business-processing logic.
Concurrent session control in Acegi is a great feature addressing real business needs. It prevents a user from concurrently authenticating to the same application more than a specified number of times. This feature may be set as cluster-aware, such that the specified session count applies to the entire server cluster, rather than a single server instance.
Once you set up the authentication strategies for your applications, the applications are protected from unauthenticated access. Nevertheless, they are still exposed under the unsecured HTTP communications. The HTTP protocol doesn't prevent abusers from eavesdropping on or tampering with messages during the transportation phase.
Channel, or transport-level, security
A critical security threat for many Web applications is session hijacking. The HTTP protocol is fundamentally stateless with a session ID (a unique number—in the form of a special cookie or a token—in URLs) as the only measure for a Web server to track stateful communication with a browser. If session hijacking is considered a significant risk for an application, HTTPS should be used to protect server-browser communications. The login mode client-certification actually enforces HTTPS channel security, since X509 certificates are used during the HTTPS transportation's handshake process. It is optional for the rest of the login modes to run over the HTTPS channel. Message encryption and decryption in HTTPS transportation are expensive operations with the lag proportional to the size of the HTTP messages, therefore, most commercial Web sites run over HTTP and redirect customers to HTTPS channels whenever they start checkout.
For SOAP Web services applications, in addition to channel security, message-level security, which secures a portion of the SOAP messages with the latest XML digital signature and encryption technology, should be considered for communications that cross enterprise boundaries.
Human user detection
It is not difficult for an experienced Web programmer to write a little script that emulates a user's interactions with a Web site. In fact, all Web testing tools represent that kind of program.
A CAPTCHA typically takes the form of an image containing distorted letters and/or numbers and is often used on login screens to differentiate a human user from a computer program. Regardless of some its drawbacks, CAPTCHA helps mitigate certain types of malicious attacks from automated computer programs. JCAPTCHA is a Java implementation of the CAPTCHA technology and can be incorporated into Java EE security or Acegi.
Once users pass authentication, authorization kicks in immediately.
Authorization
Authorization is the process of controlling, based on business rules, a user's access to application resources. Authorization is a typical crosscutting concern in AOP terms. Thus, it makes sense to implement authorization with AOP technologies. Contrary to authentication, authorization is a localized process that occurs inside an application. Role-based access control (RBAC) is perhaps the most widely accepted authorization scheme in modern IT industry. A role represents a list of privileges defined within an application. In reality, it must be mapped to a group of users subject to the same access policies. The user groups are generally declared in the same place where user accounts reside, like LDAP or relational databases. The mapping between logical roles and user groups is defined in vendor-proprietary deployment descriptors for Java EE, and Spring configuration files for Acegi. Users are granted access to different resources based on their roles rather than identities.
Legacy applications, such as mainframe programs, may have finer-grained access control specific to each individual. The downside is that the security administration may be too complex and granular to manage. Authorization in Java EE is solely role-based, while Acegi does support both role-level and identity-level access control. In an application of a multitier architecture, authorization may take place in different layers with different levels of granularities. The authorization services in Java EE and Acegi are implemented via custom security modules called authorization providers.
Authorization in the Web tier
URL pattern-based security (Web request security) is a coarse-grained access-control mechanism supported by Java EE and Acegi. The strategy is to guard Web resources based on their URLs, so setting the access-control policies is fairly easy. You may declare protected URL patterns in a configuration file (web.xml for Java EE, or Spring context file for Acegi) such that a server will prompt a security challenge whenever an unauthenticated user navigates from unprotected URLs to the protected ones. After the user is authenticated, the server checks the user's roles against those declared in the access control policies. If no match is found, the user receives a response message with HTTP status code 403 in the header. Keep in mind you should never explicitly direct users to the login Web page; instead, the server or Acegi determines when or where to prompt the user a security challenge.
In Java EE, fine-grained UI component-level security can be achieved through some programming effort. The Servlet API's isUserInRole()
method together with the JSP Standard Tag Library (JSTL) tag helps you build access control down to each HTML element. An easy way is to bind the return value of the
httpServletRequest.isUserInRole("ROLE_MANAGER")
method to a JavaBean property of Boolean type authBean.roleManager
and wrap an HTML or a JavaServer Pages element(s) inside JSTL tag . The enclosed content will display when the test condition returns true. For applications developed through the JavaServer Faces technology, you may bind that Boolean value with a JSF tag's
rendered
or disabled
attribute. Acegi also defines an tag to enable UI component-level security in JSP pages.
Authorization in beans
Method-level security is supported by Acegi for Spring beans and by Java EE for Enterprise JavaBean (EJB) components that compose an application's business layer (service layer). Acegi and many Java EE containers use AOP technologies to implement method-level security. Meanwhile, dependency injection (also called inversion of control) makes both Spring beans and the new EJB 3.0 enterprise beans POJO-styled. Therefore, it is better to use less-intrusive programming approaches for authorization, such as configurations through Spring context files or EJB deployment descriptors, or annotations inside bean class files, as I discuss in a later section.
Authorization in domain object instances
For some applications, especially legacy integrations, it's desirable to define access control lists (ACLs) for individual domain object instances (not domain object classes). Domain object-instance security offered uniquely by Acegi is the most fine-grained access-control mechanism that addresses this special security requirement with integer bit masking, permission inheritance, a JDBC-backed ACL repository, and caching for authorization policies.
Adjudication
Acegi and most Java EE containers allow you to configure multiple authentication providers and authorization providers for the same application. When an authentication or authorization decision must be made, different providers may simultaneously apply, therefore conflict decisions may occur. Adjudication is the process of evaluating multiple decisions through predefined algorithms and rendering a verdict. Not covered by the Java EE specification, adjudication is implemented by server vendors as security extensions.
In Acegi, adjudication occurs within AccessDecisionManager
objects, which have three basic types of implementations: UnanimousBased
, AffirmativeBased
, and ConsensusBased
. Like many real-life voting systems, Acegi defines three types of votes: grant, deny, and abstain. The ConsensusBased
implementation grants or denies access based on the consensus of non-abstain votes. The AffirmativeBased
implementation grants access if one or more grant votes were received. The UnanimousBased
implementation expects unanimous grant votes, ignoring abstains.
Essentially, the custom adjudication implementations offered by Java EE server vendors work similarly to the AccessDecisionManager
in Acegi.
Given so many options for you to build application security, your decision should be driven by the business requirements as well as the disciplines of application performance, programming efficiency, and code portability. Now it's time for you to start programming security.
Security programming
Both Acegi and Java EE 5 support security programming in three different flavors, programmatic, declarative, and annotations. Given the POJO nature of Spring beans and EJB 3.0 enterprise beans, the non-intrusive approaches of declarative and annotation-based security are desirable.
Programmatic security is embedded in the Java code and is used to make application security decisions. In general, programmatic security is not preferred due to the API dependencies that break the POJO programming style. Programmatic security is only suggested for use when declarative programming or annotations alone prove insufficient for expressing an application's security model. The Java EE approach for programmatic security consists of two methods (getCallerPrincipal()
and isCallerInRole()
) of the EJBContext
interface and two methods (getUserPrincipal()
and isUserInRole()
) of the HttpServletRequest
interface. Acegi defines an Authentication
object containing a principal
object and a list of GrantedAuthority
objects. You may retrieve the Authentication
object from the method call SecurityContextHolder.getSecurityContext().getAuthentication()
. The principal
object in Acegi is more flexible than the one in Java EE. It often implements a UserDetails
interface and is enriched with information other than the username, such as user's full name, email, address, phone, fax, employment number, and so on.
Declarative security expresses an application's security requirements outside the Java code using deployment descriptors (web.xml and ejb-jar.xml) in Java EE or Spring XML configuration files in Acegi. It forces you to concentrate on business logic in your Java code and promotes POJO-style programming.
Annotations, introduced in Java 5 (also described as attribute-oriented programming), is a program-level marking technique that can be used to specify information about security within a class file as metadata attributes. When an application is deployed, the metadata information will be picked up by the Java EE runtime or Acegi in Spring. It is in essence a declarative type of security. Annotations eliminate the need for maintaining side files like deployment descriptors with security settings that must be kept up to date with changes in application source code.
Acegi plus Java EE security
Having Acegi and Java EE security collaborate is like putting icing on the cake. Acegi's container adapter integrates Acegi with Java EE security through container-specific configurations. It enables you to use both Acegi security and security methods defined in the Servlet API, such as getUserPrincipal()
and isUserInRole()
. Acegi currently supports Jetty, Catalina (Tomcat), JBoss, and Resin. Custom container adapters can easily be developed for other Web servers.
You need a filter
As a real-world security programming practice, a servlet filter helps you accomplish numerous tasks that may otherwise be spread out in many different Java beans.
Stateful Web applications, especially personalized Web sites, often need to initialize user context information in the session prior to any further action. Some Web sites enforce screen navigations regardless of the URLs in users' HTTP requests. Servlet filters, which are implementations of the Chain of Responsibility pattern, fit these use cases extremely well. You may write logic in a filter class to initialize a user's context information or enforce screen flows based on business rules using REDIRECT. For applications using JSF, you may choose JSF phase listeners instead to gain access to the FacesContext
object.
Conclusion
This article is an in-depth introduction and comparison of Java EE security and Acegi. They both offer a variety of security services to make application security programming easier. The declarative and annotation-based programming methodologies let developers focus on business concerns in Java classes and encourage programming using POJO. For applications built on top of Spring, Acegi is preferred due to the enhanced features not usually available in Java EE security. Without Spring, developers should take advantage of the security services defined in Java EE to implement "container-managed security." The risks and uncertainties involved make a homegrown security system the last thing you want to explore.
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/71047/viewspace-996763/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/71047/viewspace-996763/