Question 1
We are going into reverse_proxy. There is something called server_name and proxy_pass. Define server_name and proxy_pass in your reverse configuration file.
server_name is the subdomain under your backend or server that connects to it, and it is the name of your website/directory
proxy_pass is basically the file you will deploy it from on AWS, and the backend will be forwarded to this link when the request is made.
Final Score: 0.9/1.0 verified by Mr. Mortensen in class
server {
server_name platformer_ws.nighthawkcodingsociety.com;
location / {
proxy_pass http://localhost:8085;
# this magic is needed for WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Question 2
So umm, I want you to show me a JWT login process, and I want you to split the browser screen, and I want you to show me a page that shows the JWT process.
server_name is the subdomain under your backend or server that connects to it, and it is the name of your website/directory
proxy_pass is basically the file you will deploy it from on AWS, and the backend will be forwarded to this link when the request is made.
Final Score: 0.9/1.0 Verified by Mr. Mortensen in class
package com.nighthawk.spring_portfolio.mvc.jwt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import com.nighthawk.spring_portfolio.mvc.human.Human;
import com.nighthawk.spring_portfolio.mvc.human.HumanDetailsService;
import com.nighthawk.spring_portfolio.mvc.person.Person;
import com.nighthawk.spring_portfolio.mvc.person.PersonDetailsService;
@RestController
@CrossOrigin(origins = "http://localhost:8085")
public class JwtApiController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private PersonDetailsService personDetailsService;
@Autowired
private HumanDetailsService humanDetailsService;
@PostMapping("/person/authenticate")
public ResponseEntity<?> createAuthenticationToken(@RequestBody Person authenticationRequest) throws Exception {
authenticate(authenticationRequest.getEmail(), authenticationRequest.getPassword());
final UserDetails userDetails = personDetailsService
.loadUserByUsername(authenticationRequest.getEmail());
final String token = jwtTokenUtil.generateToken(userDetails);
final ResponseCookie tokenCookie = ResponseCookie.from("jwt", token)
.httpOnly(true)
.secure(true)
.path("/")
.maxAge(3600)
.sameSite("None; Secure")
// .domain("example.com") // Set to backend domain
.build();
return ResponseEntity.ok().header(HttpHeaders.SET_COOKIE, tokenCookie.toString()).build();
}
@PostMapping("/human/authenticate")
public ResponseEntity<?> createAuthenticationToken(@RequestBody Human authenticationRequest) throws Exception {
authenticate(authenticationRequest.getEmail(), authenticationRequest.getPassword());
final UserDetails userDetails = humanDetailsService
.loadUserByUsername(authenticationRequest.getEmail());
final String token = jwtTokenUtil.generateToken(userDetails);
final ResponseCookie tokenCookie = ResponseCookie.from("jwt", token)
.httpOnly(true)
.secure(true)
.path("/")
.maxAge(3600)
.sameSite("None; Secure")
// .domain("example.com") // Set to backend domain
.build();
return ResponseEntity.ok().header(HttpHeaders.SET_COOKIE, tokenCookie.toString()).body(new TokenResponse(token));
}
private void authenticate(String username, String password) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new Exception("INVALID_CREDENTIALS", e);
} catch (Exception e) {
throw new Exception(e);
}
}
public class TokenResponse {
private final String token;
public TokenResponse(String token) {
this.token = token;
}
public String getToken() {
return token;
}
}
}
Question 3
I want you to explain security configuration that are required for Spring Boot. Authentication required
Should use SecurityConfig.java and using pom.xml that have the required dependencies for the spring boot to work as well as a message that will display when the request can not be completed
Final Score: 0.9/1.0 verified by Mr. Mortensen in class
package com.nighthawk.spring_portfolio;
import org.springframework.beans.factory.annotation.Autowired;
import com.nighthawk.spring_portfolio.mvc.jwt.JwtAuthenticationEntryPoint;
import com.nighthawk.spring_portfolio.mvc.jwt.JwtRequestFilter;
import com.nighthawk.spring_portfolio.mvc.person.PersonDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
/*
* To enable HTTP Security in Spring
*/
@Configuration
@EnableWebSecurity // Beans to enable basic Web security
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
private PersonDetailsService personDetailsService;
// @Bean // Sets up password encoding style
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// configure AuthenticationManager so that it knows from where to load
// user for matching credentials
// Use BCryptPasswordEncoder
auth.userDetailsService(personDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.disable()
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/authenticate").permitAll()
.requestMatchers("/mvc/maker/update/**", "/mvc/maker/delete/**").authenticated()
.requestMatchers("/api/maker/post/**", "/api/maker/delete/**").authenticated()
.requestMatchers("/**").permitAll()
)
.cors(Customizer.withDefaults())
.headers(headers -> headers
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Credentials", "true"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-ExposedHeaders", "*", "Authorization"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Headers", "Content-Type", "Authorization", "x-csrf-token"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-MaxAge", "600"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Methods", "POST", "GET", "OPTIONS", "HEAD"))
)
.formLogin(form -> form
.loginPage("/login")
)
.logout(logout -> logout
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
)
.exceptionHandling(exceptions -> exceptions
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
fetch("/authenticate", {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data)}).then((data) => {
if (data.status == 200) {
window.location.replace("/maker");
} else if (data.status == 401) {
document.getElementById('message').innerHTML = "Not authorized to do this task"
} else {
document.getElementById('message').innerHTML = "Entered an invalid email or password"
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.13</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.nighthawk</groupId>
<artifactId>spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring</name>
<description>Intro project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<!-- Thymeleaf 3 -->
<org.thymeleaf-version>3.0.15.RELEASE</org.thymeleaf-version>
<org.thymeleaf.extras.springsecurity4-version>3.0.2.RELEASE</org.thymeleaf.extras.springsecurity4-version>
<nz.net.ultraq.thymeleaflayout-version>2.3.0</nz.net.ultraq.thymeleaflayout-version>
<thymeleaf-extras-java8time-version>3.0.1.RELEASE</thymeleaf-extras-java8time-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- View -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${org.thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<!-- TODO Remove once available in platform BOM -->
<version>${org.thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<!-- TODO Remove version once available in platform BOM -->
<version>${org.thymeleaf.extras.springsecurity4-version}</version>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
<version>${nz.net.ultraq.thymeleaflayout-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>${thymeleaf-extras-java8time-version}</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.zsoltfabok/sqlite-dialect -->
<dependency>
<groupId>com.zsoltfabok</groupId>
<artifactId>sqlite-dialect</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.6.3</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.6.3</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.17.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Question 4
I want you to explain a POJO and change this to a POJO. Show a POJO in the VSCode editor and show the data and result via postman
Final Score: 0.9/1.0 verified by Mr. Mortensen in class
public class Person {
// 3 different attributes
private String firstName;
private String lastName;
private int age;
public Person() { // Constructors
}
public Person(String firstName, String lastName, int age) {
this.firstName = firstName; // initializing variable
this.lastName = lastName; // referencing current object
this.age = age; // refers to the age attribute
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Question 5
Show me the port that uses Docker and the application and how it is used to make and update changes.
This should be shown on AWS and showing how the instance can be changed and deployed
Final Score: 0.9/1.0 verified by Mr. Mortensen in class
docker-compose down - Take down docker server so nothing breaks and it can recompile
git pull - Fetch Latest Data
./mvnw clean - Clean Maven (optional but recommended)
docker-compose up -d --build - Rebuild docker
IF no changes are shown, run service nginx restart