Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
0,95 MB
Nội dung
ptg <exception class="javax.persistence.PersistenceException"> <end-conversation/> <redirect view-id="/generalError.xhtml"> <message>Database access failed</message> </redirect> </exception> <exception class="java.lang.RuntimeException"> <redirect view-id="/generalError.xhtml"> <message>Unexpected failure</message> </redirect> </exception> </pages> When a RuntimeException is thrown from the application, Seam redirects to the /generalError.xhtml page with the JSF error message, but without ending the current long-running conversation. The generalError.xhtml page is as follows; Figure 17.3 shows it in a browser. <ui:composition > <ui:define name="content"> <div class="section"> <h1>General</h1> <p>The following general error has occurred</p> <p><h:messages/></p> <p>Please come back and try again! Thanks.</p> </div> </ui:define> <ui:define name="sidebar"> <h1>Custom Error page</h1> </ui:define> </ui:composition> The generalError.xhtml page for RuntimeExceptionFigure 17.3 CHAPTER 17 FAILING GRACEFULLY 228 From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ptg Error Messages with @Redirect The @Redirect annotation can also take a message attribute to send a JSF message to the error page it redirects to. Using Error Pages with Seam Security It is easy to redirect to a custom login page when an unauthenticated user tries to access a restricted web page protected by the Seam security framework (see Chapter 18). You just need to capture and redirect the org.jboss.seam.security.NotLoggedInException. 17.5 The Debug Information Page Custom error pages are nice for production systems. However, when you develop the application, you do not know when and what kinds of errors might come up. Seam and Facelets provide generic mechanisms to capture any error during development and redirect to the debug information page, so that you can accurately pinpoint the error source. 17.5.1 The Facelets Debug Page To enable the Facelets debug page, you need to put Facelets in development mode in the app.war/WEB-INF/web.xml file: <web-app > <context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value>true</param-value> </context-param> </web-app> If an error occurs when Facelets renders a page, it displays a professional looking error page with accurate debugging information pinpointing the line number in the Facelets XHTML file that caused the error (see Figure 17.4). The source file line number is useful because what the standard JSF stack trace gives you is useless line numbers on the servlet compiled from the view page. The debug page also provides information about the current internal state of the JSF rendering engine. For instance, you can view the complete JSF component tree associ- ated with the current page. You can actually launch the debug page as a pop-up from any Facelets page; you just need to put the <ui:debug hotkey="d"/> element in your Facelets page. Then, at runtime, press Ctrl+Shift+d to launch the debug pop-up. You 229 17.5 THE DEBUG INFORMATION PAGE From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ptg can choose any hotkey other than the d shown here. Of course, if there is no error at this moment, the debug page shows only the component tree and scoped variables, without the stack trace. The Facelets debug pageFigure 17.4 17.5.2 The Seam Debug Page If an error occurs outside the JSF Facelets page rendering operation (e.g., an error in the UI event handler method), the Facelets debug page will not catch it. We have to use the Seam debug page for this type of error. To use the Seam debug page, you need to follow the instructions in Section 3.3 to bundle the jboss-seam-debug.jar and set up the Seam Exception Filter. Then, in the app.war/WEB-INF/components.xml file, you must enable debugging on the core:init component: <components > <core:init jndi-pattern="booking/#{ejbName}/local" debug="true"/> </components> Now, any uncaught error will be redirected to the /debug.seam page, which displays the context information as well as the stack trace (Figure 17.5). CHAPTER 17 FAILING GRACEFULLY 230 From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ptg An uncaught exception without a custom error page is redirected to /debug.seam Figure 17.5 Again, the Seam /debug.seam page works even if there is no error. You can load that page at any time to look at the current Seam runtime context information. Seam integrates exceptions in the business layer right into custom error pages in the presentation layer. This is yet another benefit of Seam’s unified component approach. You have no more excuse for ugly error pages! 231 17.5 THE DEBUG INFORMATION PAGE From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ptg This page intentionally left blank From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ptg Security is, arguably, one of the most important aspects of application development. Given the cost associated with a security breach in an organization, this should be a top priority when developing an application. Unfortunately, due to its complexity, security is often an afterthought, which can lead to gaping holes in an application for malicious users to take advantage of. How can developers allocate the time necessary to completely secure an application? Imagine that your managers have already scheduled a year worth of effort to be completed in the next six months—are you doomed to be the next security breach headline on the nine o’clock news? Fortunately, when using Seam, much of this complexity is hidden, making it simple to ensure that your application is secure. Security is a cross-cutting concern, meaning that much of the code to handle security requirements is not directly related to the business rules you are attempting to code. For example, if the method bar() in class Foo needs to be accessible only to the users who are logged in and have the role FOO_USER, we could easily code this into the method. If requirements change and we now want to ensure that every method in Foo is restricted to FOO_USER, we suddenly see that this code is getting constantly replicated. The same scenario applies to web pages. If we want to secure all pages in the directory /secured, we would like to apply this restriction only once. Seam makes it easy to handle this cross-cutting concern. As we discuss Seam security throughout this chapter, we will walk you through the basic security features of the Rules Booking example. This example can be found in the examples distributed with the book in the rulesbooking folder. Rule Booking is yet another extension of the Seam Hotel Booking example utilizing basic Seam security 18 Seam Security 233 From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ptg which will be covered in the following sections as well as rules-based authorization (Chapter 22), and using a rule base (see Chapter 23). The Rules Booking example pro- vides a rewards program to the users of the system and allows users to review the hotels they have recently booked. Obviously, these scenarios require certain role and permission checks to ensure that the system provides behavior consistent with the expectations of the business. We will demonstrate how the security features of Seam fit the requirements of this type of application. In addition to basic security, this chapter will cover additional security features provided by Seam, such as SSL and CAPTCHA, to help you to secure your application even further. Do not wait, those hackers could be hitting your web site right now! 18.1 Authentication and User Roles The most important aspect of a security framework is user authentication. Each user must log in with a username and password combo to access the restricted parts of the web application. These username and password are checked against some authentication source (e.g., LDAP, data source, etc.) to verify that the user is who he or she says. Once the user’s identity has been verified, we can determine the role of the user within the application. Each user may have one or several security roles, meaning he or she is authorized to access certain restricted sections or features of the application. For instance, in the Rules Booking example users are either basic users or rewards users. Rewards users have the benefit of gaining reward points each time a booking is confirmed and applying those rewards to future bookings for a saving. Basic users can simply search for and book hotels, as in our previous examples, as well as write reviews on the hotels they have recently booked. In order to differentiate between rewards users and basic users, a re- wards user is associated with the rewardsuser role. Let’s see how we can authenticate users and assign them appropriate roles. Seam is built upon JAAS (Java Authentication and Authorization Service), a standardized solution. It also provides a simplified approach to authentication and authorization that allows you to quickly incorporate security into your application. First, you need to write a login form for the user to enter username and password. In the login form, you should bind the user credentials to the Seam built-in #{credentials} component. The #{identity} component can then be invoked to authenticate the user based on the provided credentials. <div> Username: <h:inputText value="#{credentials.username}"/> </div> CHAPTER 18 SEAM SECURITY 234 From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ptg <div> Password: <h:inputSecret value="#{credentials.password}"/> </div> <div> <h:commandButton value="Account Login" action="#{identity.login}"/> </div> Both the #{credentials} component and #{identity} component are scoped to the HTTP session. Once a user is logged in, he or she stays logged in until the session ex- pires. The #{identity.login} method, in turn, invokes an “authenticator” method to perform the actual authentication work. We will discuss how to configure the authenti- cator method shortly. If the login succeeds, the #{identity.login} method returns the String value loggedIn, which you can use in the navigation rules to determine the next page to display. If the login fails, the #{identity.login} method returns null to redisplay the login form with an error message. The login form home.xhtml allows the users to enter their credentials to log in to the Rewards Booking application, as shown in Figure 18.1. The login form home.xhtml after a failed login attemptFigure 18.1 As you can see, when an attempted login fails, the user is presented with a “Login failed” message. This message can be customized by specifying the org.jboss.seam. loginFailed key in a message.properties resource file. 235 18.1 AUTHENTICATION AND USER ROLES From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ptg Logout The #{identity.logout} method provides a simple mechanism for logging out a user from a Seam application. It simply invalidates the current session and causes Seam to reload the current page—to be redirected to the login page if the current page is restricted. The authentication method, invoked from #{identity.login}, must ensure that the username and password from the injected credentials instance are valid user creden- tials. If they are valid, the method returns true; otherwise, it returns false. After the username and password are verified, the authentication method optionally retrieves the security roles for the user and adds those roles to the Identity component via Identity.addRole(String role). The following authenticate() method is an ex- ample authentication method. It checks the User table in the database to authenticate the user and retrieves the user’s roles from the same database upon successful authentication. @Stateless @Name("authenticator") public class AuthenticatorAction implements Authenticator { @In EntityManager em; @In Credentials credentials; @In Identity identity; @Out(required=false, scope = SESSION) private User user; public boolean authenticate() { List results = em.createQuery( "select u from User u where u.username=#{credentials.username}" + " and u.password=#{credentials.password}").getResultList(); if ( results.size()==0 ) { return false; } else { user = (User) results.get(0); for(Role role : user.getRoles()) { identity.addRole(role.getRolename()); } return true; } } } CHAPTER 18 SEAM SECURITY 236 From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ptg This is a very brute-force approach to authentication, but it can be useful if you must invoke existing authentication logic or perform custom authentication tasks. For Seam to know that the #{authenticator.authenticate} method is the authentication method for the application, you must declare it in the components.xml file: <components xmlns="http://jboss.com/products/seam/components" xmlns:security="http://jboss.com/products/seam/security" xmlns:core="http://jboss.com/products/seam/core"> <security:identity authenticate-method="#{authenticator.authenticate}"/> </components> As you will see in Section 18.3, Seam 2.1 includes support for many common authenti- cation use cases through the IdentityManager component. This allows you to avoid implementing this type of custom authentication logic. Security Lifecycle Events Seam provides a number of lifecycle events for security actions, enabling you to hook into the framework. Examples include: • org.jboss.seam.security.loginSuccessful is raised after a successful login attempt. • org.jboss.seam.security.loginFailed is raised after a login attempt fails. • org.jboss.seam.security.loggedOut is raised when the user has been logged out. These events are enumerated in the Seam documentation and are especially useful for auditing purposes. 18.2 Declarative Access Control Authentication by itself is not very useful; it must be combined with an authorization scheme to grant access to the application based on the user’s identity. Seam makes it easy to declare access constraints on web pages, UI components, and Java methods via XML tags, annotations, and JSF EL expressions. Through this declarative approach Seam allows you to easily build a layered security architecture. Security experts often term this layered approach to security a defense-in-depth approach and recommend its use to deter security threats. Not only does a layered approach decrease vulnerabil- ity to external threats; it also helps to avoid security holes from simple programming error. 237 18.2 DECLARATIVE ACCESS CONTROL From the Library of sam kaplan Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... authentication, the JpaIdentityStore generates the necessary query, based on the field annotated with @UserName as well as the user-entered value of #{credentials.username}, to retrieve the user from the persistent store Once retrieved, the JpaIdentityStore compares the entered #{credentials.password} value with the field annotated with @UserPassword What if you need to access the user entity from the. .. However, the problem with this approach is that it includes a lot of manual coding for both the client-side JavaScript and the server-side Java Servlet An AJAX servlet developer must be very careful with the states of the server-side objects This is obviously not the ideal solution Is there an easier way to support AJAX in JSF and Seam applications? Fortunately, as a cutting-edge web framework, JSF and Seam. .. discuss the following three approaches: • The first approach is to reuse AJAX-enabled JSF UI components The benefits of this approach are simplicity and power: You do not need to write a single line of JavaScript or AJAX servlet code, yet the component itself knows how to render JavaScript and AJAX visual effects; the JavaScript code and the backend communication mechanism are encapsulated in the component... Notice the mix of JPA annotations with Seam security annotations The JPA annotations specify how the User should be stored, allowing you to map the entity to a custom table definition The Seam security annotations specify how the JpaIdentityStore should use this entity The @UserPrincipal annotation defines the field or method containing the user’s username Note that we specify this as an @Id, as the username... Jesse James Garret of Adaptive Path in 2005 The idea is to use JavaScript to retrieve dynamic content from the server and then update the UI components on the web page without refreshing the entire page For example, on a Google Maps (http://maps.google.com) web page, you can use the mouse to pan and zoom the map without page reload The map page captures the user’s mouse events via JavaScript and makes... application and the IdentityManager component The IdentityManager is injected into any dependent components and abstracts the underlying provider The JpaIdentityStore and the LdapIdentityStore are provided by Seam security out -of -the- box and will be discussed in the next few sections Figure 18.2 The RegistrationAction is abstracted from the underlying identity store by interacting with the IdentityManager... presented in the form of an image, it is difficult for an automated agent to provide a correct answer—but not impossible Seam makes it easy to use a simple CAPTCHA while providing the flexibility to increase the level of security as your application grows The Rules Booking example provides an example of using a CAPTCHA within a form In order to use the Seam CAPTCHA, you must first configure the SeamResourceServlet,... IdentityManager API From the Library of sam kaplan 244 CHAPTER 18 SEAM SECURITY Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 18.3.1 Using the JpaIdentityStore The JpaIdentityStore provides identity management with a relational database The Rules Booking example, found in the examples released with the book, demonstrates the use of the JpaIdentityStore First, we must define the entities... AJAX calls back to the server to retrieve new maps to display based on the mouse events The user simply sees that the map gets updated as he or she moves the mouse Another well-known AJAX example is Google Suggest (www.google.com/webhp?complete=1&hl=en) The search box in Google Suggest makes an AJAX call to the server whenever you type something in the box The server returns a list of suggested search... user entity This annotation marks the field or method containing the roles of the user Should be a List or Set @RoleName field, method role entity This annotation marks the field or method containing the name of the role The following entity definition, taken from the Rules Booking example, declares the minimal annotations required to define a user entity for use with the JpaIdentityManager: @Entity @Name("user") . have to use the Seam debug page for this type of error. To use the Seam debug page, you need to follow the instructions in Section 3.3 to bundle the jboss -seam- debug.jar and set up the Seam Exception. ensure that the system provides behavior consistent with the expectations of the business. We will demonstrate how the security features of Seam fit the requirements of this type of application. In. found in the examples distributed with the book in the rulesbooking folder. Rule Booking is yet another extension of the Seam Hotel Booking example utilizing basic Seam security 18 Seam Security 233 From