Jon Rumsey

An online markdown blog and knowledge repository.


Project maintained by nojronatron Hosted on GitHub Pages — Theme by mattgraham

Class Notes Week 4 Jun 6 Through 10

Monday Morning Discussion

STOP BEING A COMPLETIONIST

Spring MVC requires submit FORM DATA by default unless you specificy application-type/json.

Code Challenge 13 Review

Big-O notation generally deals with TIME, and less so about space because memory is relatively cheap.

Recursive call? O(n)

Adding an Array (O(n) in Space)? Adding 2 arrays? Could be 2n, 3n etc, but it still boils down to 'n' because the increase is not significant.

Base Case: Required in recursive methods. Tells the recursive function where to stop.

Remember always check for null before calling a method and using Node.child as an argument.

Lab 13 Review

This was our first full-stack application.

Spring Retro:

Trees Retro:

Authentication

Authentication:

Authorization:

Roles:

Unauthentication/Anonymous Users

What are ways we can authenticate users/systems?

Commonly used 2FA and MFA methodologies:

  1. Something you have: A random number generator or Key
  2. Something you know: PIN, Password
  3. Something you are: Biometrics
  4. Something you do: Dynamic biometrics e.g. Voice

Hasing and Encryption

See Jun6 reading notes.

Hashing is NOT encryption in and of itself.

Salting: Merging a pre-configured variable/string with a plaintext. Salt must be kept secret. Does not make up for using a break-able cipher.

BCrypt is a hashing tool.

Hashing vs Encryption

Hashing

DO NOT add Spring Security to our existing Labs => Start a new lab instead.

Lab Preview

Class 14 Lab due today.

Use the code (below) as a baseline to developing this lab.

Don't direct people to a route UNTIL THEY ARE LOGGED ON.

Do NOT use Spring Security today.

Use Thymeleaf w/ 'Model' and avoid using "User" as the name of your user object.

MVC

Views
Controllers and Routes
Models

UserModel:

Repo with JPA:

AuthRepo: The interface that hosts the DB access methods:

Note: Do not use the class name or variable name "User". Instead, use a more-descriptive name i.e. "SiteUser" or "ChatUser" etc.

Database

postgres SQL type DB.

Live Coding Notes

Having git issues? How is your repository set up? Are you sharing projects within the same git repo?

Steps taken during live coding:

  1. Set Project structure and configs using Initializer: Select the correct JDK version that you have on your dev machine
  2. build.gradle: starter jpa, starter tymeleaf, spring web, spring boot devtools, starter test, postgresql
  3. Make sure your IDE is starting up at the actual PROJECT ROOT.
  4. Update Application.properties to include datasource.url, datasource.username, datasource.password, jpa.generate-dll, jpa.hibernate.dll, hiddenmetho.filter.enabled
  5. PGAdmin4: Create the necessary Database (if using an existing one DROP EXISTING TABLES).
  6. When building, make sure a 'build successful' actually results.
  7. build a proof-of-life html template page: index.html (new file => html, or new file => ! [Tab])
  8. add a signup.html file and write a Form action with the signup path
  9. add a login.html file and write a Form action with login path
  10. Build and check for errors: Missing datasource, etc
  11. test the home route and verify your index.html page appears!
  12. build an Auth Controller using '@Controller': '@GetMapping(/route)' with method returning the dynamic/template html page
  13. Create a SiteUser class that includes '@Entity' and import javax.persistence.Entity. Add properties including a '@Id' (java persistence ID) and '@GeneratedValue' with a strategy to auto-generate and increment the ID.
  14. Implement a repository, extending JpaRepository, and pass-in the Model and type of the ID property. Dont forget CTORs and getters+setters.
  15. build-out '@PostMapping(/route)' entries to enable posting to the dynamic website. Use method return type 'RedirectView' so that on a 'login' route, and credential test returns true, the next-loaded page (redirect page) will be the splash page (e.g. User is "in" the application).
  16. Back in the Repository class definition, set up the CRUD command and supply the Class property you are searching for: TYPE findByUser(username)
  17. Update the Controller to test the password vs what is in the database and return the redirect view (to the page the user can access only if logged on).
  18. Use .equals() to compare object.password with _password parameter.
  19. Add BCrypt to the build.gradle file, dependencies section.
  20. Implement hashed passwords using BCrypt: 'BCrypt.hashpw(password, BCrypt.gensalt(int: hash_rounds));' and then update the new site user password to be the hashed_password.
  21. Back to login Controller route, update the if statement: 'if((userFromDB == null) || (!BCrypt.checkpw(_password, userFromDB.password)) return new RedirectView("/login");' otherwise user gets sent to home route "/". Use parenthesis to force the evaluations to be expressions so they operate in the correct order.
  22. Verify your user and hashed-passwd logic for redirecting to Home or Login again.

Remember:

Code Challenge 16

Find maximum value within a binary tree.

Tip: Try to track the maximum value within recursion.

Can be partnered on one-your-own.

Team Prep Work Today

Planning for all the usual Midterm/Final Presentation preparatory work.

Tuesday 7Jun22

ALWAYS keep working within MVP and Features:

Apply this thinking to Labs.

Team Prep Comments

Try to get your MVP small enough that it is complete by EOD Tuesday.

If Tuesday MVP is reached then bolt-on smaller feature add-ons and continue with documentation and testing.

Not all conflict involves emotions, so check yourself and your situation, and communicate concerns and bring solutions to the table.

There are 4 total preps.

Project Prep 2 is PROJECT IDEAS.

Code Review

Tree Max

Review the very basics of Unit Tests

Using Cookies in Spring

Note: Case sensitivity is in play!!

Use Developer Tools > Application > Storage > Cookies: To see set cookie details e.g. JSessionID (aka SessionID) and Value etc.

Need to add a Model for the AuthenticationController to be able to properly authenticate a user.

  1. HttpServletRequest request must be added to the controller path @PostMapping("loginWithSecretPage")
  2. SetAttribute on this session: Binds an object to a session using the specified name. session.setAttribute("username", username)
  3. HttpSession session = request.getsession() comes from httpservletrequest?
  4. session.invalidate() breaks the session cookie info so they cannot be replaced (logs out the user).
  5. Hide cookie usage via server.servlet.sesion.tracking-modes="cookie" ??? (look for Alex's future update on this).

Spring Security Demo

Create an authenticated server.

New gradle project, NOT MAVEN.

Setup using Spring Security:

  1. Initializr with postgres, spring boot, spring security, etc.
  2. Verify application.properties is set up.
  3. Do a build to verify all is good. User-generated security password is provided. Use this default built-in form, but YOU need to update it by implementing the 'what to do' after form login.

Beans

Spring transforms @Service, @Entity, and @Controller into "Beans".

These are DI'd components that make up the Spring "Application Context".

Singleton: Only instantiate an object ONE TIME throughout the life of the application.

Beans exist for the life of the application, each Bean its own unique service/state, until the App shuts down.

Repositories are also Beans, so just use the '@Autowired' annotation to access it from other Classes!

Note: Variables MUST be named consistently!

Spring Beans: @Autowired, @Component, @Service, @ => All beans go away when the App is closed!

Steps:

  1. Set up a user model and repo: 'model.AppUser' with properties: username, password, and add @Entity and @Id @GeneratedValue, and be sure to use private fields and getters/setters EXCEPT for Id. Also add constructors.
  2. Create Repo: 'repository.AppRepository' and set it as an interface that 'extends JPARepository<AppUser, Long> { // custom query like findByUsername(String username);}'
  3. Create a controller for that model: New Class controller.AppController, add four routes: get to login, get to signup, post to login, and post to login. Remember to use '@Controller' and '@AutoWired' and '@GetMapping' and '@PostMapping' decorators.
  4. In the Post to Signup path, ensure the method grabs the username and password, then '@AutoWire' it (makes it a bean so it is a service available and DRY is followed).
  5. Save the new user (with hashed passwd) to the repository.
  6. UserDetailsServiceImpl implements UserDetailsService => Createa new Package called 'config.UserDetailsServiceImpl' of type Class. Then implement the method(s).
  7. Implement UserDetails on the ApplicationUser class (there are 5 of them) and Booleans all return true.
  8. Summary: WebSecurityConfig extends WebSecurityConfigurerAdapter. Create a new configs.WebSecuityConfig Class that extends WebSecurityConfigurerAdapter. Also add @Configuration and @EnableWebSecurity. Continues on next step...
  9. Implement the @AutoWired annotation and set variable type UserDetailsServiceImp userDetailsService. NExt step...
  10. Create public PasswordEncoder passwordEncoder method, takes no params. Enable BCryptPasswordEncoder as a variable (it already implemnets PasswordEncoder) so it can be returned within the method and returns bCryptPasswordEncoder. Continue...
  11. Make this method a Bean with '@Bean', then add '@Autowired PasswordEncoder passwordEncoder' which injects the singleton Bean into the class so it is usable within those methods, THEN just use 'passwordEncoder' to .encode(passwd) or .decode(passwd).
  12. Override configure(AuthenticationManagerBuilder) with 'auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());'
  13. Configure security via HttpSecurity: Override configure(HttpSecurity http) and implement CORS, CSRF, URL Maters, Form Login, and Logout. Continue
  14. CORS to configure access from outside your network: http.cors().disable() // were not sharing outside of our network
  15. CSRF Cross Site Reference Forging: 'http.csrf().disable().authroizeRequests().antMatchers("/").permitAll()' // will not allow requests to come in as you unless they come from specific routes defined in out site but this specific config just allows anonymous access to root
  16. CSRF for other routes: ... .antMatchers("/permitPath1", "/permitPath2", ...).permitAll()
  17. Tie-together chained configuration with '.and()'
  18. Form Login location config: ... .loginPath("/loginPath")
  19. Logout page too: ... .and().logout()
  20. On successful logout send user to login: ... .logoutSuccessUrl("/login")
  21. Registration Page: We have createUser route "/signup". Create a template HTML for this page, add a Form with proper names and IDs so the username and password (and anything else) are captured for setup new user route.
  22. Login Page: Similar to Registration Page but for login of an existing, valid user. This will override the built-in login page that Spring Security deployed when we initialized the project.
  23. Auth with HttpServletRequest (later): Add this method to the AppController. Autowire the HttpServletRequest and name it 'request' so that it is available to the entire Controller. authWith

Note: There is no POST TO LOGIN because it is all in WebSecurityConfig.java => '.loginPath("/login")'

Wednesday 8Jun22 Notes

Morning Discussion

Mid-term Team Project chat.

Teams tell Alex when they want to stand-up meet, and this can be scheduled day-of.

Spring Security authz to content (conditional rendering).

Security software: Don't dev it yourself, use what exists, has been well tested, and what big corporations are using.

Bruce Schneier chit-chat.

Bug Bounties: Finding bugs can turn into cash! bugcrowd

Code Review Breadth First

Tips:

O(n) Stuff:

Authorization

The Spring Security Cheat Sheet can be followed to help get Spring Security set up and implemented.

Separate Controllers to manage specific tasks i.e. User Creation actions, Authenticated actions, Unauthenticated actions, specific paths, etc.

Principal: The authenticated user or object. A User Principal in this case.

Threading: One user per thread => Only that thread's user will be handled in the auth/action workflow.

When creating a Controller Mapping, take in args Principal p and Model m and test p != null before taking action on the args.

On a path HTML where a Controller Mapping has a principal params:

All of the above is baked in to Spring Security and is fairly basic.

[ ] Today's Lab (Class 17) will build on yesterday's (CodeFellowship). [X] TODO: Get my app up and running, commit and update yesterday's Lab submission THEN move-on to the rest of the app. [ ] TODO: Reference baeldung dates-in-thymeleaf page for help with managing Date objects in your Thymeleaf website including formatting.

Profile Page Controllers and Setup

Note: When using @GetMapping("/path/{id}") => setup the controller method with a @PathVariable Long Id in the params list.

  1. Principal p only saves session information, usually "username".
  2. Principal has other functionality, but in the @GettMapping parameters list, it allows asking the MODEL (Entity) to get data from it.
  3. Within a controller: Work with the session information, and THEN make call(s) to the DB for user (Principal, now Entity) information.
  4. Utilize a 'th:if' to verify a 'user != null' as conditional to display/not the user information on the page.
  5. Forms only support POST actions be default? PUT method, required by Thymeleaf, add spring.mvc.hiddenmethod to include PUT.

Create Custom 404 Page

  1. Home controller, for practice, set a path that will throw a 404, for e.g. on the "/" route...see next step.
  2. Decorate a new nested class @ResponseStatus(value=HttpStatus.NOT_FOUND) and extend the appropriate Exception type e.1. ResourceNotFoundException extending RuntimeException (super).
  3. Disable Spring MVC Default Error page (application.config).
  4. Customize a page for the '/error' route that captures data sent by the Exception.

Thymeleaf Fragments

Analogous to React Components!

Set up a fragment html page with frags for use elsewhere: TH:FRAGMENT => Enables identifying the type of frag? e.g. ...th:fragment="nav-header"...

Utilize a fragment within a different page: 'th:replace="/fragment/fragpage :: element"'

A Redirect is just a path (?).

Thymeleaf Temporals: Enables formatting Time and Date objects.

Code Challenge Tree-Fizz-Buzz

  1. Whiteboard this
  2. K-ary trees: Input existing tree; Output NEW TREE
  3. K-ary NODES must be used
  4. Iterative or recursive? Your choice
  5. TRAVERSE THE TREE!
  6. How to build the tree looking like original but with the new values?

Project Prep #3

  1. Repo and tooling.
  2. Meet with Alex for pitching MVPs.
  3. Follow tasks to build the repo.

Friday Morning Notes

Remember things we've learned about and used these last four weeks:

Midterm Guidance

Alex will help tweak MVP.

Interview Demos

30-minute technical interviews will be happening in coming weeks.

K-ary Tree Review

Big-O

A decent recursion discussion on Stack Overflow

MVC Lab and Many-To-Many

Lab Details:

Threads:

Roles:

Many-to-Many:

@ManyToMany 
@JoinTable(
  name=temp_join_table_name, 
  joinColumns={@JoinColumn(name=table_to_join)}, 
  InverseJoinColumns={@JoinColumn(name=other_table_to_join
  )}) 
Set<Type> property_name;

TODOs

[ ] Keep hacking away at missing assignments this week [ ] Create a GH Gist with stuff like Application.properties template [ ] RETRO every day, and once per week: What can I regurgitate without looking up? What concepts do I have trouble with? Were there any blockers that I need help with? [ ] CodeChallenge 14: Do for bonus points! Pair-up to make it easier!

Return to root [README.html]