(Video)


1. Show JWT signup and/or login process

public class JwtRequestFilter extends OncePerRequestFilter {

	@Autowired
	private PersonDetailsService personDetailsService;

	@Autowired
	private JwtTokenUtil jwtTokenUtil;

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {

		final Cookie[] cookies = request.getCookies();
		String username = null;
		String jwtToken = null;
		// Try to get cookie with name jwt
		if ((cookies == null) || (cookies.length == 0)) {
			logger.warn("No cookies");
		} else {
			for (Cookie cookie: cookies) {
				if (cookie.getName().equals("jwt")) {
					jwtToken = cookie.getValue();
				}
			}
			if (jwtToken == null) {
				logger.warn("No jwt cookie");
			} else {
				try {
					// Get username from the token if jwt cookie exists
					username = jwtTokenUtil.getUsernameFromToken(jwtToken);
				} catch (IllegalArgumentException e) {
					System.out.println("Unable to get JWT Token");
				} catch (ExpiredJwtException e) {
					System.out.println("JWT Token has expired");
				} catch (Exception e) {
					System.out.println("An error occurred");
				}
			}
		}
		// If no cookies have name jwt return warning

		// Once we get the token validate it.
		if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

			UserDetails userDetails = this.personDetailsService.loadUserByUsername(username);

			// if token is valid configure Spring Security to manually set
			// authentication
			if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {

				UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
				usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
				// After setting the Authentication in the context, we specify
				// that the current user is authenticated. So it passes the
				// Spring Security Configurations successfully.
				SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
			}
		}
		chain.doFilter(request, response);
	}
}

This Java class, JwtRequestFilter, serves as a filter in a web application to handle authentication using JSON Web Tokens (JWTs).

It does the following:

  1. Retrieve JWT Token: Checks the incoming request for a JWT token in its cookies.

  2. Extract Username from Token: If a JWT token is found, it extracts the username from it. If no token is found or if there’s an issue extracting the username, it logs a warning message.

  3. Authenticate User: If a valid username is extracted, it loads user details from the application’s user service based on that username. Then, it validates the JWT token using a utility class (JwtTokenUtil). If the token is valid, it sets up the authentication context in Spring Security, indicating that the user is authenticated.

  4. Chain Execution: Finally, it allows the request to continue its journey through the filter chain, allowing subsequent filters to process the request.

2. Explain a POJO and changes to POJO

A POJO, short for plain old Java object, is used to describe a simple Java class that doesn’t depend on any special framework or library Just like any other Java class, a POJO is used to create objects. It typically contains private variables (attributes) with public getter and setter methods to access and modify those variables.

Example:

public class Car {
    private String make;
    private String model;
    private int year;

    public String getMake() {
        return make;
    }

    public void setMake(String make) {
        this.make = make;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }
}

3. Explain security configuration rules that required for access

  • Who are you? (Authentication): Making sure users are who they say they are when they log in.

  • What can you do? (Authorization): Deciding what each user is allowed to do once they’re logged in.

  • Keep secrets safe (Encryption): Scrambling information so only the right people can understand it.

  • Check everything (Input Validation): Making sure the stuff users give you won’t cause any trouble.

  • Hide your messages (Secure Communication): Making sure nobody else can see or change the information as it travels.

  • Keeping track (Session Management): Keeping an eye on who’s doing what on a website to prevent impostors.

  • Sharing safely (CORS): Deciding whether to let other websites use your stuff.

  • Put up barriers (Security Headers): Adding extra protections to web pages to keep bad guys out.

4. Describe docker and process for update

Docker:

  • It lets you package up your application and everything it needs to run, like code, libraries, and settings, into a neat little container It makes things super easy. You can create, ship, and run your applications anywhere, whether it’s on your laptop, a server, or in the cloud, without worrying about differences in environments.

Updating Process:

  1. Check for Updates: First, you need to see if there are any updates available for Docker itself. You can usually do this with a simple command or through a graphical interface if you’re using a tool like Docker Desktop.

  2. Update Docker Engine: If there’s a new version available, you download and install it. This process might vary depending on your operating system, but it’s usually just a matter of running a command or clicking a button.

  3. Update Containers: Once Docker itself is updated, you might need to update your containers. If your containers are set up to automatically pull the latest version of your app from a repository like Docker Hub, then they’ll grab the latest changes the next time they start up.

  4. Restart Containers: After updating your containers, you might need to restart them to apply the changes. This can usually be done with a simple command or through a management tool like Docker Compose.

  5. Test Everything: Finally, it’s always a good idea to test your application after updating to make sure everything still works as expected. Run your tests and do some manual checks to ensure everything is running smoothly.

5. Describe route 53 and process for domain setup

Certainly! Let’s simplify Route 53 and the domain setup process:

Route 53:

What is Route 53?

  • Route 53 is like a GPS system for the internet. It’s a domain name system (DNS) web service provided by AWS that helps route traffic to the right place on the internet. It’s essential for setting up and managing domain names (like yourwebsite.com) and directing traffic to your web servers, load balancers, or other resources. When someone enters your domain name into their web browser, Route 53 translates that domain name into the numeric IP address of your web server so the browser knows where to go. It can also handle things like routing traffic to different places based on geographic location or health checks.

Domain Setup Process:

1. Register a Domain:

  • Choose a domain name registrar, search for an available domain name, and register it. This typically involves providing contact information and paying a registration fee.

2. Set up Route 53 Hosted Zone:

  • In the AWS Management Console, navigate to Route 53 and create a new hosted zone for your domain. This essentially tells Route 53 that you’re going to be managing DNS records for this domain.

3. Update Name Servers:

  • Once your hosted zone is set up, Route 53 will provide you with a set of name servers. You need to go back to your domain register center and update the name servers for your domain to point to the ones provided by Route 53. This tells the internet to use Route 53 for DNS lookups for your domain.

4. Add DNS Records:

  • Now that Route 53 is managing DNS for your domain, you can add DNS records to specify where you want traffic to go. For example, you might add a “CNAME” record to alias your domain to another domain.

5. Test and Verify:

  • After adding DNS records, it’s essential to test and verify that everything is working correctly.

6. Show API access code and error handling, specifically redirect on 403

import java.net.HttpURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class APIClient {
    
    public static void main(String[] args) {
        String apiUrl = "https://api.example.com/data";
        
        try {
            URL url = new URL(apiUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");

            int responseCode = conn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // API call successful, read response
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String inputLine;
                StringBuilder response = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                
                // Process API response here
                System.out.println("API Response: " + response.toString());
            } else if (responseCode == HttpURLConnection.HTTP_FORBIDDEN) {
                // 403 Forbidden error, redirect or handle appropriately
                System.out.println("Error: 403 Forbidden. Redirecting...");
                // Redirect logic goes here
            } else {
                // Other HTTP errors
                System.out.println("Error: HTTP " + responseCode);
            }
            
            conn.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. We create a URL object with the API endpoint and establish a connection (HttpURLConnection).

  2. We set the request method (GET in this case) and check the response code.

  3. If the response code is HTTP_OK (200), we read the response data.

  4. If the response code is HTTP_FORBIDDEN (403), we handle it appropriately. In this example, we print a message and could perform a redirect or other action.

  5. We handle other HTTP errors by printing the error code.

  6. Finally, we disconnect the connection.

7. Describe managing CORS policies through Nginx and Java

The Nginx configuration you provided is already set up to manage CORS policies. It allows all origins (*) for simple requests (GET, POST, PUT, DELETE), and for preflighted requests (OPTIONS), it specifies allowed methods, headers, and responds with a 200 status.

However, if you want to restrict CORS to specific origins rather than allowing all (*), you can replace the * with the desired origin.

For example:

server {
   listen 80;
    listen [::]:80;
    server_name -----.stu.nighthawkcodingsociety.com ; # CHANGE SERVER NAME TO YOUR REGISTERED DOMAIN
    location / {
        proxy_pass http://localhost:8---; # CHANGE PORT TO YOUR UNIQUE PORT
        # Simple requests
        if ($request_method ~* "(GET|POST|PUT|DELETE)") { # Customize Request methods based on your needs
                add_header "Access-Control-Allow-Origin" "http://example.com";
        }
        # Preflighted requests
        if ($request_method = OPTIONS ) {
                add_header "Access-Control-Allow-Origin"  *;
                add_header "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, OPTIONS, HEAD"; # Make sure the request methods above match here
                add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
                return 200;
        }
    }
}

Now for java, we added it to the MvcConfig file so it looks like this:

package com.nighthawk.spring_portfolio;

import org.springframework.context.annotation.*;
import org.springframework.web.servlet.config.annotation.*;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    // set up your own index
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
    }

    /* map path and location for "uploads" outside of application resources
       ... creates a directory outside "static" folder, "file:volumes/uploads"
       ... CRITICAL, without this uploaded file will not be loaded/displayed by frontend
     */
    @Override
    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/volumes/uploads/**").addResourceLocations("file:volumes/uploads/");
    }

    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("https://nighthawkcoders.github.io", "http://localhost:4000", "http://127.0.0.1:4100" );
    }

By overriding the addCorsMappings method and specifying the allowed origins, you can configure CORS policies for your Spring MVC application. This ensures that the application’s resources can be accessed from trusted domains while protecting against unauthorized access from other origins.

8. Describe reverse proxy of server_name to proxy_pass

In Nginx, setting up a reverse proxy involves directing incoming requests to a different server or port based on the server_name specified in the request.

  1. When a request comes to example.com, Nginx knows to handle it because of the server_name directive. The location / block specifies that all requests should be proxied.

  2. Nginx forwards the request to the backend server at http://localhost:8080.

  3. This configuration allows Nginx to act as a reverse proxy, forwarding requests to different backend servers based on the requested domain name. It’s commonly used for load balancing, caching, and routing requests to different applications.

good luck