Académique Documents
Professionnel Documents
Culture Documents
Faculty of Computer Science Supervisor: Prof. Dr. Oliver Braun Assessor: Prof. Dr. Dietmar Beyer Author: Marcus Denison Matr.-Nr. 280362 Brckenauerstr. 21 97772 Wildecken Schmalkalden, 09-01-2011
Abstract This thesis deals with the implementation of EmployeeWeb, a web application which can be integrated into the spirit@fhs ecosystem. The key task of EmployeeWeb is to act as the frontend for all employees in order to create/update news or events which concern the students at the faculty of computer science. Based on the ideas from spirit-news, EmployeeWeb was designed from scratch to have a cleaner code base. EmployeeWeb received a more modular User management layer, a persistence layer based on the Active Record Pattern and the option of being upgraded very easily. The prototype was developed using the Lift webframework, a secure and scalable framework using the Scala programming language.
Acknowledgements Many among my fellow students, professors that have taught me my knowledge, the Lift Community, my supervisor during my internship and at last but not least my parents have greatly deserved to be honorably mentioned.
Contents
1 Introduction 2 Goals 3 Background 3.1 Scala: Functional and Object-oriented programming 3.1.1 Functional Scala . . . . . . . . . . . . . . . 3.1.2 Object-oriented Scala . . . . . . . . . . . . . 3.2 Lift: A web framework implemented with Scala . . 3.2.1 A brief history . . . . . . . . . . . . . . . . 3.2.2 Design Goals . . . . . . . . . . . . . . . . . 3.2.3 Goodbye MVC, Hello V-VM-M . . . . . . . 3.2.4 Lifts answers to OWASP Top 10 . . . . . . 4 Analysis of the current implementation 4.1 User Management . . . . . . . . . . . 4.2 Persistence Layer . . . . . . . . . . . 4.3 Security vulnerabilities . . . . . . . . 4.3.1 Session Stealing . . . . . . . . 4.3.2 Cross Site Scripting . . . . . . 4.3.3 SQL Injection . . . . . . . . . 4.4 Design failures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 3 3 3 4 5 5 5 6 7 9 9 12 13 14 14 16 16 19 19 21 23 24 26 26 28 28 30 31 32 37
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
5 A new implementation from scratch 5.1 Authentication Module . . . . . . . . . . . . . . . 5.2 SpiritRecord based on the Active Record Pattern 5.3 A cleaner design . . . . . . . . . . . . . . . . . . . 5.4 DRY - Dont repeat yourself . . . . . . . . . . . . 6 Integration into the spirit@fhs ecosystem 6.1 SPIRIT . . . . . . . . . . . . . . . . . . 6.2 StudWeb . . . . . . . . . . . . . . . . . . 6.3 RESTful DB-Service . . . . . . . . . . . 6.4 Merging with PlanningWeb . . . . . . . 7 Conclusion and Future work Bibliography Statutory declaration
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
Marcus Denison
IV
1 Introduction
Innocent Code - A Security Wake-Up Call for Web Programmers is the title of a book by Sverre H. Huseby [Hus03]. It addresses the needs of developing secure web applications. Sverre H. Huseby sets up 27 best practices, how one can evolve to a better web programmer. Web application security does not start with a rewall nor with encryption, rst of all it is more the developer which has to be sensitised in writing more reliable and secure code. It is important that the developer understands the complete chain between data input on the client side and data processing on the server side. The Web Application Security Consortium released the Web Application Security Statistic Project in 20081 , which revealed data about over 12,000 web applications with more than 97,000 detected vulnerabilities of dierent risks. Around 13 percent of the tested web applications were vulnerable to be compromised completely automatically. Half of the tested web applications contained high risk level vulnerabilities. Cross Site Scripting was the most found security issue with overall 39 percent, this problem problem is based in the code of the web applications. In addition there were around 41.000 vulnerabilities found on administrative side. The Lift web framework praises itself to be a secure web framework, which will be illustrated in chapter 3. The objectives of this thesis is it to analyse spirit-news, a web application which was implemented with Lift and a novice developer, as well as re-implement this web application with a developer who had a deeper look into the Lift libraries and integrate the new implementation into the spirit@fhs ecosystem.
http://projects.webappsec.org/w/page/13246989/Web-Application-SecurityStatistics
Marcus Denison
Page 1 of 37
2 Goals
Primary goal is it to get a better understanding of the Lift libraries and the creation of a cleaner design which can be adopted for new features within the project. It is also necessary to take a closer look at the security features which are integrated into the web framework. The following Steps which will be taken throughout this thesis: Analysing the implementation of spirit-news and which false decisions were made, due to lack of experience. Taking a short glance at the security, since it was not taken into consideration when spirit-news was implemented. Taking spirit-news apart, create modules and use more of Lift internal libraries for implementing features. Evaluate the new design, whether it is ecient enough to be used any further in this project. Integrating the new implementation into the spirit@fhs ecosystem and which possible failures for the design it might bring. In each chapter one or more of these steps will be evaluated. The output will be a sample web application as a prototype, which is not meant to be fully functional but will be released as an open source project, so anyone could work on this to make it really work.
Marcus Denison
Page 2 of 37
3 Background
"Modern Applications Demand Modern Tools" was stated on the greylockpartners blog1 when theyve invested $3 million Dollars into the new founded company TypeSafe2 by Martin Odersky3 . Preparing for a new era, it is important to take a look at modern programming languages and their frameworks. A quick introduction into the Scala4 Programming Language and an overview of the Lift5 web framework is going to be part of this chapter. In this thesis Scala 2.8.1 and Lift 2.3 are outlined.
Marcus Denison
Page 3 of 37
Marcus Denison
Functions Functions are rst-class citizens in functional programming. It is possible to pass functions as parameters to other functions, return functions from functions or nest functions into functions. Functions that take functions as parameters are so called higher-order functions. [Sub09, P. 75 f.] Currying Transforming a function that takes more than one parameter into a function that takes multiple parameter lists, is called Currying, named after Haskell Brooks Curry7 , whose rst name is also the name of the pure functional programming language Haskell8 .
7 8
http://www-history.mcs.st-and.ac.uk/history/Biographies/Curry.html http://www.haskell.org
Page 4 of 37
3. Background
Marcus Denison
Page 5 of 37
3. Background
Marcus Denison
Figure 3.1: View-ViewModel-Model An explanation what Figure 3.1, taken from Lift in Action [Per10, P. 4], means. View There are two approaches which are valid for Lifts View templates. Validated XHTML templates are the rst and the more important one, secondly, embedded XML within Scala code which is generated into a valid View. Lift forces the developer to write correct XML markup. It is not possible to put any logic within a XHTML template. ViewModel The middle piece of this pattern, also called snippet. A Scala class or object may represent a snippet, which are responsible for rendering valid HTML output. Snippets are not controllers, as known from the MVC pattern. Snippets should only be responsible for non-control ow actions. Views can call any amount of snippets. According to David Pollak, snippets are the reason why developers have to work hard to introduce cross site scripting vulnerability [Pol11, Ch. 3.4]. Model The third part is responsible for taking calls from and returning data to the ViewModel. Data from the persistence and return values from actions can be a part of this.
19
View-ViewModel-Model
Page 6 of 37
3. Background
Marcus Denison
Table 3.1: Lift vs. OWASP Top 10 Web application vulnerability Lifts answer A1 - Cross Site Scripting (XSS) "Lift is resistant to XSS attacks. By default pages are composed in XML rather than Strings. It takes the developer extra work to insert XSS strings into output rather than having to make sure each String is properly escaped before being cated to the output." A2 - Injection Flaws "Lift is resistant to SQL Injection attacks because mapper and JPA do not compose Strings into SQL statements, but rather bind well typed parameters into prepared statements. So, if you go the normal path, you get SQL injection resistance. If you want to manually craft a String to send as a query, in mapper you have to sign the string with the time, date and a certication that youve reviewed the String for SQL Injection problems." "Lift never shells out. You cant cause a le to be executed from a Lift app unless your app manually uses Javas Runtime.execute() call." "By default, Lift creates opaque GUIDs to refer to components on the server side (whether thats a function to execute when a form eld is submitted, what to do on an Ajax call, etc.) By default, its easier to use this callback mechanism than advertise a primary key or other sensitive piece of information. Lift also has the KeyObfuscator which will create a session-specic mapping of primary keys to opaque ids. Using KeyObfuscator, you can send JSON objects to the client with stable primary keys that are obfuscated and not usable outside the current session."
20
Page 7 of 37
3. Background
Marcus Denison
Table 3.1: (continued) A5 - Cross Site Forgery (CSRF) Request "By default Lifts form elds contain GUIDs that are cryptographically impossible to predict. Its not possible to do CSRF because one does not know the name of form elds (they are not stable)."
A6 - Information Leakage and "Lift has dierent production vs. development Improper Error Handling mode error messages. Theres little information that leaks about underlying congurations, even exceptions, in production mode." A7 - Broken Authentication and Session Management "Lift uses the containers session management (usually JSESSIONID) for session management. Of course, anything thats not over SSL is vulnerable to a cookie stealing attack."
A8 - Insecure Cryptographic "Crypto key storage is a container-level issue." Storage A9 - Insecure Communications "See 7"
A10 - Failure to Restrict URL "Lifts sitemap is the best and most secure inteAccess gration of UI and page-level access. You can look at the sitemap to determine the access control rules for a given page (its declarative) and its enforced long before your page gets accessed." This chapter was an introduction into the Lift web framework, for further understandings please see Simply Lift [Pol11], Lift in Action [Per11], or Exploring Lift [DCBW11].
Page 8 of 37
1 2
https://github.com/spirit-fhs/news University of Applied Sciences Schmalkalden 3 Lightweight Directory Access Protocol 4 LDAP Server across all faculties 5 LDAP Server only for the Faculty of Computer Science 6 https://github.com/spirit-fhs/news/blob/master/src/main/scala/org/unsane/ spirit/news/model/LDAPAuth.scala 7 Username based on the membership at the FhS
Marcus Denison
Page 9 of 37
Marcus Denison
def tryLogin ( userName : String , passWord : String ) : Boolean = { // allow additional users in setting . properties val additionalUsers = loadProps ( " users " ) . split ( ; ) . map { _ . trim } if ( additionalUsers contains userName ) { val userInfo = loadProps ( userName ) . split ( ; ) . map { _ . trim } if ( userInfo . length >= 3) { if ( userInfo (2) = = md5SumString ( passWord ) ) { S . setSessionAttribute ( " fullname " , userInfo (0) ) S . setSessionAttribute ( " email " , userInfo (1) ) true }}} if ( useLDAPAuth ) { tryLoginLDAP ( userName , passWord ) } else { S . setSessionAttribute ( " fullname " , userName ) S . setSessionAttribute ( " email " , " testuser @ nonvalid " ) true } } def tryLoginLDAP ( userName : String , passWord : String , ldapServer : String = " ldap1 " ) : Boolean = { val ( ldapURL , dn ) = if ( ldapServer = = " ldap1 " ) { ( " ldaps : // ldap1 . fh - schmalkalden . de : 636 " ," uid = " + userName + " ," + ( if ( userName . equals ( " denison " ) ) " ou = students , dc = fh - sm , dc = de " else " ou = people , dc = fh - sm , dc = de " ) ) } else if ( ldapServer = = " zefi " ) { ( " ldaps : // zefi . fh - schmalkalden . de : 636 " ," uid = " + userName + " , ou = people , ou = in , dc = fh - schmalkalden , dc = de " ) } else { false }}
Page 10 of 37
Marcus Denison
Reviewing a part of the User object8 in Listing 4.2, demonstrates how LDAP authentication is integrated into the User life cycle within the project. In detail: The LDAPAuth trait is mixed in via with LDAPAuth The values sitemap, loginXhtml and login are overridden in order to receive proper output for the user which is viewing the login page. Within the denition of login, the tryLogin method is called and if successful the user name is logged in and a valid session is opened for the users browser. Listing 4.2: User Object object User extends User with MetaMegaProtoUser [ User ] with LDAPAuth with Config { ... override lazy val sitemap : List [ Menu ] = List ( loginMenuLoc , logoutMenuLoc ) . flatten ( a = > a ) override def loginXhtml = { ... <tr > < td style = " border : 0; colspan : 2 " > { S .??( " log . in " ) } </ td > </ tr > <tr > < td style = " border : 0 " > { S .??( " FHS - ID " ) } </ td > < td style = " border : 0 " > < user : user / > </ td > </ tr > <tr > < td style = " border : 0 " > { S .??( " password " ) } </ td > < td style = " border : 0 " > < user : password / > </ td > </ tr > <tr > < td style = " border : 0 " > < user : submit / > </ td > </ tr > ...} override def login = { if ( S . post _ ?) { ... if ( tryLogin ( S . param ( " username " ) . open _ ! , S . param ( " password " ) . open _ !) ) { User . logUserIdIn ( S . param ( " username " ) . open _ !) ... } else { } } ... }} A comparison between Figure 4.1 and 4.2 views the dierences without and with the necessary modications for employee authentication.
8
https://github.com/spirit-fhs/news/blob/master/src/main/scala/org/unsane/ spirit/news/model/User.scala
Page 11 of 37
Marcus Denison
Page 12 of 37
Marcus Denison
Figure 4.3: Entry Record Listing 4.3: Record Usage def viewUserEntries ( xhtml : NodeSeq ) : NodeSeq = { Entry . findAll ( " name " -> User . currentUserId . open _ !. toString ) . sortWith ( ( entry1 , entry2 ) = > ( entry1 > entry2 ) ) . flatMap ( v = > <tr > < td style = " border : 0 " >{ v . writer . value . toString } </ td > ... < td style = " border : 0 " >{ link ( " / edit / delete " , () = > CurrentEntry ( Full ( v ) ) , Text ( " Delete " ) ) } </ td > </ tr > ) }
Figure 4.4: Entries by a User As mentioned in the previous chapter user management was not part of the required persistence. User management was retrieved from the internal LDAP servers.
Page 13 of 37
Marcus Denison
three common vulnerabilities (Cross Site Scripting11 , Session Stealing12 and Injection13 ) and reviewing why they are or arent potential risks to spirit-news.
Page 14 of 37
Marcus Denison
Figure 4.6: XSS Input mentation for the text area which the user uses for inputting data, which takes the input and stores it into the database without checking for any malicious code. Listing 4.4: Textarea code def view ( xhtml : NodeSeq ) : NodeSeq = { bind ( " CRUDView " , xhtml , ... " textarea " -> textarea ( CrudEntry . news . value . toString , CrudEntry . news . set ( _ ) , " rows " -> " 12 " , " cols " -> " 80 " , " style " -> " width : 100% " , " id " -> " entry " ) , ...) }
Page 15 of 37
Marcus Denison
Listing 4.5 is the function which renders the inputted data from the database to the browser. It doesnt check for malicious code either. The Textile-Parser15 just indicates that a markup language may be used for output. On the other hand, Figure 4.7 views the data just as it was inputted. Lift escapes everything by default, so it is hard for the developer to introduce XSS vulnerabilities, as stated by David Pollak [Pol11, Ch. 3.4]. Listing 4.5: Textarea output code def view ( xhtml : NodeSeq ) : NodeSeq = { ... " news " -> TextileParser . toHtml ( entry . news . value . toString ) ) ) ...}
A HTML Markup language. http://www.mongodb.org/display/DOCS/Do+I+Have+to+Worry+About+SQL+Injection 17 See Chapter 4 for the three points of authentication and two LDAP servers.
Page 16 of 37
4. Analysis of the current implementation to understand the whole code base to adopt a new mechanism.
Marcus Denison
Reviewing Figure 4.3 every eld of an Entry was implemented as a StringField, that means the attributes semester, date, lifecycle and nr could not be obvious to other developers. Creating new features using the Entry record for spirit-news could cause tremendous problems for a developer, since type-safety18 is not given for those attributes at any point. The same occurs with the attribute nr which is used as a sort of primary key, while the primary key should be handled by the database and not by business logic within the program code. Reviewing Listing 4.6 and 4.7 which are parts of the snippet that creates the view for inputting news, both methods are controlling the usage of the nr attribute. Recalling that this attribute is used as the primary key for entries and should be handled by the persistence layer and not by the snippets which are actually only used by rendering output to the users browser. Another part is that both methods make usage of the possibility to send the created entry as an email or tweeting19 it on twitter20 . Listing 4.6: Update method def update () { val oldNr = CrudEntry . nr . value val newNr = if ( tweetUpdate ) if ( EntryCounter . findAll . isEmpty ) " 1 " else EntryCounter . findAll . head . counter . toString else oldNr ... if ( newNr ! = oldNr ) { val count = if ( EntryCounter . findAll . isEmpty ) EntryCounter . createRecord else EntryCounter . findAll . head count . counter . set ( ( newNr . toInt + 1) . toString ) count . save } if ( sendEmail ) MailHandler . send ( TextileParser . toHtml ( CrudEntry . news . value ) . toString , " [ Update ] " + CrudEntry . subject . value , loadEmails ( changedSemester split ( " " ) ) ) if ( tweet && tweetUpdate )
18 19
Giving assurance that objects are always compatible with each other. Posting on twitter.com is called tweeting. 20 http://www.twitter.com
Page 17 of 37
Marcus Denison
Spreader ! Tweet ( " [ Update ] " + CrudEntry . subject . value , changedSemester . split ( " " ) . map ( " # " + _ ) . mkString , newNr ) } Listing 4.7: Create method def create () { lazy val nr = if ( EntryCounter . findAll . isEmpty ) " 1 " else EntryCounter . findAll . head . counter . toString ... val count = if ( EntryCounter . findAll . isEmpty ) EntryCounter . createRecord else EntryCounter . findAll . head count . counter . set ( ( nr . toInt + 1) . toString ) count . save if ( sendEmail && changedSemester . nonEmpty ) { MailHandler . send ( TextileParser . toHtml ( CrudEntry . news . value . toString ) . toString , CrudEntry . subject . value , loadEmails ( changedSemester . split ( " " ) ) ) } if ( tweet ) { Spreader ! Tweet ( CrudEntry . subject . value , changedSemester . split ( " " ) . map ( " # " + _ ) . mkString , nr ) } } The security issue regarding session stealing, was known prior to Lift version 2.2 and was xed during the development of the 2.2 release21 . But other than relying on the framework in all terms, it was also a failure in the server side conguration. Putting it all together, spirit-news was implemented without any knowledge on persistence layers, security nor where to properly put business logic within the code base. It is necessary to re-think the implementation of the user management, redesign the persistence UML and clearly put business logic where it belongs.
21
https://www.assembla.com/spaces/liftweb/tickets/727-create-new-http-sessionon-login
Page 18 of 37
1 2
https://www.assembla.com/spaces/liftweb/wiki/Modules https://github.com/mdenison/FhS-LDAP-Module
Marcus Denison
Page 19 of 37
Marcus Denison
Page 20 of 37
Marcus Denison
Figure 5.3: Re-factored Entry Record Figure 5.4 explains the path of creating an instance of a type which has inherited from the SpiritRecord. Listing 5.2 shows an example which denes methods for a SpiritRecord, pattern matching [OSV10] against which database as back end shall be used and for what kind of SpiritRecord the methods are needed. Reviewing the SpiritMetaRecord trait in Figure 5.4, it is clear that the MethodFactory is given the parameter this, thus the MethodFactory returns the appropriate object of methods for the type which was created, in the example case for an SpiritEntry.
Listing 5.2: Method factory object MethodFactory { def apply [ T <: SpiritRecord [ T ]]( in : T ) : SpiritMethods [ T ] = ( db , in ) match { case ( this . rest , in : SpiritEntry ) = > new persistence . rest . SpiritEntryMethods [ T ] case ( this . h2db , in : SpiritEntry ) = > new persistence . h2 . SpiritEntryMethods [ T ]
3
Page 21 of 37
Marcus Denison
lazy val db = Props . get ( " spirit . admin . record . backentry " ) . openOr (( " " )) lazy val h2db = " h2db " // Usage for H2 Database lazy val rest = " rest " // Usage for RESTful DB Service } Every SpiritRecord, which is created needs to implement the methods dened in the SpiritMethods trait4 in order to work awlessly, therefore the verbosity may increase to an tremendously unreadable code chaos. That is the reason why the MethodFactory was implemented. Once a SpiritRecord is implemented and a decision for a dierent database may come up, that specic SpiritRecord does not have to be changed, merely the classes which are instanced by the MethodFactory have to be adjusted. This chapter described the implementation of SpiritRecord, which
Figure 5.4: SpiritRecord UML allows the code to be cleaner than it was within spirit-news. The next chapter is going to explain, how the SpiritRecord helps having a cleaner design.
Page 22 of 37
Marcus Denison
Page 23 of 37
5. A new implementation from scratch " name = tooltip " #> createTextileTooltip }
Marcus Denison
Listing 5.4: Validating that the subject is never empty object subject extends StringField ( this , 100) with LifecycleCallbacks { override def beforeSave () { if ( this . value . isEmpty ) { this . set ( news . value ./ : (( " " , 20) ) { ( output , input ) = > if ( output . _ 2 = = 0) output else ( output . _ 1 + input , output . _ 2 - 1) }. _ 1 + " ... " ) } } }
Page 24 of 37
Marcus Denison
def confirmdelete ( in : NodeSeq ) = { ( " name = yes " # > (( b : NodeSeq ) = > ajaxButton (b , () = > { CurrentSpiritRecord . open _ !. delete _ ! Unblock & RedirectTo ( reloadAfterDelete ) }) ) & " name = no " # > (( b : NodeSeq ) = > < button onclick = { Unblock . toJsCmd } >{ b } </ button >) ) ( in ) } } This is an example of the DRY principle, since it can be used by any SpiritRecord without modication and if another style of dialog is needed it is only to be changed within the blockUI trait and nowhere else.
Page 25 of 37
6.1 SPIRIT
Figure 6.1 is a basic structure of most projects worked on at the present moment and how they communicate. Data - Is a RESTful DB-Service which provides the persistence for the complete ecosystem. StudWeb - The front end for Students, where it is possible to read news, submit comments and dene their schedule for the current semester. Mobile - Mobile applications which can be used to interact with the complete ecosystem, based on Android, Windows Mobile and the iPhone platform. Migrate - Dening an interface between the old schedule and the sub-project data is the goal of the Migrate project. LibSpirit - Providing access to the RESTful DB-Service through a C Library, which can be used in class to create small pieces of software by students in order to achieve a greater learning eect. EmployeeWeb & PlanningWeb - Both projects shall interact as the front end for employees, EmployeeWeb is part of this thesis and PlanningWeb provides support for time scheduling. For a more complete and comprehensible list of projects and a more detailed explanation, please see the spirit@fhs projects website2 .
1
The project name came up on a Wednesday afternoon when Oliver Braun and the Author were brainstorming. 2 http://pads.fh-schmalkalden.de/spirit.html
Marcus Denison
Page 26 of 37
Marcus Denison
Page 27 of 37
Marcus Denison
6.2 StudWeb
After introducing the spirit@fhs ecosystem, the communication between two projects which are more important to EmployeeWeb are to be reviewed, one of them is StudWeb. All communication between StudWeb and EmployeeWeb is happening through the DB-Service. Basically an agreement had to be found which denes the data, whichever needs to be transferred between the two projects. The second agreement was for a markup-language, the textile markup language3 was chosen, since the Lift web framework has superior support with a textile plug in.
http://textile.thresholdstate.com/ JavaScript Object Notation. 5 Even if the library is a part of the Lift web framework, it may be used by any Scala project without having dependencies on Lift.
Page 28 of 37
6. Integration into the spirit@fhs ecosystem val rawJson = h ( req <: < asJson as _ str ) val newsList = for { i <- ( parse ( rawJson ) \ " news " ) . children } yield i . extract [ news ]
Marcus Denison
newsList map { nl = > val newSE = SpiritEntry . createRecord newSE . id . set ( nl . news _ id ) newSE . subject . set ( nl . title ) newSE . news . set ( nl . content ) newSE . displayName . set ( nl . owner . displayedName ) newSE . crdate . set ( nl . creationDate ) newSE . semester . set ( nl . degreeClass . map ( _ . title ) ) newSE . asInstanceOf [ T ] } } case class news ( news _ id : Int , title : String , content : String , owner : owner , creationDate : String , degreeClass : List [ degreeClass ]) Listing 6.2 is a rudimentary implementation of the save(inst: T) method of the SpiritEntry. Which uses the :-* method, dened in the SpiritEntry, to get a valid JSON string from a created SpiritRecord in order to send it to the RESTful DBService. Listing 6.2: Saving data to the RESTful DB-Service def save ( inst : T ) : Boolean = { val in = inst . asInstanceOf [ SpiritEntry ] val asJson = Map ( " Accept " -> " application / json " , " Content - Type " -> " application / json " ) . toMap val req = new Request ( restURL + " news " ) <<< in . : -* val answer = h ( req <: < asJson as _ str ) true }
Page 29 of 37
Marcus Denison
the comparison, the only dierence is the persistence layer. It would be necessary to evaluate the behaviour of the Lift web framework when dening more than one persistence layer within the bootstrap. Chapter 6 described the easiness of integration into the spirit@fhs ecosystem, thanks to the thoughtful integration of the Active Record Pattern which was evaluated in chapter 5. Merging PlanningWeb with EmployeeWeb into one project was not achieved. In chapter 7 next steps and future work on the integration are going to be specied.
Page 30 of 37
https://www.assembla.com/spaces/liftweb/tickets/1061-allow-snippet-resolutionfor-subpackages
Marcus Denison
Page 31 of 37
Bibliography
[Bar11] Barski, Conrad: Land of Lisp. no starch press, 2011 [Bra10] Braun, Oliver: Scala Objektfunktionale Programmierung. Hanser Verlag, 2010 Carl
[com09] compurware, Gomez The Web Performance D.: Why Web Performance Matters. Whitepaper, 2009. Available online at www. gomez.com/pdfs/wp_why_web_performance_matters.pdf, visited on June 4th 2011. [DCBW11] Derek Chen-Becker, Marius D. ; Weir, Tyler: Exploring Lift: Lift 2.0 Edition. http://exploring.liftweb.net, 2011. Available online at http://exploring.liftweb.net, visited on June 4th 2011 [FFSB04] Freeman, Eric ; Freeman, Elisabeth ; Sierra, Kathy ; Bates, Bert: Head First Design Patterns. OReilly, 2004 [Fow03] Fowler, Martin: Patterns of Enterprise Application Architecture. Addison Wesley, 2003 [HT99] Hunt, Andrew ; Thomas, David: The Pragmatic Programmer. Addison Wesley, 1999 [Hus03] Huseby, Sverre H.: Innocent Code: A Security Wake-Up Call for Web Programmers. John Wiley and Sons, 2003 [Mar09] Martin, Robert C.: Clean Code: A Handbook of Agile Softare Craftsmanship. Prentice Hall, 2009 [Mey00] Meyer, Bertrand: Object-Oriented Software Construction. Prentice Hall, 2000 [OSV10] Odersky, Martin ; Spoon, Lex ; Venners, Bill: Programming in Scala 2nd Edition. artima, 2010 [Per10] Perrett, Timothy: Introducing Lift from Lift in Action. Greenpaper, 2010. Available online at http://www.manning.com/perrett/; visited on June 3rd 2011. [Per11] Perrett, Timothy: Lift in Action: The simply functional web framework for Scala. 2011. Available online at http://www.manning.com/ perrett/, visited on June 3rd 2011.
Marcus Denison
Page 32 of 37
Bibliography
Marcus Denison
[Pol11] Pollak, David: Simply Lift. Website, 2011. Available online at http://simply.lift.net; visited on June 3rd 2011. [SEB10] Stefan Edlich, Jens H. Achim Friedland F. Achim Friedland ; Brauer, Benjamin: NoSQL: Einstieg in die Welt nichtrelationaler Web 2.0 Datenbanken. Hanser, 2010 [Sub09] Subramaniam, Venkat: Programming Scala: Tackle Multicore Complexity on the Java Virtual Machine. Pragmatic Programmers, 2009
Page 33 of 37
List of Figures
3.1 4.1 4.2 4.3 4.4 4.5 4.6 4.7 5.1 5.2 5.3 5.4 6.1 View-ViewModel-Model . . . . . . . . . . . . . . . . . . . . . . . . . Before modication of the User object After modication of the User object . Entry Record . . . . . . . . . . . . . . Entries by a User . . . . . . . . . . . . User Session . . . . . . . . . . . . . . . XSS Input . . . . . . . . . . . . . . . . XSS Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 12 12 13 13 15 15 16 20 20 21 22
FhS-LDAP-Module API . . . . . . . . . . FhS-LDAP Module API LDAP Attributes Re-factored Entry Record . . . . . . . . . SpiritRecord UML . . . . . . . . . . . . .
Marcus Denison
Page 34 of 37
List of Tables
3.1 6.1 Lift vs. OWASP Top 10 . . . . . . . . . . . . . . . . . . . . . . . . . 7 EmployeeWeb vs. PlanningWeb . . . . . . . . . . . . . . . . . . . . . 30
Marcus Denison
Page 35 of 37
Listings
4.1 4.2 4.3 4.4 4.5 4.6 4.7 5.1 5.2 5.3 5.4 5.5 6.1 6.2 LDAPAuth . . User Object . . Record Usage . Textarea code . Textarea output Update method Create method . . . . . . . . . . . . code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 11 12 15 16 17 18 19 21 23 24 24
FhS LDAP Module Init . . . . . . . . . . Method factory . . . . . . . . . . . . . . . Refactored snippet for writing news . . . . Validating that the subject is never empty Block UI trait . . . . . . . . . . . . . . . .
Fetching data from the RESTful DB-Service . . . . . . . . . . . . . . 28 Saving data to the RESTful DB-Service . . . . . . . . . . . . . . . . 29
Marcus Denison
Page 36 of 37
Statutory declaration
I declare that I have authored this thesis independently, that I have not used other than the declared sources / resources, and that I have explicitly marked all material which has been quoted either literally or by content from the used sources.
Schmalkalden, 09-01-2011
Marcus Denison
Marcus Denison
Page 37 of 37