the authentication request in question is located in: /src/main/java/com/nighthawk/spring_portfolio/mvc/jwt/JwtApiController.java
@PostMapping("/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();
}
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);
}
}
this is the authentication method we are calling to, which provides us with the cookie we need for access to our database.
so how do I add login?
create a login function on the frontend which can send authentication request to backend. make sure it passes user input as variables for the authentication request
in database page, create method which calls a get method that checks for authentication first before displaying the data.
add error handling for when our authentication fails
Sign Up
Steps
Collect user input
Put user input into a url as parameters
Send POST to backend to make user
(RECOMMENDED) Redirect/Refresh page
Frontend code that collects user input
function signup_user() {
var requestOptions = {
method: 'POST',
mode: 'cors',
cache: 'no-cache'
};
// Collect user input
let fetchName = document.getElementById("signUpNameInput").value;
let fetchEmail = document.getElementById("signUpEmailInput").value;
let fetchPassword = document.getElementById("signUpPasswordInput").value;
let fetchDob = document.getElementById("signUpDobInput").value;
// Posting in backend only works if user input is sent as query parameters
let requestURL = `http://localhost:8085/api/person/post?email=${fetchEmail}&password=${fetchPassword}&name=${fetchName}&dob=${fetchDob}`;
console.log(requestURL)
fetch(requestURL, requestOptions)
.then(response => {
if (!response.ok) {
return response.text().then(errorMsg => {
alert('Error: ' + errorMsg);
});
}
// Success!!!
alert("Signup Complete");
// Redirect to Database location
location.reload();
})
.catch(error => {
alert('An unexpected error occurred: ' + error.message);
});
}
under /src/main/java/com/nighthawk/spring_portfolio/mvc/human/HumanApiController.java scroll down to the chunk of code that says post
/*
POST Aa record by Requesting Parameters from URI
*/
@PostMapping( "/post")
public ResponseEntity<Object> postHuman(@RequestParam("email") String email,
@RequestParam("password") String password,
@RequestParam("name") String name,
@RequestParam("dob") String dobString,
@RequestParam("role") String role) {
Date dob;
try {
dob = new SimpleDateFormat("MM-dd-yyyy").parse(dobString);
} catch (Exception e) {
return new ResponseEntity<>(dobString +" error; try MM-dd-yyyy", HttpStatus.BAD_REQUEST);
}
password = passwordEncoder.encode(password);
List<Human> humans = repository.findAll();
for (Human hman : humans){
usedClassCodes.add(hman.getClassCode());
}
String classCode = "";
if (role.equals("Teacher")){
int CODE_LENGTH = 6;
SecureRandom random = new SecureRandom();
BigInteger randomBigInt;
do {
randomBigInt = new BigInteger(50, random);
classCode = randomBigInt.toString(32).toUpperCase().substring(0, CODE_LENGTH);
} while (usedClassCodes.contains(classCode));
usedClassCodes.add(classCode);
}
else{
if (role.equals("Student")){
classCode = null;}
else{
return new ResponseEntity<>("The role has to be either 'Student' or 'Teacher'", HttpStatus.BAD_REQUEST);
}
}
// A Human object WITHOUT ID will create a new record with default roles as student
Human human = new Human(email, password, name, dob, role);
human.setClassCode(classCode);
repository.save(human);
Statistic stat = new Statistic();
stat.setClassCode(classCode);
stat.setName(name);
return new ResponseEntity<>(email +" created successfully", HttpStatus.CREATED);
}
Explain a POJO and changes to a POJO
A POJO, which stands for Plain Old Java Object, is a Java class that doesn't extend or implement any frameworks, interfaces, or annotations specific to a particular framework, such as Java EE or Spring. It is a simple and standard Java object that encapsulates data and behavior, following basic Java conventions. POJOs are typically used to represent data structures and transfer data between different layers of an application.
public class Person {
private String name;
private int age;
// Constructors
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Getter and Setter methods
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Changes to a POJO can involve modifications to its fields, methods, or even the addition of new methods. Here are some common changes that might occur:
Adding a new field: You might decide to add a new attribute to the POJO to represent additional information.
public class Person {
private String name;
private int age;
private String address; // New field
// Constructors, getters, and setters remain unchanged
}
Modifying existing fields or methods: You might need to change the data type of a field, update method logic, or make adjustments based on evolving requirements.
public class Person {
private String fullName; // Modified field name
// Updated getter and setter
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
}
Adding or removing methods: You might add new methods to provide additional functionality or remove methods that are no longer needed.
public class Person {
// Existing fields and methods
// New method
public String greet() {
return "Hello, my name is " + name;
}
}
Explain security configuration rules that are required for access
Security configuration rules depend on the context, such as the technology stack being used. However, for a web application, especially in a Java Spring Security context, here are some general concepts:
Authentication:
Configure authentication with JWT to validate user credentials.
Define login and logout URLs.
Describe docker and process for update docker application
Docker is a platform that enables developers to automate the deployment of applications inside lightweight, portable containers. Containers encapsulate an application and its dependencies, providing a consistent and reproducible environment across different systems. Docker containers can run on any machine that has Docker installed, making it easier to develop, test, and deploy applications in various environments.
Update Dockerfile:
If there are changes to dependencies or configurations that affect the Docker image, update the Dockerfile accordingly.
Example Dockerfile snippet:
# Use a base image
FROM amd64/eclipse-temurin:20-jdk-alpine
Set the working directory
WORKDIR /app
Install dependencies or perform other setup tasks
RUN apt-get update && apt-get install -y some-package
### Push the Updated Image to a Registry (Optional):
- If you are using a container registry like Docker Hub, push the updated image to the registry. This step is essential if you want to share the updated image with others or deploy it on multiple machines.
docker push amd64/eclipse-temurin:20-jdk-alpine
### Stop and Remove Existing Containers:
- Stop and remove the existing containers running the old version of the application.
### Run a New Container with the Updated Image:
- Create and run a new container using the updated Docker image.
docker run -d --name your-container-name -p 8081 amd64/eclipse-temurin:20-jdk-alpine
# Describe route 53 and process for domain setup
view the quizlet for a better answer
Amazon Route 53 is a scalable and highly available domain name system (DNS) web service provided by Amazon Web Services (AWS). It allows users to register and manage domain names, and it also provides DNS routing services to route end-user requests to globally distributed AWS resources, such as EC2 instances, S3 buckets, and load balancers. Route 53 supports various DNS record types, and it offers features like health checks, traffic management, and domain registration.
Here is a general process for setting up a domain using Amazon Route 53:
Domain Registration:
Sign in to AWS Console:
Log in to the AWS Management Console using your AWS account credentials.
Navigate to Route 53:
Go to the Route 53 service in the AWS Management Console.
Choose "Register Domain":
Click on the "Register Domain" button to initiate the domain registration process.
Search for a Domain:
Enter the desired domain name in the search bar to check its availability. If the domain is available, you can proceed with the registration.
Select and Review Domain Details:
Select the desired domain from the search results.
Review the domain details, including the registration period, and configure additional options if needed.
Configure Domain Settings:
Configure the domain settings such as contact information, privacy protection (if desired), and name server settings.
Review and Confirm:
Review your domain registration details and confirm the purchase.
Complete the Registration:
Provide payment information and complete the domain registration process.
DNS Configuration:
Once the domain is registered, you can configure the DNS settings using Amazon Route 53:
Access Route 53 Dashboard:
Go back to the Route 53 dashboard in the AWS Management Console.
Create a Hosted Zone:
Click on "Create Hosted Zone" to set up a hosted zone for your domain. This is where you configure DNS records.
Enter Domain Information:
Enter your domain name and choose a region for the hosted zone.
Create DNS Records:
Within the hosted zone, create DNS records such as A records, CNAME records, MX records, etc., based on your application's requirements.
Update Name Servers:
After creating DNS records, Route 53 provides you with a set of name servers for your domain. Update the name server settings with your domain registrar to point to the Route 53 name servers.
Verify DNS Configuration:
Wait for the DNS changes to propagate. You can use tools like "nslookup" or "dig" to verify that your domain is resolving to the correct IP addresses.
Configure Additional Features (Optional):
Explore additional features of Route 53, such as health checks, traffic routing policies, and domain aliases, to enhance your DNS configuration.
# Show API access code and error handling, specifically redirect on 403
- This works with the JWT from earlier
- this function resides in our database display on our frontend, and does 2 things
1. access our jwt method and check for authentication, then get the database if so
2. handle errors for when authentication fails
``` javascript
function fetchUserData() {
var requestOptions = {
method: 'GET',
mode: 'cors',
cache: 'default',
credentials: 'include',
};
fetch("http://localhost:8085/api/person/jwt", requestOptions)
.then(response => {
if (!response.ok) {
const errorMsg = 'Login error: ' + response.status;
console.log(errorMsg);
switch (response.status) {
case 401:
alert("Please log into or make an account");
window.location.href = "http://127.0.0.1:4100/Login-Lesson/loginSignup";
break;
case 403:
alert("Access forbidden. You do not have permission to access this resource.");
break;
case 404:
alert("User not found. Please check your credentials.");
break;
// Add more cases for other status codes as needed
default:
alert("Login failed. Please try again later.");
}
return Promise.reject('Login failed');
}
return response.json();
// Success!!!
})
.then(data => {
// Display user data above the table
const userDataContainer = document.getElementById("userData");
userDataContainer.innerHTML = `
<img src="/Login-Lesson/images/defaultUser.png" width="250" height="250">
<h1><strong>${data.name}</strong></h1>
<p>Email: ${data.email}</p>
<p>Age: ${data.age}</p>
<p>ID: ${data.id}</p>
<button onclick="signOut()">Sign Out</button>
`;
console.log(data);
})
.catch(error => console.log('error', error));
}
Describe managing CORS policies through Nginx and Java
Cross-Origin Resource Sharing (CORS) is a security feature implemented by web browsers to control how web pages in one domain can request and interact with resources hosted on another domain. Managing CORS policies is crucial when dealing with web applications that make cross-origin requests, and it involves configuring both the server (e.g., Nginx) and the backend application (e.g., Java) to handle these requests securely.
Let's go through the steps for managing CORS policies using Nginx and Java:
Nginx Configuration:
Install Nginx:
Ensure that Nginx is installed on your server.
Configure CORS in Nginx:
Open the Nginx configuration file, often located at /etc/nginx/nginx.conf or /etc/nginx/sites-available/default.
Inside the server block, add the following configuration to enable CORS:
server {
# ... other server configurations
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
add_header 'Access-Control-Allow-Credentials' 'true';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
# ... other location configurations
}
Restart Nginx:
After making changes to the Nginx configuration, restart the Nginx service to apply the changes:
sudo service nginx restart
Java Application Configuration:
Handle CORS in Java:
In your Java web application, you need to ensure that it handles CORS requests appropriately. If you're using a framework like Spring, you can use annotations or configuration to manage CORS.
Example using Spring Boot:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class YourController {
@GetMapping("/data")
public String getData() {
return "Your data";
}
}
Handle Preflight Requests:
For complex requests (e.g., those with custom headers), browsers may send a preflight OPTIONS request before the actual request. Ensure that your backend application responds appropriately to these preflight requests.
Describe reverse proxy of server_name to proxy_pass
In Nginx, the server_name directive is used to define the server's domain name or IP address. On the other hand, the proxy_pass directive is used to specify the backend server to which Nginx should forward client requests. When these two directives are used together, Nginx acts as a reverse proxy, forwarding requests to the specified backend server based on the server_name. This is a common setup for load balancing, security, or content delivery purposes.
Let's walk through the basic configuration for a reverse proxy using server_name and proxy_pass in an Nginx server block:
server {
listen 80;
server_name your-domain.com www.your-domain.com;
location / {
proxy_pass http://backend-server-ip:backend-server-port;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Additional configurations can be added as needed
# ...
}
Explanation of the key directives:
listen: Specifies the IP address and port on which the server listens for incoming requests (e.g., 80 for HTTP).
server_name: Defines the domain name(s) associated with this server block. Requests with matching Host headers will be directed to this server block.
location /: Sets up the location block for the root path (/). This is where the proxying behavior is defined.
proxy_pass: Specifies the protocol, IP address, and port of the backend server to which requests should be forwarded.
proxy_set_header: Sets additional headers to be passed to the backend server. In this example, headers like Host, X-Real-IP, X-Forwarded-For, and X-Forwarded-Proto are commonly set to provide information about the original client request.
Working API's coming from a deployed server. Individuals will be required to know the following...
Helpful quizlet: https://quizlet.com/846745588/csa-deployment-pop-quiz-flash-cards/?new
Show JWT signup and/or login process
the authentication request in question is located in: /src/main/java/com/nighthawk/spring_portfolio/mvc/jwt/JwtApiController.java
this is the authentication method we are calling to, which provides us with the cookie we need for access to our database.
so how do I add login?
Sign Up
Steps
Frontend code that collects user input
under /src/main/java/com/nighthawk/spring_portfolio/mvc/human/HumanApiController.java scroll down to the chunk of code that says post
Explain a POJO and changes to a POJO
A POJO, which stands for Plain Old Java Object, is a Java class that doesn't extend or implement any frameworks, interfaces, or annotations specific to a particular framework, such as Java EE or Spring. It is a simple and standard Java object that encapsulates data and behavior, following basic Java conventions. POJOs are typically used to represent data structures and transfer data between different layers of an application.
Changes to a POJO can involve modifications to its fields, methods, or even the addition of new methods. Here are some common changes that might occur:
Adding a new field: You might decide to add a new attribute to the POJO to represent additional information.
Adding or removing methods: You might add new methods to provide additional functionality or remove methods that are no longer needed.
Explain security configuration rules that are required for access
Security configuration rules depend on the context, such as the technology stack being used. However, for a web application, especially in a Java Spring Security context, here are some general concepts:
Authentication:
Configure authentication with JWT to validate user credentials. Define login and logout URLs.
Describe docker and process for update docker application
Docker is a platform that enables developers to automate the deployment of applications inside lightweight, portable containers. Containers encapsulate an application and its dependencies, providing a consistent and reproducible environment across different systems. Docker containers can run on any machine that has Docker installed, making it easier to develop, test, and deploy applications in various environments.
Update Dockerfile:
Set the working directory
WORKDIR /app
Install dependencies or perform other setup tasks
RUN apt-get update && apt-get install -y some-package
Copy application code
COPY . /app
run maven
RUN ./mvnw package
Command to run the application
CMD ["java", "-jar", "target/spring-0.0.1-SNAPSHOT.jar"]
Expose the necessary ports
EXPOSE 8081
docker build -t amd64/eclipse-temurin:20-jdk-alpine .
docker push amd64/eclipse-temurin:20-jdk-alpine
docker stop your-container-name docker rm your-container-name
docker run -d --name your-container-name -p 8081 amd64/eclipse-temurin:20-jdk-alpine
Describe managing CORS policies through Nginx and Java
Cross-Origin Resource Sharing (CORS) is a security feature implemented by web browsers to control how web pages in one domain can request and interact with resources hosted on another domain. Managing CORS policies is crucial when dealing with web applications that make cross-origin requests, and it involves configuring both the server (e.g., Nginx) and the backend application (e.g., Java) to handle these requests securely.
Let's go through the steps for managing CORS policies using Nginx and Java:
Nginx Configuration:
Install Nginx:
Configure CORS in Nginx:
Inside the server block, add the following configuration to enable CORS:
Restart Nginx:
Java Application Configuration:
Handle CORS in Java:
Example using Spring Boot:
Handle Preflight Requests:
Example in Spring Boot:
Describe reverse proxy of server_name to proxy_pass
In Nginx, the server_name directive is used to define the server's domain name or IP address. On the other hand, the proxy_pass directive is used to specify the backend server to which Nginx should forward client requests. When these two directives are used together, Nginx acts as a reverse proxy, forwarding requests to the specified backend server based on the server_name. This is a common setup for load balancing, security, or content delivery purposes.
Let's walk through the basic configuration for a reverse proxy using server_name and proxy_pass in an Nginx server block:
Explanation of the key directives:
listen: Specifies the IP address and port on which the server listens for incoming requests (e.g., 80 for HTTP).
server_name: Defines the domain name(s) associated with this server block. Requests with matching Host headers will be directed to this server block.
location /: Sets up the location block for the root path (/). This is where the proxying behavior is defined.
proxy_pass: Specifies the protocol, IP address, and port of the backend server to which requests should be forwarded.
proxy_set_header: Sets additional headers to be passed to the backend server. In this example, headers like Host, X-Real-IP, X-Forwarded-For, and X-Forwarded-Proto are commonly set to provide information about the original client request.