- What is the difference between FormBased and BasicAuth?
The Difference between FormAuth and BasicAuth is in BasicAuth UserName and Password would be sent everytime when making a request to the server in the header as base64 encoded character. BasicAuth happens at http Protocol level where as Formbased Auth happens at Framework level. - What is the difference between JKS and PKCS12?
JKS is the most common if you stay within the Java world. PKCS#12 isn’t Java-specific, it’s particularly convenient to use certificates (with private keys) backed up from a browser or coming from OpenSSL-based tools.JKS, Java Key Store. You can find this file at sun.security.provider.JavaKeyStore. This keystore is Java specific, it usually has an extension of jks. This type of keystore can contain private keys and certificates, but it cannot be used to store secret keys. Since it’s a Java specific keystore, so it cannot be used in other programming languages.PKCS12, this is a standard keystore type which can be used in Java and other languages. You can find this keystore implementation at sun.security.pkcs12.PKCS12KeyStore. It usually has an extension of p12 or pfx. You can store private keys, secret keys and certificates on this type. -
How safe is Userid and Password in Basic Auth?
UserId and Password in BasicAuth would transferred using base64 encoded UserName and Password attached to Header prepending BasicAuthorization : Basic base64(UserId:Password)
- How POST, PUT and DELETE works in Basic Auth?
In Basic Auth with respect to Spring Security CSRF Token would be used incase CSRF is enabled. If CSRF is disabled Authorization in header would be used
for access. csrf().disable() should be always used incase you are using other than GET method. - What is JSESSIONID?
JSESSIONID which is generated and Stored as Cookie in Postman helps the spring boot app to recognizane whether the User is Authenticated or not. - How Spring Security handles CSRF in client Side when enabled?
Spring Security generates JSESSIONID and XSRF-TOKEN. Both were Set in Cookie. On Subsequent request X-XSRF-TOKEN should be sent in Header for Authorization. - What happens when I delete XSRF token in Cookie?
New Token would be generated based on JSESSIONID in cookie - What happens when I delete XSRF token and in Cookie and try POST, DELETE and PUT over API?
New JSESSIONID would be generated and placed in cookie. For this X-XSRF-TOKEN should be passed in header. - Where is JSESSION stored?
JSESSION is session ID which is stored in Inmemory Database in Server and in a Cookie in Client Side. - What is the default Expiration time of JSESSION Cookie?
30 Minutes - Spring Security Arcitecture?
- Encoding vs Encrytion vs Hashing?
Encoding refers to any transformation of a given input. For example, if we have a function x that reverses a string, function x -> y applied to ABCD produces DCBA.x -> y
Encryption is a particular type of encoding where, to obtain the output, you provide both the input value and a key. The key makes it possible for choosing afterward who should be able to reverse the function (obtain the input from the output). The simplest form of representing encryption as a function looks like this:
(x, k) -> y
where x is the input, k is the key, and y is the result of the encryption. This way, an individual knows the key can use a known function to obtain the input from the output (y, k) -> x. We call this reverse function decryption. If the key used for encryption is the same as the one used for decryption, we usually call it a symmetric key.If we have two different keys for encryption ((x, k1) -> y) and decryption ((y,k2) -> x), then we say that the encryption is done with asymmetric keys. Then (k1,k2) is called a key pair. The key used for encryption, k1, is also referred to as the public key, while k2 is known as the private one. This way, only the owner of the private key can decrypt the data.
Hashing is a particular type of encoding, except the function is only one way. That is,from an output y of the hashing function, you cannot get back the input x. However,there should always be a way to check if an output y corresponds to an input x, so we can understand the hashing as a pair of functions for encoding and matching. If hashing is x -> y, then we should also have a matching function (x,y) ->boolean.
(x,y) ->boolean
Sometimes the hashing function could also use a random value added to the input:
(x, k) -> y. We refer to this value as salt. The salt makes the function stronger, enforcing the difficulty of applying a reverse function to obtain the input from the
result. - Two ways of Configuring Spring Security?
Method 1: Adding userservice and passwordEncoder in configure method(Not Recommended)@Configuration public class ProjectConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("john") .password("12345") .authorities("read") .and() .passwordEncoder(NoOpPasswordEncoder.getInstance()); } }
Method 2: Using Seperate Configuration class for Bean and injecting beans(Recommended Method)
PasswordConfig.java@Configuration public class PasswordConfig { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(10); } }
ApplicationSecurityConfig.java
@Configuration @EnableWebSecurity public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private PasswordEncoder passwordEncoder; @Override @Bean protected UserDetailsService userDetailsService() { UserDetails mugilUsrBuilder = User.builder() .username("Mugil") .password(this.passwordEncoder.encode("password")) .roles("ADMIN") .build(); return new InMemoryUserDetailsManager(mugilUsrBuilder); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception{ httpSecurity.csrf().disable() .authorizeRequests() //Whitelisting URLS .antMatchers("/", "index", "/css/*", "/js/*").permitAll() .antMatchers(HttpMethod.GET,"/api/**").permitAll() .antMatchers(HttpMethod.DELETE,"/api/**").hasRole("ADMIN") .antMatchers(HttpMethod.PUT,"/api/**").hasRole("ADMIN") .antMatchers(HttpMethod.POST,"/api/**").hasRole("ADMIN") .anyRequest() .authenticated() .and() .httpBasic(); } }
- What are the interface methods available in Spring Security?
UserDetailsManager public interface UserDetailsManager extends UserDetailsService { void createUser(UserDetails user); void updateUser(UserDetails user); void deleteUser(String username); void changePassword(String oldPassword, String newPassword); boolean userExists(String username); }
UserDetailsService public interface UserDetailsService { UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; }
UserDetails public interface UserDetails extends Serializable { String getUsername(); String getPassword(); Collection<? extends GrantedAuthority> ➥getAuthorities(); boolean isAccountNonExpired(); boolean isAccountNonLocked(); boolean isCredentialsNonExpired(); boolean isEnabled(); }
AuthenticationProvider public interface AuthenticationProvider { Authentication authenticate(Authentication authentication) throws AuthenticationException; boolean supports(Class<?> authentication); }
Authentication public interface Authentication extends Principal, Serializable { Collection<? extends GrantedAuthority> getAuthorities(); Object getCredentials(); Object getDetails(); Object getPrincipal(); boolean isAuthenticated(); void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; }
FormBased Authentication
Note:The example is for CSRF disabled
- From the above diagram you can see JSESSIONID and HttpStatus.OK is send is response once the credentials are authenticated
- JSESSIONID would be used for Subsequent request
- In the below code we define URL for login and logout.
.formLogin() .loginPage("/login").permitAll().usernameParameter("username").passwordParameter("password") .defaultSuccessUrl("/test", true) .and() .rememberMe() .and() .logout().logoutUrl("/logout").clearAuthentication(true).invalidateHttpSession(true).deleteCookies("JSESSIONID", "remember-me") .logoutSuccessUrl("/login")
- usernameParameter and passwordParameter is the name of the input form element as given in html
- defaultSuccessUrl tells the default page after authentication
- rememberMe allows the User to remember the session in server. The default JSESSIONID time is 30 minutes of inactivity. remember-me session would be active for 2 weeks and allows user to access page for 2 weeks
- logout is similar to login with following
.logout().logoutUrl("/logout") .clearAuthentication(true) .invalidateHttpSession(true) .deleteCookies("JSESSIONID", "remember-me") .logoutSuccessUrl("/login")
JSESSIONID and remember-me as seen in cookie in response after login button clicked
JSESSIONID and remember-me cookie deleted in response after logout button clicked
login.html
<body> <div class="container"> <form class="form-signin" method="post" action="/login"> <table cellpadding="3" cellspacing="3" border="1px solid black" style="border-collapse: collapse"> <tr> <td><label for="username" class="sr-only">Username</label></td> <td><input type="text" id="username" name="username" class="form-control" placeholder="Username" required="" autofocus=""></td> </tr> <tr> <td><label for="password" class="sr-only">Password</label></td> <td><input type="password" id="password" name="password" class="form-control" placeholder="Password" required=""></td> </tr> <tr> <td><label for="remember-me" class="sr-only">Remember Me?</label></td> <td><input type="checkbox" id="remember-me" name="remember-me" class="form-control"></td> </tr> <tr> <td colspan="2" align="center"><button class="btn btn-lg btn-primary btn-block" type="submit">Login</button></td> </tr> </table> </form> </div> </body>
test.html
You have been Logged In <form class="form-signin" method="get" action="/logout"> <button class="btn btn-lg btn-primary btn-block" type="submit">Logout</button> </form>
@Override protected void configure(HttpSecurity httpSecurity) throws Exception{ httpSecurity .csrf().disable() .authorizeRequests() .antMatchers("/", "index", "/css/*", "/js/*").permitAll() .antMatchers("/api/**").hasRole("ADMIN") .anyRequest() .authenticated() .and() .formLogin() .loginPage("/login").permitAll().usernameParameter("username").passwordParameter("password") .defaultSuccessUrl("/test", true) .and() .rememberMe() .and() .logout().logoutUrl("/logout").clearAuthentication(true).invalidateHttpSession(true).deleteCookies("JSESSIONID", "remember-me") .logoutSuccessUrl("/login"); }
JWT implementation 1
- Advantage of JSON token is it could be used form multiple platforms like PC, Mobile for accessing secured pages
- User enters user credentials(Username and Password) and gets authenticated.
- User Credentails are validated and token is generated
- On Subsequent request from APIs tokens are used in header for authorization
- Tokens are generated and verified by filters.There would be line of filters on way from request to API
- JwtUsernameAndPasswordAuthenticationFilter generates the Token after authentication
- JwtTokenVerifierFilter authorizes the user in each and every request by interpreting the token in the request header
JwtTokenVerifierFilter.java
public class JwtTokenVerifierFilter extends OncePerRequestFilter { private final SecretKey secretKey; private final JwtConfig jwtConfig; public JwtTokenVerifierFilter(SecretKey secretKey, JwtConfig jwtConfig) { this.secretKey = secretKey; this.jwtConfig = jwtConfig; } @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { String authorizationHeader = httpServletRequest.getHeader(jwtConfig.getAuthorizationHeader()); if(Strings.isNullOrEmpty(authorizationHeader) || !authorizationHeader.startsWith("Bearer ")){ filterChain.doFilter(httpServletRequest, httpServletResponse); return; } String token = authorizationHeader.replace(jwtConfig.getTokenPrefix(), ""); try{ Jws<Claims> claimsJws = Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token); Claims body = claimsJws.getBody(); String username = body.getSubject(); List<Map<String, String>> authorities = (List<Map<String, String>>)body.get("authorities"); Set<SimpleGrantedAuthority> simpleGrantedAuth = authorities.stream() .map(m -> new SimpleGrantedAuthority(m.get("authority"))) .collect(Collectors.toSet()); Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, simpleGrantedAuth); SecurityContextHolder.getContext().setAuthentication(authentication); }catch (JwtException e){ throw new IllegalStateException(String.format("Token %s cannot be Trusted", token)); } filterChain.doFilter(httpServletRequest, httpServletResponse); } }
JwtUsernameAndPasswordAuthenticationFilter.java
public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final AuthenticationManager authenticationManager; private final JwtConfig jwtConfig; private final SecretKey secretKey; public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authenticationManager, JwtConfig jwtConfig, SecretKey secretKey) { this.authenticationManager = authenticationManager; this.jwtConfig = jwtConfig; this.secretKey = secretKey; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { try { UsernameAndPasswordAuthenticationRequest authenticationRequest = new ObjectMapper() .readValue(request.getInputStream(), UsernameAndPasswordAuthenticationRequest.class); Authentication authentication = new UsernamePasswordAuthenticationToken( authenticationRequest.getUsername(), authenticationRequest.getPassword() ); Authentication authenticate = authenticationManager.authenticate(authentication); return authenticate; } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { String token = Jwts.builder() .setSubject(authResult.getName()) .claim("authorities", authResult.getAuthorities()) .setIssuedAt(new Date()) .setExpiration(java.sql.Date.valueOf(LocalDate.now().plusWeeks(jwtConfig.getTokenExpirationAfterDays()))) .signWith(secretKey) .compact(); response.addHeader(jwtConfig.getAuthorizationHeader(), jwtConfig.getTokenPrefix() + token); } }
Wisdom Pearls from Devops Pipeline Creation
Irrespective of Devops tool you use the below are the generic steps which would be carried out from
code changes to deployment in environment
Build Pipeline
- Step 1-Preparation of Environment for Build. This includes initializing buildno, commitid, buildname which would be used internally by the devops tool
- Step 2-Build Script for creating artifact
- Step 3-Copy Script for Copying Artifact to Staging Directory. Environment Directory(Directory on which new artifact would be created after build) to Staging Directory(Directory from which artifact would be created to drop location)
- Step 4-Publishing Script – to publish the artifact to DROP location. This is like common place which would be refered by release pipeline
Release Pipeline
- From DROP location the artifact would be picked. For this Trigger should be used.
- Trigger should detect the availability of new release and in which branch should be checked for new release.
- New artifact should be pushed to Deployment Environment(Dev, Testing or Prod). For this push Command should be used
- There should be agent to carry out the above tasks
Wiremock Interview Questions
- Wiremock Intro?
- Serves canned responses to particular requests (stubbing), and that captures incoming requests so that they can be checked later (verification).
- External to application code which helps in the testing app in Dev and ST(System Testing) environment
- Helps in testing negative Scenarios like network latency
- Language Agnostic and production like testing
- How to differentiate Positive and Negative Scenarios?
It could be done based on method(GET, POST, DELETE, PUT), Path(/employee, /success) and based on Parameter.GET /employee?name=mugil Method - GET Path - /employee Params - name
- How priority of Stub Response is selected when Paths overlap?
Stub is lowest no in priority would be selected.//Priority 1 wireMockServer.stubFor(get("/welcome") .atPriority(1) .willReturn(aResponse() .withBody("Welcome with Priority 1"))); //Priority 2 wireMockServer.stubFor(get("/welcome") .atPriority(2) .willReturn(aResponse() .withBody("Welcome with Priority 2")));
Output
Welcome with Priority 1
- What is advantage of using Wiremock as Standalone?
- Less dependency on Environment
- Useful for Load Testing
- Can be used by non JVM environment
- Can run remotely
- What are possible defects which could happen in application?
- Timeout
- Server Error
- Invalid Response
UML Class Relationships
Relationships between Classes
- Association
- Composition
- Aggregation
- Generalization
- Realization
- Dependency
Association(Has-A Relationship)
- Association is a relationship between two separate classes that establish through their objects. Each objects have their own life-cycle and there is no owner. Association can be one-to-one, one-to-many, many-to-one, many-to-many. It isn’t a “has-a” relationship and only means that the objects “know” each other
class Bank { private String name; Bank(String name){ this.name = name; } public String getBankName(){ return this.name; } } class Employee { private String name; Employee(String name){ this.name = name; } public String getEmployeeName(){ return this.name; } } class Association { public static void main (String[] args) { Bank bank = new Bank("Axis"); Employee emp = new Employee("Mani"); System.out.println(emp.getEmployeeName() + " is employee of " + bank.getBankName()); } }
In above example two separate classes Bank and Employee are associated through their Objects. Bank can have many employees, So it is a one-to-many relationship.
- Aggregation and Composition are subsets of association meaning they are specific cases of association.Both of them conveys a has-a relationship to strong and weak degree
- Composition(Strong has-a relationship)
- Aggregation(Weak has-a relationship)
- has-a relationship simply means that an instance of one class has a reference to an instance of another class or an other instance of the same class
- Composition denotes a has-a relationship of Strong degree. Relationship among class members are strong.Classes which are grouped by Composition doesnot makes sense when interpreted seperately. I.E. when Person, Heart, Hand were seperated Heart and Hand doesnot make much sense.Objects in a composition relationship cannot, conceptually, exist in isolation. If we destroy the owner object, its members also will be destroyed with it
public class WebPage { private final PageHeader header; private final PageBody pageBody; public WebPage(PageHeader header, PageBody pageBody) { this.header = header; this.pageBody = pageBody; } } class PageHeader { private String title; private String charset; } class PageBody { private String body; }
- Aggregation denotes a has-a relationship of Weak degree.Relationship among class members are weak. I.E. When trees were seperated from City Class Trees still make perfect sense and stand on it own.Objects on both sides of an aggregation relationship can exist in isolation.
public class Team { private List<Player> players = new ArrayList<>(); public void addPlayer(Player player) { this.players.add(player); player.setTeam(this); } public void removePlayer(Player player) { this.players.remove(player); player.setTeam(null); } } class Player { private String name; private int age; public void setTeam(Team team) { this.team = team; } }
- In UML notation, a composition is denoted by a filled diamond, while aggregation is denoted by an empty diamond, which shows their obvious difference in terms of strength of the relationship.
Composition vs Aggregation
Generalization(Is-A Relationship)
- In inheritance, a child of any parent can access, update, or inherit the functionality as specified inside the parent object. A child object can add its functionality to itself as well as inherit the structure and behavior of a parent object.This type of relationship collectively known as a generalization relationship.
-
public class Vehicle { } class Truck extends Vehicle { } class Boat extends Vehicle { }
Realization(interfaces)
- In a realization relationship of UML, one entity denotes some responsibility which is not implemented by itself and the other entity that implements them. This relationship is mostly found in the case of interfaces.
- Realization is a specialized abstraction relationship between two sets of model elements, one representing a specification (the supplier) and the other represents an implementation of the latter (the client).
-
class Hyndai implements Car { . . }
Dependency
- In a dependency relationship, as the name suggests, two or more elements are dependent on each other.Dependency relationships exist when classes depend on each other in such a way that a change to one class may affect the other, such as when one class accepts an instance of another class as parameter to a method.
-
Dependency –> A references B (as a method parameter or return type)
public class A { private C c; public void myMethod(B b) { b.callMethod(); } }
- Dependency relationships are represented by arrows on dashed lines. Dependency represents the weakest of relationship
- A dependency relationship can exist when we have a Library class that manages Book objects. Since the Library class has a method that returns a Book, changes to the Book class could result in changes to the Library class (based on how Book objects are created).
public class Library { public Book findBook(String name) { //Do some book stuff. return new Book(); } } class Book { private String name; private String author; }
- A dependency typically (but not always) implies that an object accepts another object as a method parameter, instantiates, or uses another object. A dependency is very much implied by an association.
Class Diagram Basics
UML Diagrams
- Structure Diagrams
- Class Diagrams
- Deployment Diagrams
- Behaviour Diagrams
- Use Case Diagrams
- Activity Diagrams
- State Machine Diagrams
- Interaction Diagrams
- Sequence Diagrams
Class Diagrams Basics
- Class Contains ClassName, Attributes and Operations
- Class Names are written in Bold or Italic if class is Abstract
-
Attributes
<Visibility><Name>:<Type>=<Defaultvalue><{Modifier}>
Visibility + - Public - - Private ~ - Package # - Protected Name Name of Variable Type Integer, String, Boolean DefaultValue Value by DefaultValue Modifier ReadOnly
-
Operations
<Visibility><Name>(<ParameterList>):<ReturnType>
Visibility + - Public - - Private ~ - Package # - Protected Name Name of Operations ParameterList List of Parameters - Comma Seperarted or Empty ReturnType Integer, String or Another Class
- Static Elements – Static Operations and Attributes are underlined in UML Diagram
Relationships
Practical UML Wisdom Pearls
Relationship | Depiction | Interpretation | Example |
---|---|---|---|
Dependency | A depends on B This is a very loose relationship and so I rarely use it, but it’s good to recognize and be able to read it. |
||
Association | An A sends messages to a B Associations imply a direct communication path. In programming terms, it means instances of A can call methods of instances of B, for example, if a B is passed to a method of an A. |
||
Aggregation | An A is made up of B This is a part-to-whole relationship, where A is the whole and B is the part. In code, this essentially implies A has fields of type B. |
||
Composition | An A is made up of B with lifetime dependency That is, A aggregates B, and if the A is destroyed, its B are destroyed as well. |
Are Dependency Injection and Depencency are Different?
Yes, They are. The Closest one to DI is aggregation. In Aggregation, we deal with direct objects. i.e. objects which maintain a state, life-cycle, etc.
But in Dependency Injection, we focus on class level interactions. This is diverged with pure OOP practice. Actually, in DI we tend to inject stateless classes(worker classes) into some other classes. Though they look like objects they are actually just stateless classes that are being injected. And instances of that class can stand independently too.
Assume a stateless worker class called StringUtils. It can be injected into classes called NounUtils, VerbUtils, etc. And also instances of StringUtils can also exist.
Which one is Close to Dependency(Not DI)
An association almost always implies that one object has the other object as a field/property/attribute (terminology differs).
A dependency typically (but not always) implies that an object accepts another object as a method parameter, instantiates, or uses another object. A dependency is very much implied by an association.
Association --> A has-a C object (as a member variable) Dependency --> A references B (as a method parameter or return type)
public class A { private C c; public void myMethod(B b) { b.callMethod(); } }
Simple Example of Dependency, Association, Aggregation and Composition
Dependency (references)
It means there is no conceptual link between two objects. e.g. EnrollmentService object references Student & Course objects (as method parameters or return types)
public class EnrollmentService { public void enroll(Student s, Course c){} }
Association (logical relationship) It means there is almost always a link between objects (they are associated). Order object has a Customer object
public class Bank { } public class Employee{ } class Association { public static void main (String[] args) { Bank bank = new Bank("Axis"); Employee emp = new Employee("Mani"); System.out.println(emp.getEmployeeName() + " is employee of " + bank.getBankName()); } }
Aggregation (has-a relationship of weak degree)
Special kind of association where there is whole-part relation between two objects. they might live without each other though.
public class PlayList { private List<Song> songs; }
OR
public class Computer { private Monitor monitor; }
Note: the trickiest part is to distinguish aggregation from the normal association. Honestly, I think this is open to different interpretations.
Composition (has-a relationship of strong degree+ ownership or Part-Of)
Special kind of aggregation. An Apartment is composed of some Rooms. A Room cannot exist without an Apartment. when an apartment is deleted, all associated rooms are deleted as well.
public class Apartment{ private Room bedroom; public Apartment() { bedroom = new Room(); } }
Test Driven Development – Getting Started
Basics
-
Fail(Red)->Pass(Green) ->Refactor
- New Test would fail
- Write minimum code to pass
- Perform refactor and check again
- Test cases should be written for Single Logic and should test business logic
-
@Test
Junit5 Fundementals
Junit 5 = Platform + Jupiter + Vintage
- Platform = Engine + Runner + Launcher
- All the Class files needed for Coding Test Cases
- Provides Support for Junit3 and 4
Adding Dependency in pom.xml for Junit 5
JUnit 5 Platform
includes junit-jupiter-api + junit-platform-engine
<dependencies> [...] <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.4.0</version> <scope>test</scope> </dependency> [...] </dependencies>
If you want to write and execute JUnit 3 or 4 tests via the JUnit Platform add the Vintage Engine to the dependencies
<dependencies> [...] <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <version>5.4.0</version> <scope>test</scope> </dependency> [...] </dependencies>