text:
Patent US6144969 - File name conversion - Google PatentsSearch Images Maps Play YouTube News Gmail Drive More »Sign in<nobr>Advanced Patent Search</nobr>PatentsFile name conversion method, and apparatus, for converting a first file name that can be distinguished by a given operating system into a second file name that can be distinguished both by the given operating system and other operating systems. The method and apparatus insure that the first and second...http://www.google.com/patents/US6144969?utm_source=gb-gplus-sharePatent US6144969 - File name conversionAdvanced Patent SearchPublication numberUS6144969 APublication typeGrantApplication numberUS 08/930,820PCT numberPCT/JP1997/000321Publication dateNov 7, 2000Filing dateFeb 7, 1997Priority dateFeb 9, 1996Fee statusPaidAlso published asEP0821309A1, EP0821309A4, WO1997029426A1Publication number08930820, 930820, PCT/1997/321, PCT/JP/1997/000321, PCT/JP/1997/00321, PCT/JP/97/000321, PCT/JP/97/00321, PCT/JP1997/000321, PCT/JP1997/00321, PCT/JP1997000321, PCT/JP199700321, PCT/JP97/000321, PCT/JP97/00321, PCT/JP97000321, PCT/JP9700321, US 6144969 A, US 6144969A, US-A-6144969, US6144969 A, US6144969AInventorsTatsuya Inokuchi, Osamu Udagawa, Yasuyoshi Kaneko, Kazuhisa TairaOriginal AssigneeSony CorporationExport CitationBiBTeX, EndNote, RefManPatent Citations (15), Non-Patent Citations (2), Referenced by (53), Classifications (9), Legal Events (4) External Links: USPTO, USPTO Assignment, EspacenetFile name conversionUS 6144969 AAbstract File name conversion method, and apparatus, for converting a first file name that can be distinguished by a given operating system into a second file name that can be distinguished both by the given operating system and other operating systems. The method and apparatus insure that the first and second file names do not already exist on an associated recording medium prior to recording the first file name on the recording medium and prior to converting the first file name to the second file name. Also provided is a recording medium on which is recorded a file conversion program for converting the first file name to the second file name and for searching whether or not the file names exist on the recording medium.
8095 block�4 byte+2�4 byte=32388 byte=15.8 block≈16 block                                                     (1)
1�220 kbyte/2 kbyte�4/2048 kbyte=1024 block(2)
170�170/2�145/2�2=2095250≈2 [Gbyte](4)
Furthermore, since the index node immediately after the division is embedded up to 2/3 at most, it is required to newly insert 170/3 indices at least to fill the index nodes. Furthermore, when the adjacent index nodes are not filled, index nodes are moved to average the number of respective indices instead of division. Consequently, the least number of times of the insertion of the index nodes into B*tree (B star tree) which is required from the generation of the division of the index nodes until the next division will be 170/3�2=113. Furthermore, in the case of the leaf nodes, the insertion of at least 145/3�2=96 extents EXTx is required for generating the next division in the same manner. Thus the maximum value CBCmax of data block number generated by the call of one time block generation with respect to the sequence manager SQM will be represented by the following equation:
Patent CitationsCited PatentFiling datePublication dateApplicantTitleUS5359725 *Oct 15, 1991Oct 25, 1994Time Warner Interactive Group, Inc.Method of creating CD-ROM image of files of different format with proper directories to be read by respective operating systemsUS5579517 *Apr 24, 1995Nov 26, 1996Microsoft CorporationCommon name space for long and short filenamesUS5608905 *Apr 25, 1995Mar 4, 1997Software Architects, Inc.DOS and Macintosh preformatted computer storage mediaUS5627996 *Aug 19, 1992May 6, 1997At&TMethod and apparatus for accessing the same computer file using different file name formatsUS5745752 *Dec 13, 1994Apr 28, 1998Microsoft CorporationIn a computer systemUS5745888 *Jul 28, 1997Apr 28, 1998Ncr CorporationAdvanced file server apparatus and methodUS5745902 *Jul 6, 1992Apr 28, 1998Microsoft CorporationMethod and system for accessing a file using file names having different file name formatsUS5754848 *Sep 11, 1996May 19, 1998Hewlett-Packard Co.Apparatus and method for disaster recovery of an operating system utilizing long file and directory namesUS5758352 *Sep 5, 1996May 26, 1998Microsoft CorporationCommon name space for long and short filenamesUS5761675 *Mar 19, 1996Jun 2, 1998Symantec CorporationComputer-implemented methodJPH06161855A * Title not availableJPH06187211A * Title not availableJPH06231023A * Title not availableJPH06309207A * Title not availableJPH07503084A * Title not available* Cited by examinerNon-Patent CitationsReference1Y. E. Gail Wang, "Universal-File-Names for Ada," Ada Letters, vol. 10, No. 1, Feb. 1990, pp. 111-117.2 *Y. E. Gail Wang, Universal File Names for Ada, Ada Letters, vol. 10, No. 1, Feb. 1990, pp. 111 117.* Cited by examinerReferenced byCiting PatentFiling datePublication dateApplicantTitleUS6260140Nov 30, 1998Jul 10, 2001Micron Electronics, Inc.Operating system multi boot integratorUS6275953 *Sep 26, 1997Aug 14, 2001Emc CorporationRecovery from failure of a data processor in a network serverUS6330669 *Nov 30, 1998Dec 11, 2001Micron Technology, Inc.OS multi boot integratorUS6424429 *Nov 13, 1998Jul 23, 2002Ricoh Company, Ltd.File system and a recording medium with a program used in the system stored thereinUS6434574 *Dec 17, 1998Aug 13, 2002Apple Computer, Inc.System and method for storing and retrieving filenames and files in computer memory using multiple encodingsUS6631387 *Apr 30, 2001Oct 7, 2003Lg Electronics Inc.Apparatus for creating and managing navigation information in a rewritable recording mediumUS6654772 *Apr 28, 1999Nov 25, 2003Emc CorporationMulti-volume extent based file systemUS6714952 *Nov 10, 1999Mar 30, 2004Emc CorporationMethod for backup and restore of a multi-lingual network file serverUS6854109 *Jun 7, 2001Feb 8, 2005International Business Machines CorporationTool for converting .MAP file formatsUS6895418 *Apr 28, 1999May 17, 2005Emc CorporationVersatile indirection in an extent based file systemUS7010551 *Mar 15, 2001Mar 7, 2006Sony CorporationFile conversion method, file converter, and file display systemUS7013314 *Jun 20, 2002Mar 14, 2006Apple Computer, Inc.System and method for storing and retrieving filenames and files in computer memoryUS7143445 *May 23, 2000Nov 28, 2006Sony CorporationInformation processing apparatus, information processing method, and program storage mediumUS7346904 *Aug 7, 2003Mar 18, 2008International Business Machines CorporationSystems and methods for packaging files having automatic conversion across platformsUS7370066 *Mar 24, 2003May 6, 2008Microsoft CorporationSystem and method for offline editing of data filesUS7490109 *Mar 6, 2006Feb 10, 2009Microsoft CorporationSystem and method for offline editing of data filesUS7526497 *Mar 13, 2007Apr 28, 2009Canon Kabushiki KaishaDatabase retrieval apparatus, retrieval method, storage medium, and programUS7620300Feb 20, 2003Nov 17, 2009Lg Electronics, Inc.Method for creating and managing navigation information in a rewritable recording mediumUS7801906Feb 22, 2006Sep 21, 2010Apple Inc.System and method for storing and retrieving filenames and files in computer memoryUS7856459 *Jan 5, 2005Dec 21, 2010Sony CorporationRecording apparatus, recording method, and disc shaped record mediumUS7860907 *Jun 29, 2007Dec 28, 2010Data Equation LimitedData processingUS7917539 *Jan 28, 2008Mar 29, 2011Netapp, Inc.Zero copy write datapathUS7925621 *Jan 29, 2008Apr 12, 2011Microsoft CorporationInstalling a solutionUS7949623Dec 5, 2005May 24, 2011Hiflex Software GesmbhCommunication methodUS7991781Dec 28, 2006Aug 2, 2011Apple Inc.System and method for storing and retrieving filenames and files in computer memoryUS8095576 *Nov 1, 2007Jan 10, 2012Panasonic CorporationRecording deviceUS8117552Dec 5, 2006Feb 14, 2012Microsoft CorporationIncrementally designing electronic forms and hierarchical schemasUS8141074Jan 7, 2008Mar 20, 2012International Business Machines CorporationPackaging files having automatic conversion across platformsUS8295677May 17, 2004Oct 23, 2012Lg Electronics Inc.Method for creating and managing navigation information in a rewritable recording mediumUS8321439Feb 20, 2009Nov 27, 2012Microsoft CorporationQuick filename lookup using name hashUS8341197Dec 28, 2007Dec 25, 2012Nippon Telegraph And Telephone CorporationEncoder, decoder, their methods, programs thereof, and recording media having programs recorded thereonUS8364732Jan 13, 2011Jan 29, 2013Microsoft CorporationExtending cluster allocations in an extensible file systemUS8433677Jun 16, 2011Apr 30, 2013Microsoft CorporationExtending cluster allocations in an extensible file systemUS8438172Jul 23, 2008May 7, 2013Fujitsu LimitedInformation processing method, information processing program and information processing deviceUS8452729Jan 13, 2011May 28, 2013Microsoft CorporationExtending cluster allocations in an extensible file systemUS8560555 *Jul 20, 2011Oct 15, 2013Fujitsu LimitedInformation processing method, information processing program and information processing deviceUS8583708Mar 20, 2008Nov 12, 2013Microsoft CorporationExtensible file systemUS8606830Feb 20, 2009Dec 10, 2013Microsoft CorporationContiguous file allocation in an extensible file systemUS8624983 *Mar 20, 2008Jan 7, 2014Canon Kabushiki KaishaDigital information input apparatusUS8725772May 2, 2013May 13, 2014Microsoft CorporationExtending cluster allocations in an extensible file systemUS8805780May 24, 2013Aug 12, 2014Microsoft CorporationExtending cluster allocations in an extensible file systemUS20080170045 *Mar 20, 2008Jul 17, 2008Canon Kabushiki KaishaDigital information input apparatusUS20110125768 *Jun 26, 2009May 26, 2011Canon Kabushiki KaishaInformation processing apparatus, method of controlling the same, and storage mediumUS20110276544 *Jul 20, 2011Nov 10, 2011Fujitsu LimitedInformation processing method, information processing program and information processing deviceUS20120137218 *Nov 30, 2010May 31, 2012International Business Machines CorporationMethod to Automatically Display Filenames Encoded in Multiple Code SetsCN100580799CJan 20, 2004Jan 13, 2010索尼株式会社Recording device, regeneration device, and file management methodDE102004059045A1 *Dec 7, 2004Jun 8, 2006Hiflex Software GmbhVerfahren zur KommunikationDE102004059045B4 *Dec 7, 2004Jan 24, 2008Hiflex Software GmbhVerfahren zur Kommunikation zwischen einem Management Information System und einem ausf�hrenden System und KommunikationsmodulEP2093672A1 *Dec 28, 2007Aug 26, 2009Nippon Telegraph and Telephone CorporationEncoding and decoding apparatus, method, and program, and recording mediumEP2290564A1 *Dec 1, 2005Mar 2, 2011Microsoft CorporationExtensible file systemEP2294511A1 *Jun 26, 2009Mar 16, 2011Canon Kabushiki KaishaInformation processing apparatus, method of controlling the same, and storage mediumWO2006061162A1 *Dec 5, 2005Jun 15, 2006Hiflex Software GmbhCommunication methodWO2010001979A1Jun 26, 2009Jan 7, 2010Canon Kabushiki KaishaInformation processing apparatus, method of controlling the same, and storage medium* Cited by examinerClassifications U.S. Classification707/705, 707/E17.01, 707/999.2, 707/821, 707/999.001International ClassificationG06F17/30Cooperative ClassificationY10S707/99931, G06F17/30123European ClassificationG06F17/30F5G1Legal EventsDateCodeEventDescriptionMay 3, 2012FPAYFee paymentYear of fee payment: 12May 7, 2008FPAYFee paymentYear of fee payment: 8May 7, 2004FPAYFee paymentYear of fee payment: 4Jan 12, 1998ASAssignmentOwner name: SONY CORPORATION, JAPANFree format text: ASSIGNMENT OF ASSIGNORS INTEREST;ASSIGNORS:INOKUCHI, TATSUYA;UDAGAWA, OSAMU;KANEKO, YASUYOSHI;AND OTHERS;REEL/FRAME:008903/0974Effective date: 19971104RotateOriginal ImageGoogle Home - Sitemap - USPTO Bulk Downloads - Privacy Policy - Terms of Service - About Google Patents - Send FeedbackData provided by IFI CLAIMS Patent Services©2012 Google


text:
1. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
2. MEAP Edition Manning Early Access Program Copyright 2008 Manning Publications For more information on this and other Manning titles go to www.manning.comPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
3. TABLE OF CONTENTSPart 1: Getting StartedChapter 1: Introducing Spring: the IoC containerChapter 2: Working with databases and transactionsChapter 3: Spring Web MVCPart 2: General Application RecipesChapter 4: User registrationChapter 5: AuthenticationChapter 6: User account redux and authorizationChapter 7: Site navigation and themesChapter 8: Communicating with users and customersChapter 9: CommunityChapter 10: Application monitoring and diagnosticsPart 3: Domain-Specific RecipesChapter 11: Product catalogsChapter 12: Shopping cartsChapter 13: Customer ordersChapter 14: Lead generation and qualificationChapter 15: Customer relationship managementChapter 16: Technical supportPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
4. 4 User registrationUser registrations are important. For many applications and websites, registration rates areclosely tied to revenue goals: registrations generate revenues. They enable orders, theysupport targeted marketing campaigns and advertising, and in general they represent ausers or customers desire for an ongoing relationship with your company or website. Forthese reasons alone it literally pays to take user registrations seriously. User registrations are also a source of risk. User data is sensitive and we have to secureit to avoid PR, legal and operational problems. We want to reduce our exposure to legal riskby presenting our privacy policy and asking registrants to acknowledge our terms of use.Sometimes we have to take steps to protect children too.1 Given this dual importance, we want to get our registration forms right. We dont wantavoidable usability issues to cost us registrations. We dont want to compromise user data.And we dont want to expose our employers or ourselves to lawsuits. Attention to detail helps. Consider the problem of maximizing user registrations. The formshould be short, nonthreatening and easy to use. We can  put users at ease by delivering the initial form over HTTPS even though it doesnt offer any security advantage;  provide an explicit privacy policy (which has usability and presumably legal benefits);  use a "Register securely" button instead of simply saying "Register" or "Submit;" and1 See http://www.coppa.org/ for more information about protecting children. Its about now that Ill invoke IANAL("I am not a lawyer"). Dont take anything in this chapter or in this book to be legal advice. Its not. If you needlegal advice please contact a qualified legal expert. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
5.  improve the forms usability by giving focus to the first form field when the form loads, providing descriptive form labels and error messages, highlighting fields containing errors and so forth.While these gestures may seem small, collectively they can increase registration rates bymaking your site more trustworthy and convenient to use. Our goal for this chapter is to learn how to design and implement user registration formsusing Spring. We will of course consider standard topics such as displaying the form,validating user data and saving user data. But well also explore design issues that allow usto improve usability, improve security and address legal risk.4.1 Display a registration formPREREQUISITESNoneKEY TECHNOLOGIESSpring Web MVC, Spring form tag libraryBackgroundUsers often establish a more in-depth relationship with a website or an organization byregistering. The resulting account supports an ongoing relationship between the user and thewebsite, allowing logins, order placement, community participation and so on. Usability, security and legal risk are key concerns commonly associated with userregistration forms: we want simple and trustworthy forms to encourage registrations, wewant secure forms to prevent user data from being compromised, and we want to dowhatever we need to do to keep our lawyers smiling. In this recipe well build out aregistration form, paying particular attention to these and other issues.ProblemYou want to create a web-based user registration form. The form should accept standardinputs (first name, e-mail, etc.) and bind them to a user model for further processing. Theform should be usable and secure. Finally it should adopt standard approaches for reducinglegal exposure, such as requiring the user to acknowledge terms of use.SolutionIn this recipe, well use Spring Web MVC to display a user registration form. Well build auser model, a registration form, a confirmation page and a controller to process formsubmissions. Well bind user inputs to the user model so we can easily validate and storeuser data. (Well validate the user model in recipe 4.2 and store the data in recipe 4.3.)CREATE A USER MODELModel objects store information users provide in web-based forms. These are variouslyreferred to as command objects, form-backing objects (a.k.a. form beans) or model objects,depending on the specific flavor. In this case were using something thats halfway between aPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
6. form bean and a model object since were modeling the form itself (witness thepasswordConfirmation field) but later well persist our User instances (which makesUser more like a model object). Well just call ours a "user model." Here it is:Listing 4.1 User.java, a user model for our registration form package r4_1.model; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; public class User { private String firstName; #1 private String lastName; private String username; private String email; private String password; private String passwordConfirmation; #2 private boolean marketingOk = true; #3 private boolean acceptTerms = false; #4 private boolean enabled = true; #5 public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } ...other getter/setter pairs... public String toString() { #6 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("firstName", firstName) .append("lastName", lastName) .append("userName", username) .append("email", email) .append("marketingOk", marketingOk) .append("acceptTerms", acceptTerms) .append("enabled", enabled) .toString(); } }Cueballs in code and text #1 Standard persistent demographic data #2 Nonpersistent password confirmation #3 OK to market to user? #4 Does user accept terms of use? #5 Is account enabled? #6 toString() implementationPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
7. User is a user model with properties for personal [#1], security-related [#2], marketing[#3] and legal [#4] information, which are all common registration form concerns. Note thatthe passwordConfirmation field is a little out of place: in reality its more a part of theform model rather than the user model, but its convenient to include it here. We also havean administrative enabled property [#5], which has precisely the opposite characteristics:its part of the user model but not part of the form. One of the design decisions youll have tomake when dealing with registration forms (and forms in general) is how "pure" you wantyour models to be. If you want to separate your form model and user model you can do that,but were opting here to just combine the two into a single form. Weve defaulted our marketingOk property to true since wed like to market to ourusers unless they explicitly opt out. On the other hand, weve defaulted acceptTerms tofalse because we want the users acceptance of the terms of use to be active rather thanpassive. Presumably this gives us a stronger legal leg to stand on in the event of adisagreement with the user.2 User conforms to the JavaBeans component model, having getters and setters for eachproperty. This allows Spring Web MVC to bind registration form data our User bean forfurther processing. Also, weve included a descriptive toString() method [#6], based onthe Commons Lang library, so we can see the form binding later in the recipe. Let’s move on to the views.CREATE A REGISTRATION FORM VIEWLets create a basic registration form that we’ll enhance over the course of the chapter. Allwe need for now are labels and input fields. Figure 4.1 shows what we want to build:2 Again, I am not a lawyer! Consult a qualified legal expert if necessary. See footnote 1.Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
8. Figure 4.1 The bare-bones registration form we will createAnd here, in listing 4.2, is a JSP that does it:Listing 4.2 form.jsp, a view to display our registration form <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">   <title>Register</title>
Register
Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
9.
All fields are required.
 <form:form modelAttribute="user"> #1

First name:
 <form:input path="firstName" size="40"/> #2

Last name:
 <form:input path="lastName" size="40"/>

E-mail address:
 <form:input path="email" size="40"/> We wont spam you

User name:
 <form:input path="username" size="40"/>

Password:
 <form:password path="password" showPassword="true" size="40"/> #3

Confirm password:
 <form:password path="passwordConfirmation" showPassword="true" size="40"/>

 <form:checkbox path="marketingOk"/> #4 Please send me product updates by e-mail.
 (You can unsubscribe at any time.)

 <form:checkbox path="acceptTerms"/> I accept the  terms of use.
 Please see our privacy policy.
 <input type="submit" value="Register"/> #5
 </form:form>  Cueballs in code and text #1 Renders an HTML <form> #2 Renders an HTML <input type="text"> #3 Renders an HTML <input type="password">Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
10. #4 Renders an HTML checkbox #5 No special submit tagOur registration view is simple enough. It uses the form [#1], input [#2], password [#3]and checkbox [#4] tags from the Spring form tag library to render HTML form elementsthat are "bound" to their underlying properties. This means that the form elementsautomatically reflect the value contained in the underlying user model, and that changes tothe form element will be pushed into the user model when the form is submitted. Well seethis in action in recipe 4.2; for now its enough to understand that these are basicallyenhanced HTML form input widgets. The tag library doesnt provide anything for submitbuttons, so we just use standard HTML [#5]. Lets pause to consider some usability concerns weve attempted to address with thedesign of the registration form in listing 4.2.DESIGN ISSUES: USER PSYCHOLOGY AND USABILITYIn many cases its an important business goal to maximize registration rates. Attention touser psychology and usability can pay dividends here; the general theme is to eliminatebarriers to completing the form. Here are several ideas: 1. Obviously you dont always control the business requirements here, but try to minimize the number of fields that the user is required to complete. Clearly distinguish required from optional fields. 2. Even better than minimizing the number of required fields is to minimize the number of fields, period. Long forms are intimidating. Multipage registration forms are similarly intimidating, especially if it isnt clear how long the form actually is. Providing visual indications of progress can be helpful in multipage registration scenarios. 3. Understand that certain types of data are much more "personal" than other types, and that by requiring (or even asking for) highly personal data, your registration rates will drop. If you ask me for my first name, that is probably OK, but if you ask for my phone number, my home address or my SSN, I have to be pretty committed before I complete your registration form. 4. Do what you can to establish trust with the user. In listing 4.2, weve indicated that we wont spam the user and weve provided a link to a privacy policy. If youre asking for highly personal data of the sort described in item 3 above, then consider adding "Why?" links next to the field to explain why youre asking for the data in question. In chapter 6 well discuss the use of HTTPS to further establish trust with the user. 5. Dip into your bag of "stupid JavaScript tricks" if it helps you enhance usability. In listing 4.2 we use JavaScript to place initial focus on the first name field. Its small but it helps. Avoid using purely gratuitous effects. Effects that enhance usability (such as highlighting the currently selected form field) are great.Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
11. 6. Normally wed use the HTML label element for our checkboxes for improved usability, but it doesnt make to do that for the terms of use since the text contains a link. And it probably doesnt make sense to use the label for one checkbox but not the other, so weve just left them off. 7. Use analytics and site optimization tools to try different ideas out, such as "what happens to registration rates if we stop asking for home addresses?" Google Analytics and Google Optimizer can be of great value here (and theyre free).Those are some common usability design issues associated with registration forms. Lets lookbriefly at some other design issues.DESIGN ISSUES: ADDRESSING SECURITY AND LEGAL CONCERNSWeve already discussed these a bit, but besides taking steps to improve usability, we alsowant the form to be secure, and to address legal risks. Regarding security, well have much more to say in recipe 4.4 and in chapter 6, but evenwith the simple display of the form were dealing with certain security issues. We use theHTML password element to keep passwords hidden from onlookers. We can use theshowPassword attribute of the form:password tag to control whether the password isprepopulated in the case of a form validation error. (Well cover validation in recipe 4.2.)Suppressing the password is probably a bit more secure, especially if you arent usingHTTPS, but showing it is more convenient for the end user. So take your pick. We mentioned the privacy policy and terms of use in connection with legal issues. Werelaunching those two items in a new window so the user doesnt lose all of his registrationdata should he click on them. One other piece that bears repeating is the Childrens Online Privacy Protection Act, orCOPPA. If your site targets children under 13 or if you know that you have users under 13,then you will want to find out more about COPPA. Obviously the specific legal issues that apply to your site are going to depend on thenature of your business and site, so you should consult a qualified legal expert if you haveany questions or doubts in this area. With the design issues behind us, were done with the registration form itself (at least asfar as the current recipe is concerned). In the next recipe well see how to use theregistration page we just created not only for initially delivering the form but also forhandling validation failures. But for now lets examine the confirmation page that users seeafter they successfully register.CREATE A BASIC CONFIRMATION PAGEWe need a page to send users to once theyve successfully registered. Heres a minimalisticconfirm.jsp file: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
12.
Registration Confirmed

Thank you for registering.
  Nothing fancy at all. It doesnt really even have to be a JSP though its a little easier to setyour Spring view resolution up if you make it one, as opposed to making it an HTML file. Were all done with our user model and our two views. Now its time for us to handle thethird part of the MVC triumvirate: the controller.COORDINATE THE MODEL AND VIEWS WITH A REGISTRATION FORM CONTROLLEROur registration form controller, in listing 4.3, handles both GET and POST requests for theregistration form.Listing 4.3 RegFormController.java, a controller to serve and process registrationforms package r4_1.web; import java.util.logging.Logger; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.*; import r4_1.model.User; @Controller @RequestMapping("/register/form") public class RegFormController { private static final String MA_USER = "user"; @RequestMapping(method = RequestMethod.GET) #1 public void form(Model model) { model.addAttribute(MA_USER, new User()); } @RequestMapping(method = RequestMethod.POST) #2 public String form( @ModelAttribute(MA_USER) User user, BindingResult result) { verifyBinding(result); Logger.global.info("Processing user: " + user); return "redirect:confirm"; } @InitBinder public void initBinder(WebDataBinder binder) { binder.setAllowedFields(new String[] { #3Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
13. "firstName", "lastName", "email", "username", "password", "passwordConfirmation" "marketingOk", "acceptTerms" }); } private void verifyBinding(BindingResult result) { #4 String[] suppressedFields = result.getSuppressedFields(); if (suppressedFields.length > 0) { throw new RuntimeException("Youve attempted to bind fields [CA]that havent been allowed in initBinder(): " + StringUtils.join(suppressedFields, ", ")); } } }Cueballs in code and text #1 Show the form on GET requests #2 Process the form on POST requests #3 Define a binding "whitelist" #4 Throw RuntimeException when fields aren’t in the whitelistGET requests retrieve our form at [#1] and we process POST requests at [#2]. Currently, wedont do much when users click submit. We simply send them to our confirmation page,which is handled by a separate controller (not shown). Of course, in the recipes that followwell add functionality to the form submission handler method. As noted earlier, Spring Web MVC takes care of binding HTML form fields to our modelproperties. Internally, it uses request parameters and reflection to do this, and thatssomething that makes Spring Web MVC easy to use from a developers perspective. Unfortunately, that convenience also makes Spring Web MVC easy to hack if youre notpaying attention.A POTENTIAL SECURITY ISSUE SURROUNDING FORM BINDINGHackers (the bad kind) could potentially alter the state of our model objects by craftingmalicious requests. For example, our User object has an enabled property that is initiallyset to true, but what if we needed to initially set it to false and enable users only afterthey clicked a special link in a confirmation e-mail we sent them? In that case, a hackercould craft a request with enabled set to true in our form, and he’d bypass ourconfirmation process. Spring Web MVC makes it fairly straightforward to protect our application from this sortof data injection attack. To make sure our forms arent altered, were using the@InitBinder annotation to define an explicit whitelist containing all the fields the binder isallowed to bind at [#3]. Any submitted parameters not in the whitelist remain unbound. In practice, the problem with doing this is that we have to remember to update ourwhitelist every time we add a new field to our class and form; otherwise well scratch ourPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
14. heads wondering why our field isnt being bound. To solve this problem weve created ahelper method at [#4] that throws a RuntimeException every time a new parameter issubmitted but isnt explicitly allowed by the binder.DiscussionUser registrations are an important piece of application functionality. Whether or not our goalis to maximize registrations, we certainly want our registration forms to be usable, secure,legally helpful and well-engineered. In this recipe weve seen how a little analysis coupledwith Spring Web MVC can help. Its worth noting that much of what weve done so far isnt particularly tied to registrationforms; you can use this recipe as a blueprint for displaying web-based forms in general. Aswe move forward in the chapter well continue to target registration forms, but most of thediscussion and techniques will be broadly applicable. Not all applications that require user logins need registration forms. Sometimes you willhave an account provisioning process instead of a user registration process. In the following recipes well build upon the work weve done to validate and saveregistration data. Well also look at techniques for making registration forms more secure,both in recipe 4.4 and in chapter 6.4.2 Validate user registrationsPREREQUISITE4.1 Display a registration formKEY TECHNOLOGIESSpring Web MVC, Spring Validation, Bean Validation Framework, Spring form tag libraryBackgroundPeople make mistakes. No matter how intuitive our registration form might seem, chancesare good that people will accidentally or even intentionally fill it out with garbageinformation. We generally treat such errors as user errors rather than system or applicationexceptions, meaning that we usually want to explain the error to the user in non-technicallanguage and help him overcome it. Several frameworks exist to assist with handling user errors of this sort, includingCommons Validator, Valang, Hibernate Validator and the Bean Validation Framework.Fortunately, Spring integrates with such frameworks.ProblemWhen users submit registration form data, you want to validate it before saving it to apersistent store. If there are validation errors, you would like to help the user understandwhat went wrong, and you would like to make it as easy as possible for him to correct theissue so he can continue.Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
15. SolutionWe will use the Bean Validation Framework (BVF) to validate user registrations. The BVF,which is based on the Spring Validation framework, is part of the Spring Modules project.The BVF is nice because it supports annotation-based declarative validation.3 With the BVF,we can annotate our User properties with validation rules. The annotations work with theform binding we set up in the previous recipe to flag rule violations and generate errorcodes. Spring Validation maps those to localized error messages.ANNOTATE THE USER DOMAIN OBJECT WITH VALIDATION RULESBVF annotations are straightforward and easy to use. Revisiting our User class, lets seehow it looks fortified with validation rules. Listing 4.4 shows the code:Listing 4.4 Annotating User fields with validation rules package r4_2.model; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.springmodules.validation.bean.conf.loader.annotation.handler.*; public class User { @NotBlank #1 @MaxLength(40) #2 private String firstName; @NotBlank @MaxLength(40) private String lastName; @NotBlank @MaxLength(20) private String username; @NotBlank @MaxLength(80) @Email #3 private String email; @NotBlank @MaxLength(20) @Expression(value = "password equals passwordConfirmation", #4 errorCode = "password.not.match") #5 private String password; private String passwordConfirmation; private boolean marketingOk = true;3 Hibernate Validator also supports annotation-based declarative validation. JSR-303 targets the development of astandard approach to annotation-based bean validation.Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
16. @Expression(value = "acceptTerms equals true", #6 errorCode = "terms.not.accepted") private boolean acceptTerms = false; private boolean enabled = true; ... }Cueballs in code and text #1 First name can’t be empty or null #2 First name can’t be over 40 characters #3 E-mail must be formatted correctly #4 Password must match confirmation #5 Override error code ‘expression’ with ‘password.not.match’ #6 User must accept termsIn listing 4.4, @NotBlank [#1] makes sure fields arent empty or null, @MaxLength [#2]constrains fields to specified lengths and @Email [#3] ensures the e-mail field contains avalid e-mail address. The @Expression [#4] annotation over password takes as its firstargument a freeform expression; the one weve provided enforces password equality.MAP ERROR CODES TO MESSAGES IN A PROPERTIES FILEWhen one or more validation rules are broken, BeanValidator generates error codes thatSpring then resolves to localized messages. The correspondence between the annotationsthemselves and their generated error codes is intuitive. For example, @NotBlank generatesnot.blank and @Email generates email. In our @Expression annotation, weve replacedthe default error code, expression, with password.not.match [#5]. Error codes are mapped to messages in a standard error.properties file: not.blank=Please enter a value. max.length=Please enter no more than {1} characters. email=Please enter a valid e-mail. password.not.match=Passwords do not match. Its also worth mentioning that we have fine-grained control over how error codes map tomessages. We can specify error codes with rule.bean.property syntax, and they willtake precedence, on a per-field basis, over error codes with only the rule specified like thoseabove. So, not.blank.user.firstName would take precedence over not.blank andwould only apply to the firstName field on User. You might want to do this, for instance,to provide a more descriptive error message, such as one that describes the expectedformat, or one that is just clearer. (Compare "Password cannot be blank" to "Please choose apassword containing at least six characters.") The user must accept the terms of use to register [#6].Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
17. SET UP BEANVALIDATOR WITH ANNOTATIONS SUPPORT IN THE SPRING CONFIGURATIONNow we need to wire up BeanValidator with a few dependencies. We also need to specifyour message source. Listing 4.5 shows the configuration for this:Listing 4.5 Configure your BeanValidator in your application context <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/ [CA]spring-context-2.5.xsd"> <context:component-scan base-package="r4_2.web"/> <bean class="org.springframework.web.servlet.view. [CA]InternalResourceViewResolver" p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/> <bean id="configurationLoader" class="org.springmodules.validation.bean.conf.loader.annotation. [CA]AnnotationBeanValidationConfigurationLoader"/> #1 <bean id="errorCodeConverter" class="org.springmodules.validation.bean.converter. [CA]KeepAsIsErrorCodeConverter"/> #2 <bean id="validator" class="org.springmodules.validation.bean.BeanValidator" p:configurationLoader-ref="configurationLoader" p:errorCodeConverter-ref="errorCodeConverter"/> #3 <bean id="messageSource" class="org.springframework.context.support. [CA]ReloadableResourceBundleMessageSource" p:basename="WEB-INF/errors"/> </beans>Cueballs in code and text #1 Extracts validation rules from annotations #2 Fine- and coarse-grained message codes #3 BeanValidatorAnnotationBeanValidationConfigurationLoader [#1] extracts validation rules fromour annotations. Incidentally, BeanValidator [#3] can also work with XML files given thePlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
18. appropriate configurationLoader, but we dont cover that in this book.KeepAsIsErrorCodeConverter [#2] lets us choose between fine- and coarse-grainedmessage resolution as we discussed above. The default ErrorCodeConverterimplementation, ModelAwareErrorCodeConverter, supports only fine-grained messagecodes, so there isnt a good reason to use it.INJECT THE VALIDATOR IN THE CONTROLLER AND VALIDATE THE USER MODELWith our BeanValidator configured, listing 4.6 shows how to autowire it into our controllerand use it to validate our user model:Listing 4.6 Wiring up BeanValidator in RegFormController and validating Users package r4_2.web; import org.springframework.validation.Validator; ...other imports... @Controller public class RegFormController { private static final String MA_USER = "user"; @Autowired private Validator validator; public void setValidator(Validator validator) { this.validator = validator; } @RequestMapping(method = RequestMethod.POST) public String form( @ModelAttribute(MA_USER) User user, BindingResult result) { verifyBinding(result); validator.validate(user, result); #1 if (result.hasErrors()) { result.reject("form.problems"); #2 return "register/form"; } Logger.global.info("Processing user: " + user); return "redirect:confirm"; } ...other methods... }Cueballs in code and text #1 Validate the model #2 Return to form if errors presentPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
19. The validate() method [#1] takes in our user model and determines whether or not anyvalidation rules have been violated. It reports any problems to the result object, which isthen implicitly passed on to our view and rendered (as error messages) if it contains errors.If there are any validation errors, we create a global error [#2], which well display at thetop of the form shortly.USE THE SPRING FORM TAG LIBRARY TO DISPLAY VALIDATION ERRORS ON THE REGISTRATION FORMWe indicated earlier that when a user makes an error, one of our goals is to help himunderstand what went wrong and to fix it. We present user-friendly error messages thatexplain exactly those things. For that, we turn to the Spring form tag library. Besides displaying helpful error messages, we also want to help the user quicklytriangulate on the error by visually distinguishing the problematic fields from the others. Figure 4.2 shows how our form looks with validation applied:Figure 4.2 Heres how our form will look when it is submitted with problems. In listing 4.7, we display validation errors to the user using the form:errors tag:Listing 4.7 Displaying validation errors in form.jsp with the Spring Form tag library <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>   <title>Register</title>
Register
 <form:form>

First name:
 <form:input path="firstName" size="40" cssErrorClass="form-error-field"/> #1
 #2 <form:errors path="firstName"/>

 ...other form fields... </form:form> ...  Cueballs in code and text #A Error messages are red to distinguish from other text #B Inputs with errors have a light yellow background #1 This CSS class is only selected for inputs with errors #2 Empty until errors are presentThe divs that contain form:errors tags [#1] are empty until validation errors are present.Then, our localized error messages display in red to distinguish them from the rest of theform labels. The cssErrorClass attribute [#2] renders as a standard HTML classattributes when its corresponding field has a validation error. We use it to apply a subtleyellow background to indicate that the field requires attention.DISPLAY A BANNER OVER THE REGISTRATION FORM TO ALERT USERS OF PROBLEMSWhen there are errors, lets display a large banner over the entire form that reads, "Pleasefix the problems below." This helps the user understand more immediately that the formdata must be corrected. Figure 4.3 shows the form after we add the banner:Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
21. Figure 4.3 We want to display a banner over the form to grab our users’ attentionFirst, lets add the error code and message to our errors.properties file: form.problems=Please fix the problems below: not.blank=Please enter a value. max.length=Please enter no more than {1} characters. email=Please enter a valid e-mail. password.not.match=Passwords do not match.Next, we add a line of code to our POST-handler form() method in our controller: @RequestMapping(method = RequestMethod.POST) public String form( @ModelAttribute(MA_USER) User user, BindingResult result) { verifyBinding(result); validator.validate(user, result); if (result.hasErrors()) { result.reject("form.problems"); return "register/form"; } return "redirect:confirm"; }The result object tracks two different types of errors. When the annotation-basedvalidation rules we set up earlier are broken, they are tracked as field errors. Additionally,result can track global errors, or errors related to an entire form. Here, weve manipulatedresult directly by calling result.reject() with a single error code, which will beinterpreted as being global. In listing 4.8 we add a bit of code to our registration form so it displays the global error:Listing 4.8 Displaying a global error message with the Spring tag libraryPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
22. <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> #1 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> ...  <title>Register</title>   <form:form> <spring:bind path="user"> <spring:hasBindErrors name="user"> #2
<form:errors/>
 </spring:hasBindErrors> </spring:bind> ... the fields and their errors ... </form:form> ...Cueballs in code and text #1 Import Spring tag library #2 Check for global errorsHere weve imported the Spring tag library [#1], which is a predecessor of the Spring formtag library. Among other things, it provides lower-level binding functionality than the Springform tag library. It still supplies one bit of functionality that the Spring form tag librarycuriously does not: the ability to test whether or not a model object or its fields have errorsassociated with them [#2]. We rely on that functionality here because our global errormessage displays in a div with padding applied to it, and we dont want a large empty spaceto show up when the error isnt present.Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
23. DiscussionForm validation helps us clean our data before passing it along to a persistent store. In thisrecipe we saw how to use annotations to attach validation rules to individual form fields in aconvenient and intuitive way. Our treatment handles validation in the web tier. Thats a standard approach, but youshould know that its not the only one—indeed, validation frameworks nowadays (e.g.,Hibernate Validator, Bean Validation Framework) tend to abandon the assumption thatvalidation exclusively in the web tier. Some people advocate validating data in the businessand data access tiers as well. This approach can provide extra assurance that bad data wontmake its way into our business logic or our data stores, often with no significant performanceimpact. In some cases, performing validation in the business tier (with the web tier perhapsdelegating validation to the business tier) can also keep the business tier API clean. Welldiscuss this further in a recipe 4.4 "brother vs. brother" sidebar. With validation done, its now time to look at submitting form data from the browser tothe server in a secure manner.4.3 Save user registrationsPREREQUISITES4.1 Display a registration form4.2 Validate user registrationsKEY TECHNOLOGIESSpring, JPA, Hibernate 3, MySQL or other RDBMSBackgroundSo far we’re accepting and validating user registrations as they come in, but we aren’t savingthem anywhere. In this recipe, we’ll persist them using Spring, JPA and Hibernate.ProblemYou want to save users to a persistent store so you can load and work with them later, andyoud like to do this in a way thats compatible with Spring Security.SolutionThere are of course multiple ways in which we might store user data. Here were going totake one perfectly standard and popular approach, which is to use Hibernate 3 ORM sitting infront of a database.CREATE A DATABASE SCHEMA FOR STORING USERSWell start with a simple database schema that contains a table for users and another fortheir roles. We haven’t discussed roles yet, but Spring Security logins require them, so wellproceed with that in mind. Listing 4.11 shows our MySQL schema, but you should be able toget it working with your RDBMS of choice with some minor tweaking:Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
24. Listing 4.11 A schema that supports user registrations create table users ( id int(10) unsigned not null auto_increment primary key, first_name varchar(40) not null, last_name varchar(40) not null, email varchar(80) unique not null, username varchar(20) unique not null, password varchar(40) not null, marketing_ok tinyint(1) not null, accepts_terms tinyint(1) not null, enabled tinyint(1) not null, date_created timestamp default current_timestamp ); create table roles ( user_id int(10) unsigned not null, role varchar(20) not null, foreign key (user_id) references users (id) );In the users table, all of the columns, except id and date_created, represent ourfamiliar User properties. id is our standard primary key, and date_created is atimestamp that MySQL will automatically fill in when a row is created (we don’t happen touse date_created in our model, but it’s a nice-to-have for reporting and auditing). Were using a pretty large length for the password field because were eventually goingto store an SHA-1 hash in there. (Well do this in chapter 6.) We’ve also put unique constraints on the username and email columns. It’s standardpractice to disallow duplicate usernames in a system since they essentially function as user-friendly identifiers. For some applications duplicate e-mails are acceptable and for otherstheyre not. SECURITY TIP If your system requires unique e-mail addresses, its a good idea to require users to confirm their e-mail address (for example, by sending a confirmation e-mail to the address in question) before activating the account. Otherwise its possible for a user to hijack somebody elses e-mail address. (I sign up as you, Im awarded the account, now youre out of luck if you want to sign up for the same site.)ANNOTATE THE USER MODEL FOR PERSISTENCEAs described in chapter 1, Hibernate 3 provides annotations to support the Java PersistenceAPI (JPA) standard. Listing 4.12 below shows our User object annotated for persistence.Listing 4.12 User.java with persistence semantics package r4_3.model;Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
25. import org.hibernate.annotations.CollectionOfElements; ... JPA and other imports ... @Entity @Table(name = "users") public class User { private static final String DEFAULT_ROLE = "ROLE_USER"; private Long id; ... other private fields, with validation annotations ... public User() { addRole(DEFAULT_ROLE); } @Id @GeneratedValue public Long getId() { return id; } @SuppressWarnings("unused") private void setId(Long id) { this.id = id; } @Column(name = "first_name") #1 public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } ... other getter/setter pairs ... @Transient #2 public String getPasswordConfirmation() { return passwordConfirmation; } @CollectionOfElements(targetElement = java.lang.String.class) #3 @JoinTable(name = "roles", joinColumns = @JoinColumn(name = "user_id")) @Column(name = "role") public Set<String> getRoles() { return roles; } public void setRoles(Set<String> roles) { this.roles = roles; } public void addRole(String role) { roles.add(role);Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
26. } public String toString() { ... } }Cueballs in code and text #1 Maps first name to database column #2 Not persistent #3 Hibernate annotation; collection of value typesJPA assumes all properties are persistent unless they are marked as @Transient, sousername, email, and password are ready as-is. We use the @Column annotation to mapproperties to database columns [#1]. passwordConfirmation is marked @Transient[#2] because we dont want to save it to the database; we were simply using it for formvalidation. We’ve set roles up as collection of simple Hibernate value types, and JPAdoesn’t support relationships for those yet; therefore, we’ve dropped back to nativeHibernate @CollectionOfElements [#3] annotation to make them persistent. We add a default role by calling addRole(DEFAULT_ROLE) in the constructor. SpringSecurity logins require at least one role.CREATE THE USER DATA ACCESS OBJECTIn listing 4.13 we extend the HbnAbstractDao we introduced in chapter 1 by adding findermethods we can use to check for existing usernames and e-mails. We’ve suppressed theUserDao interface but its there.Listing 4.13 HbnUserDao.java with finders to support dupe checks package r4_3.dao; import org.hibernate.Query; import org.springframework.stereotype.Repository; import r4_3.model.User; @Repository("userDao") public class HbnUserDao extends HbnAbstractDao<User> implements UserDao { @SuppressWarnings("unchecked") public User findByUsername(String username) { Query q = getSession().createQuery("from User where username = ?"); q.setParameter(0, username); return (User) q.uniqueResult(); } @SuppressWarnings("unchecked") public User findByEmail(String email) { Query q = getSession().createQuery("from User where email = ?"); q.setParameter(0, email); return (User) q.uniqueResult();Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
27. } }To detect duplicate usernames and e-mails, its not sufficient to rely on the uniqueconstraints we set up for the username and email table columns. While Hibernate willthrow a ConstraintViolationException if we attempt to insert duplicates, we wouldn’teasily be able to tell which constraint was violated. ConstraintViolationExceptionprovides a getConstraintName() method, but it is unreliable across different RDBMSesand always returns null for the standard MySQL driver. Additionally, Hibernate would throwthe exception upon the first constraint violation that occurred, so if both the suppliedusername and e-mail address were duplicates, we’d only be able to report one at a time. Now lets create a user service around the user DAO.CREATE THE USER SERVICEWe are going to create a service with a method that contains the business logic we need toregister users. It will check for duplicate usernames and e-mail addresses and then persistUser objects to the database. In this service’s design, we assume that most validation ishandled externally. The exceptions are cases where validation is "costly;" we handle those inthe service bean. Recall from chapter 1 that we don’t need to explicitly flush and close our Hibernatesessions so long as they execute within the context of a transaction. Instead of specifyingtransaction boundaries at the DAO level, it makes more sense to do so at the service levelsince service methods often rely on multiple database operations. Listing 4.14 shows ourservice implementation (weve suppressed the UserService interface):Listing 4.14 UserServiceImpl.java, a service bean for registrations and more package r4_3.service; ... imports ... @Service("userService") @Transactional( propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = true) public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Transactional(readOnly = false) public void registerUserIfValid(User user, boolean userIsValid) throws DuplicateRegistrationException { boolean usernameTaken =Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
28. userDao.findByUsername(user.getUsername()) != null; #A boolean emailTaken = userDao.findByEmail(user.getEmail()) != null; #B if (usernameTaken || emailTaken) { throw new DuplicateRegistrationException( usernameTaken, emailTaken); #1 } if (userIsValid) { #2 userDao.save(user); } } }Cueballs in code and text #A Check whether username is taken #B Check for duplicate e-mail #1 Throw exception if either is taken #2 Save only if validation succeedsIn registerUserIfValid() we throw a DuplicateRegistrationException if wedetect either a duplicate username, e-mail address or both [#1]. Then only if our externalvalidation passed do we persist the User object to the database [#2]. You can download thecode for DuplicateRegistrationException from the books website. The fact that registerUserIfValid() relies on an external flag makes it sort of anodd bird. Developers using our API in different contexts, perhaps independently of SpringWeb MVC, wouldn’t necessarily understand the circumstances we faced when we designed itthe way we did. Therefore, if we were designing this API for public consumption, it wouldmake sense to Javadoc it well and add an alternative method, registerUser(), that savedUsers unconditionally. We’ll leave all that out for our purposes. Brother vs. brother: Validation in the business tier In recipe 4.2 we noted that while were doing our validation in the web tier, its also possible to perform validation in the business and data access tiers. (It is even routinely done in the persistence tier via database constraints.) We also said that validation in the business tier can simplify the business tier API. Lets consider that in the context of our UserService interface. We have the userIsValid flag and DuplicateRegistrationException because UserService is not itself validation-aware. The userIsValid flag essentially allows us to pass in contextual information that tells the service bean whether the registration request is "real," and the exception allows the service bean to signal validation errors that arent captured by BVF validation rules. (We could externalize the explicit dupe checks to allow the client to callPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
29. them directly before calling a simpler register() method, but its nice to keep the checks and registration in the same transaction without requiring extra work of the client.) John prefers to keep validation out of the business tier because he thinks we should ensure the data is clean before passing it to the service, and he doesnt think the service API should expose the Spring-specific Errors interface. Willie thinks that this situation is ideal for business tier validation, even if it means exposing Errors, since it eliminates the flag and exception, and it presents "lightweight" (BVF) and "heavyweight" (database-calling) rule violations uniformly to the client.INVOKE THE USER SERVICE FROM REGFORMCONTROLLERNow we are ready to wire UserService into our aptly-named registration form controller,RegFormController, and register users. Listing 4.15 shows how this we do this:Listing 4.15 RegFormController.java with persistence code package r4_3.web; ... imports ... @Controller @RequestMapping("/register/form") public class RegFormController { private static final String MA_USER = "user"; private Validator validator; private UserService userService; @Autowired public void setValidator(Validator validator) { this.validator = validator; } @Autowired public void setUserService(UserService userService) { this.userService = userService; } @RequestMapping(method = RequestMethod.GET) public void form(Model model) { Logger.global.info("Serving initial form"); model.addAttribute(MA_USER, new User()); } @RequestMapping(method = RequestMethod.POST) public String form( @ModelAttribute(MA_USER) User user, BindingResult result) { verifyBinding(result); validator.validate(user, result); #1 try {Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
30. userService.registerUserIfValid(user, !result.hasErrors()); #2 } catch (DuplicateRegistrationException dre) { if (dre.isUsernameTaken()) { result.rejectValue("username", "not.unique", new String[] { "Username" }, null); #3 } if (dre.isEmailTaken()) { result.rejectValue("email", "not.unique"); } } if (result.hasErrors()) { result.reject("form.problems"); return "register/form"; #4 } return "redirect:confirm"; #5 } ... initBinder() and verifyBinder() from recipe 4.2 ... }Cueballs in code and text #1 Validate with BeanValidator #2 Pass in external validation results #3 Signal a duplicate username #4 If invalid, redisplay form with errors #5 Otherwise redirect to confirmation pageAfter we validate users with BeanValidator [#1], we call registerUserIfValid() onour service while passing the flag indicating whether or not validation was successful [#2]. Ifa DuplicateRegistrationException is thrown during the service call, we directly adderror codes to the BindingResult [#3] then we either redisplay the form with errors [#4]or forward to our confirmation page [#5]. We handle the confirmation page with a separatecontroller that isnt shown here. We also need to add the not.unique error code to our errors.properties messagebundle: not.unique={0} has already been taken.APPLICATION CONTEXT CONFIGURATIONIn listing 4.16 we present spring-servlet.xml, which is our application context file. Wewont go into the details of the configuration here since this will to a large extent be arepetitive element throughout the book. Well show it here, however, since this is our firstrecipe using ORM persistence. For more information on the configuration please see part 1.Listing 4.16 spring-servlet.xml, our application contextPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
31. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context [CA]/spring-context-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <context:property-placeholder location="file:${user.home}/springbook.properties"/> <context:component-scan base-package="r4_3.dao"/> <context:component-scan base-package="r4_3.service"/> <context:component-scan base-package="r4_3.web"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${dataSource.driverClassName}" p:url="${dataSource.url}" p:username="${dataSource.username}" p:password="${dataSource.password}"/> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation. [CA]AnnotationSessionFactoryBean" p:dataSource-ref="dataSource"> <property name="annotatedClasses"> <list> <value>r4_3.model.User</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect. [CA]MySQL5InnoDBDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3. [CA]HibernateTransactionManager" p:sessionFactory-ref="sessionFactory"/>Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
32. <tx:annotation-driven/> ... internal resource view resolver (see recipe 4.2) ... ... configuration loader (see recipe 4.2) ... ... error code converter (see recipe 4.2) ... ... validator (see recipe 4.2) ... ... message source (see recipe 4.2) ... </beans>The configuration above uses Hibernate 3 and MySQL 5. If youre not using those, youllneed to consult a reference manual to wire it up with your ORM (assuming youre using one)and DBMS of choice.PROVIDE A LINK TO AN ACCOUNT RECOVERY PAGE WHEN DUPLICATE E-MAILS ARE DETECTEDLets display a link to an account recovery page if users submit a duplicate e-mail, as itprobably means they registered with us a long time ago and forgot about it. We can takeadvantage of the fine-grained validation message we set up during the validation section byadding the following line to errors.properties. not.unique.user.email=We have this e-mail on file. Have you lost your username or password?The link is just a placeholder, and Spring form tags form:errors won’t display it properlyunless we turn off HTML escaping for e-mail in form.jsp.
 <form:errors path="email" htmlEscape="false"/>
In figure 4.4 we see the end result:Figure 4.4 We allow users to recover their account information if they enter a duplicate e-mail address.With that, we have a fully-functional registration form. Congratulations! From an end userperspective, everything works as expected: he can register and (once logins are in place)hell be able to use the registration to log in.Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
33. Were not completely done yet, though. So far were transmitting and storing passwordsin the clear, and thats usually a bad idea for production applications. In chapter 6 wellcontinue with the security theme by showing how to handle passwords more securely. Thereare other security measures we might take as well, as well see in recipe 4.4.DiscussionIn this recipe, weve checked for duplicate usernames and e-mail addresses and saved userregistrations to a database. Sometimes, however, it is preferable to nix the username fieldaltogether in favor of using email and password as security credentials. People aregenerally more likely to forget their usernames than their e-mail addresses, especially if theuser was forced to choose a second-choice username because his usual was already taken. A downside of using email as an identifier is that doing so might violate a user’s privacy.What if someone who knew the e-mail address tried to use it to register with our website,just to see whether an account already exists? Wed have to report its unavailability. Inmany cases this disclosure would be unacceptable; examples include adult websites, creditrepair websites, or websites where there are legal reasons (FERPA, HIPAA, etc.) why suchinformation must be tightly held. In cases like that, you might want to stick with usernames,and you might even advise the user to avoid usernames that create privacy concerns.4.4 Use CAPTCHAs to prevent automated user account creationPREREQUISITES4.1 Display a registration form4.2 Validate user registrationsKEY TECHNOLOGIESSpring Web MVC, Spring Validation, reCAPTCHA, reCAPTCHA4jBackgroundIts well-understood that computers and people are good at solving different—and largelycomplementary—problems. While thats probably a statement with a shelf life, at the time ofthis writing (2008) Skynet4 appears to be at least four or five years away.5 It turns out thatwe can use this difference in capability to prevent automated agents, or "bots," fromperforming actions that we want only real people to do, such as filling out user registrationforms. Enter the "Completely Automated Public Turing test to tell Computers and HumansApart," or CAPTCHA. Here’s how it works. Suppose that we have a registration form and we want to ensurethat only real people complete the form. We add to the form a "problem"—or a CAPTCHA—4 http://en.wikipedia.org/wiki/Skynet_(Terminator)5 Dont laugh. Its already possible to use the Amazon Mechanical Turk to orchestrate armies of humancomponents to solve problems that computers cant directly solve themselves. While I dont necessarily expectMTurk to evolve into Skynet, its hard not to be impressed with how well computers are competing against thehuman race.Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
34. that all (or most) and only real human beings can easily solve, and we dont accept the formsubmission unless the problem is actually solved. That allows us to be sure that a realhuman being completed the form. The most common type of CAPTCHA asks the user to look at some visually distorted textand enter that text into a text field in the form. Youve probably run into those many timeson the web. In this recipe we’re going to look at an interesting, socially-conscious variant to thatapproach from Carnegie Mellon University called reCAPTCHA. ReCAPTCHA6 was conceived asa way to use CAPTCHAs to digitize books. When optical character recognition (OCR) systemsscan books, they often come across words that they cant read. ReCAPTCHA collects OCR-unrecognizable words and presents them to human beings as two-part CAPTCHAs: oneknown word and one OCR-unrecognizable word. The known word gives reCAPTCHA a way todetermine whether theres really a human on the other end since by definition the otherword cant be directly validated. To solve the CAPTCHA (which is the end users concern), thehuman only has to get the known word right. To solve the unknown word (which is CMUsconcern), enough humans have to agree on its proper translation. Of course, the user isnttold which word is the known word. And most users are blissfully unaware the distinctionbetween the known and unknown words anyway.ProblemYou have a user registration form, and you want to make sure that only real human beingscan use it to create accounts.SolutionWe are going to add a reCAPTCHA widget to our registration form. Figure 4.5 shows how itlooks:Figure 4.5 This is a reCAPTCHA widget. ReCAPTCHA allows you to load a new pair of words if you cantread the current pair, and it also provides audio CAPTCHAs for blind users.6 http://recaptcha.net/ Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
35. As you can see, the user interface is nice and polished. Its also possible to select differentthemes for the widget though we wont go into that here. We will continue to use Spring Web MVC here, along with the Spring form tag library.CREATE AN ACCOUNT AND KEY PAIRThe first step is to log into http://recaptcha.net/ and sign up for a reCAPTCHA account. Youllbe asked to specify the domain your reCAPTCHAs will service. After providing that, thereCAPTCHA website will provide you with a key pair (which they call a "reCAPTCHA key" eventhough its really a key pair) that you can use for requesting reCAPTCHA challenges andvalidating user responses. The key pair includes a public key you use to request the widget,and a private key you use when forwarding user responses to the reCAPTCHA server.7 Now lets look at how to add reCAPTCHA to a Spring application.PLACE A RECAPTCHAIMPL BEAN ON THE APPLICATION CONTEXTThe ReCaptchaImpl class, which comes from the reCAPTCHA4j client library, allows us torequest challenges from a remote reCAPTCHA server, and to check with the same whetherthe users response to the reCAPTCHA challenge was correct. We need to inject it with ourpublic key so we can request challenges from the reCAPTCHA server, and with our privatekey we can validate user responses. Because we might want to use ReCaptchaImpl inmultiple places (not just the registration form), and because we dont want to duplicate ourkeys (especially our private key) everywhere, were going to place a ReCaptchaImpl beanon the application context. <bean id="reCaptcha" class="net.tanesha.recaptcha.ReCaptchaImpl" p:publicKey="YOUR_PUBLIC_KEY" p:privateKey="YOUR_PRIVATE_KEY"/>ReCaptchaImpl is threadsafe by design, so its OK to use a shared single instance in thisfashion. As is obvious, replace YOUR_PUBLIC_KEY and YOUR_PRIVATE_KEY with the keysyou received when you created your reCAPTCHA account. Thats it for the Spring application context. Now lets go to the controller.UPDATE THE CONTROLLERWell need to modify the controller a little to make reCAPTCHA work. First well have to add asetter for the reCAPTCHA bean from reCAPTCHA4j to support dependency injection. I wonteven show the code here; Ill just recommend that you follow good API design practice andcode the setter to the ReCaptcha interface rather than to the ReCaptchaImplimplementation. Next lets update the form-serving method. We show the reCAPTCHA widget byembedding some boilerplate HTML and JavaScript into our web form. The only non-7 From the reCAPTCHA website: "This key pair helps to prevent an attack where somebody hosts a reCAPTCHA ontheir website, collects answers from their visitors and submits the answers to your site." An attacker would needyour private key to check responses for a reCAPTCHA generated for your public key.Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
36. boilerplate pieces would be the public key you use to identify your reCAPTCHA account andany customization options you want to include. Conveniently, we can use the reCAPTCHAbean to generate the HTML and JavaScript for us. We make both the user account and thereCAPTCHA HTML available to the form JSP by placing them on the model: private static final String MA_USER = "user"; private static final String MA_RECAPTCHA_HTML = "reCaptchaHtml"; ... @RequestMapping(method = RequestMethod.GET) public void form(Model model) { model.addAttribute(MA_USER, new User()); String html = reCaptcha.createRecaptchaHtml(null, null); model.addAttribute(MA_RECAPTCHA_HTML, html); } Though you cant see it from the Java code (you can see it if you view the HTML pagesource though), the reCAPTCHA bean generates HTML and JavaScript to pull a reCAPTCHAwidget down from the reCAPTCHA servers using your public key. We just put thatHTML/JavaScript on the model so the JSP can incorporate it. The first argument tocreateRecaptchaHtml() allows us to indicate whether a validation error happened (theanswer is no when were first serving the form, so we pass in null). The second argumentallows us to specify some properties to customize the widget, but we arent doing that here.Consult the reCAPTCHA Javadocs for more information. Third, update the initBinder() method to allow parameters namedrecaptcha_challenge_field and recaptcha_response_field. Were going to bindthe corresponding incoming data not to the user model but to some request parameters withthose names. The fourth and final controller modification is to update the form-processing method. Thisones actually fairly interesting so lets take a good look. The reCAPTCHA widget is itself able to display CAPTCHA validation errors when theyoccur, so first, listing 4.17 shows how to perform form validation (the whole form, includingthe CAPTCHA) and display CAPTCHA validation errors in the widget itself:Listing 4.17 The first version of our reCAPTCHA validation code @RequestMapping(method = RequestMethod.POST) public String form( HttpServletRequest req, @RequestParam("recaptcha_challenge_field") String challenge, #1 @RequestParam("recaptcha_response_field") String response, #2 @ModelAttribute(MA_USER) User user, BindingResult result, Model model) { verifyBinding(result);Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
37. validator.validate(user, result); #3 ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(req.getRemoteAddr(), challenge, response); #4 if (result.hasErrors() || !reCaptchaResponse.isValid()) { String errMsg = reCaptchaResponse.getErrorMessage(); #5 String html = reCaptcha.createRecaptchaHtml(errMsg, null); #6 model.addAttribute(MA_RECAPTCHA_HTML, html); result.reject("form.problems"); return "register/form"; } ... save user ... return "redirect:confirm"; }Cueballs in code and text #1 Code representing challenge delivered to user #2 Users response to challenge #3 Validate non-CAPTCHA form data #4 Validate CAPTCHA response #5 Get error message, if any #6 Generate widget HTML/scriptThe method accepts, among other things, a couple of reCAPTCHA-specific parameters:recaptcha_challenge_field [#1] and recaptcha_response_field [#2]. Thewidget sends values for these, and we use them to validate the users response. The code begins with a call to validate() [#3] to perform a general form validation.This validates everything except the CAPTCHA itself. The next piece uses the reCAPTCHAbean to submit the users response to the reCAPTCHA servers [#4]. Recall that thereCAPTCHA bean knows the sites private key, and it submits that as part of the CAPTCHAvalidation call. If either the account data or else the CAPTCHA is invalid, we grab an error code from theresponse (its really more code-like than message-like, despite the namegetErrorMessage()) [#5] and pass it back to the reCAPTCHA bean when we generate theHTML and JavaScript we use for getting the widget [#6]. That way the widget knows whaterror message to display. Otherwise we save the user account and redirect to a confirmation page using theredirect-after-post pattern to prevent double submissions. The approach just described works, but theres a usability issue to deal with. ThereCAPTCHA error message is small, embedded in the widget, and just doesnt look like theerror messages for the other fields. Its easy to miss, and its inconsistent. USABILITY TIPPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
38. Jakob Nielsen, a well-known usability expert, notes that being consistent is a general principle of usable user interface design. Of consistency and standards he says: "Users should not have to wonder whether different words, situations, or actions mean the same thing. Follow platform conventions."8To improve the usability of the form, lets make the error message for the CAPTCHA fieldlook like the other ones. Heres listing 4.18:Listing 4.18 The second and improved version of our reCAPTCHA validation code @RequestMapping(method = RequestMethod.POST) public String form( HttpServletRequest req, @RequestParam("recaptcha_challenge_field") String challenge, @RequestParam("recaptcha_response_field") String response, @ModelAttribute(MA_USER) User user, BindingResult result, Model model) { verifyBinding(result); validator.validate(user, result); ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(req.getRemoteAddr(), challenge, response); if (!reCaptchaResponse.isValid()) { result.rejectValue("captcha", "errors.badCaptcha"); #1 } String html = reCaptcha.createRecaptchaHtml(null, null); #2 model.addAttribute(MA_RECAPTCHA_HTML, html); if (result.hasErrors()) { result.reject("form.problems"); return "register/form"; } return "redirect:confirm"; }Cueballs in code and text #1 Flag captcha property as having error #2 Generate widget HTML/script, no errorFrom a Spring perspective this code is noteworthy because it shows how to combineValidator-based validation with manual validation (in this case, manual reCAPTCHAvalidation). Here, instead of displaying an error message through the reCAPTCHA, we call8 http://www.useit.com/papers/heuristic/heuristic_list.html Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
39. binding.rejectValue(), passing in both the name of the offending property and theerror code [#1]. Then we generate the reCAPTCHA HTML, but we pass in null for the firstargument [#2] since we dont want the widget itself to display an error message; theregistration form itself will do that. You might have noticed that we dont actually have a property called captcha; well turnto that issue right now.ADD A DUMMY GETTER TO THE FORM BEANTo display error messages for a given property, there must be an associated getter methodin the model. Hence we just add a dummy getCaptcha() method to User: public String getCaptcha() { return null; }This is of course nothing more than a hack to make it work, but its probably the moststraightforward way to display the error message in HTML.UPDATE YOUR MESSAGE RESOURCE BUNDLETo define an error message to display, open your errors.properties file and add a singleline: errors.badCaptcha=Please try again. Hover over the red buttons for [CA]additional options.Were almost there. Now all we need to do is update the JSP and were set.UPDATE YOUR REGISTRATION FORMJust add the reCAPTCHA widget and the error message to your JSP: <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> ...

Please prove youre a person:

${reCaptchaHtml}

<form:errors path="captcha"/>

Were using the Spring form tag library to display the error message. USABILITY TIP Many users wont have any idea why theyre being asked to respond to a CAPTCHA, and the widget doesnt itself make it obvious whats going on. It is helpful to include a short explanation, such as "Please prove youre a real person" as weve done above.FIRE IT UPPoint your browser at the form and try it out. You should see your reCAPTCHA widget. Trysubmitting a blank form. You should see error messages for your form fields, including anPlease post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503
40. error message for the reCAPTCHA widget rendered in the same style as your other errormessages. You might view the page source to see what it is that the reCAPTCHA beanactually generates, in terms of HTML and JavaScript. TIP Note that even though reCAPTCHA normally expects your reCAPTCHA requests to originate from the domain you specified when creating your account, it wont complain if your requests come from localhost or 127.0.0.1. (If however somebody tries to request a reCAPTCHA widget using your public key from some alien domain, the reCAPTCHA service will not respond with the widget.)Good job! Score: human race 1, Skynet 0.DiscussionCAPTCHAs arent of course inherently tied to registration forms. They are useful any timeyou want to keep bots from submitting web forms. Examples beyond registration formswould include "contact us" forms, anonymous discussion forum postings, user comments,product reviews and so forth. From a usability perspective, reCAPTCHA is something of a mixed bag. For end users,completing CAPTCHAs is a necessary evil; they dont derive any direct benefit from it. So thefact that reCAPTCHA requires that the user translate two words instead of just one meansthat weve doubled the nuisance factor. On the other hand, as noted above, reCAPTCHA doesallow users to request a new challenge if the existing challenge is too difficult, and it doessupport accessibility by allowing audio CAPTCHAs as an alternate. While reCAPTCHA is one of the nicer CAPTCHA solutions available (and arguably the onewith most important social impact), it isnt the only one out there. You might look atJCaptcha as well, which like reCAPTCHA integrates with Spring:  http://jcaptcha.sourceforge.net/SummaryAt the beginning of the chapter we claimed that registration isnt just a matter of collectingform data and saving it. We hope you can see what we mean. Weve highlighted functional,usability, security, legal and engineering concerns that registration forms can address eithermore or less successfully, and weve shown how to use Spring and other tools to tackle thoseissues effectively. At the end of the day, we want forms that are easy to use and that protectthe private data that they capture, and Spring certainly provides a nice framework foraccomplishing those ends. In the next chapter well turn our attention to registrations partner in crime, which wouldbe authentication. As you might expect, Spring Security will play an even more prominentrole in that discussion.Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=503

type: global

value: This website is an American hosting service, now owned by Scribd, for professional content including presentations, infographics, documents, and videos. Users can upload files privately or publicly in PowerPoint, Word, PDF, or OpenDocument format.


text:
Amazon.com: Programas Wifi
"Programas Wifi"
EasyN FS-613A-M136 Wireless WiFi Pan/Tilt IP Camera Two-Way Audio, Email FTP Motion Alert, Remote Mobile View, DDNS, UPNP, 64 Channel Software, Windows & Mac Compatible by EasyN USA
Camaras IP, Como Vigilar Tu Casa y Tu Negocio por Internet (Spanish Edition) by Javier LOPEZ GOMEZ, Alfaomega Grupo Editor (MX) and http://www.alfaomega.com.mx/af/images/libros/5038_1?1229104392 (Paperback - Dec. 1, 2008)
Seguridad en Wifi / Wifi Security (Spanish Edition) by Bens Smith (Paperback - July 30, 2006)
Pharos Traveler GPS525E 2.3-Inch Bluetooth Portable GPS Navigator by Pharos
Huawei E173 Unlocked HSDPA 7.2Mbps GSM 3G USB Modem by Huawei E173
Kocaso M752 7" Android 4.0 All Winner A13 Cortex A8 1.2GHz 4GB 512MB Dual Camera Capacitive Multi-Touch Tablet PC (Black) by Kocaso
Buy new: $109.00 $72.01

value: This website is an American multinational technology company which focuses on e-commerce, cloud computing, digital streaming, and artificial intelligence.