// 15 Essential Spring Security Interview Questions
Spring Security is an access-control and authentication framework that is both robust and very flexible. It is popular among developers and now is the de-facto standard for protecting Spring-based apps. Spring Security is a framework for providing Java applications with both authentication and permission. The actual value of Spring Security, like all Spring projects, is in how readily it can be modified to meet specific requirements.
There are a lot of great opportunities for Spring Security engineers right now, but getting the best ones will require you to be well prepared for interviews. So, in this article, we've compiled a list of carefully crafted Spring Security interview questions to assist you in acing your interviews. Not only that but these questions and answers can help you learn about new aspects of Spring Security even if you aren't preparing for interviews. So let's get started.
Looking for Freelance Spring Security Developers? Build your product with Flexiple's top-quality talent.
Hire a Spring Security DeveloperHire NowDigest authentication is an accepted technique for having a web server negotiate credentials with a user's web browser. Before sending sensitive information, such as a user's online banking transaction history, this can be used to verify the user's identity.
There are numerous ways to authenticate RESTful web services, but more sophisticated authentication techniques include digest authentication. Sending credentials in an encrypted form applies a hash function to the username, password, HTTP method, and URL. It produces more complicated cryptographic results by utilizing the hashing technique, which is difficult to decode.
Here is a basic syntax of digest authentication:
Hash1=MD5(username:realm:password)
Hash2=MD5(method:digestURI)
response=MD5(Hash1:nonce:nonceCount:cnonce:qop:Hash2)
//Example , this got generated by running this example
Authorization: Digest username="TestAdmin", realm="admin-digest-realm",
nonce="MTYwMDEwMTUyMDM4OToxM2M1Y2I4MGFjMjk4OGI1ODQzZjc3NDUzOGFlMjZjYw==",
uri="/admin/hello?name=User", response="2f080edbec53be2bdf3853d477e4a543",
qop=auth, nc=00000002, cnonce="11ecd9bf947dbcf4"
Note: Commonly asked Spring Security interview questionA successful CSRF attack involves the attacker tricking the victim user into performing an unintentional action. It gives an attacker the ability to partially get around the same-origin policy, which is meant to stop various websites from interfering with one another. For instance, they might need to do this to make a money transfer, change their password, or update their email address on file.
In addition, the attacker might take complete control of the user's account depending on the nature of the action. For example, the attacker might be able to fully control all the data and functionality of the application if the compromised user has a privileged role within it.
Examining a practical example is the best way to comprehend a CSRF attack. For example, assume that your bank's website offers a form that enables money transfers from the user who is currently logged in to another bank account. The transfer form, for instance, might resemble the example shown above.
The corresponding HTTP request might look like this:
POST /transfer HTTP/1.1
Host: bank.example.com
Cookie: JSESSIONID=randomid
Content-Type: application/x-www-form-urlencoded
amount=100.00&routingNumber=1234&account=9876
Let's say you log in to your bank's website and then visit a malicious website without logging out. An HTML page with the following format can be found on the malicious website:
<form method="post"
action="https://bank.example.com/transfer">
<input type="hidden"
name="amount"
value="100.00"/>
<input type="hidden"
name="routingNumber"
value="evilsRoutingNumber"/>
<input type="hidden"
name="account"
value="evilsAccountNumber"/>
<input type="submit"
value="Win Money!"/>
</form>
You press the submit button because you enjoy winning money. But unfortunately, you unintentionally sent $100 to a malicious user during the process (See the input type is defined as hidden in the form). This occurs because the malicious website cannot see your cookies, and the bank-related cookies are still sent with the request.
Even worse, JavaScript could have automated the entire procedure. This implies that you weren't even required to press the button. It might also occur if a user visits a legitimate website that has been the victim of an XSS attack.
Note: Commonly asked Spring Security interview questionThe configuration class for the Web Security Configuration would be the most critical component of the project. In our application, Spring Security is configured using the @EnableWebSecurity directive. Swagger's URL needs to be set up so all users can access it.
The password can be encrypted using BCryptPasswordEncoder, and user credentials can be saved using inMemoryAuthentication.
The OpenApi can offer a variety of security schemes. We can define several components in our application, including Scheme, type, header, etc.
Now, let us write code for @EnableWebSecurity, for which we will need some imports first.
package com.codeusingjava.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
We can now write the main code where we take the password to be 123:
@EnableWebSecurity
@SecurityScheme(name="codeusingjava", scheme="basic", type=SecuritySchemeType.HTTP, in=SecuritySchemeIn.HEADER)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("nj")
.password("{bcrypt}$2a$10$BagghBQvnxcVuhHyXc9g9.fM6s109FakmyF4tPAoOMRkjqKsg1xl.") //123
.authorities("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/swagger-ui/**","/v3/api-docs/**").permitAll()
.anyRequest().authenticated()
.and().httpBasic();
http.csrf().disable();
}
}
Note: Commonly asked Spring Security interview questionOne of the most crucial frameworks for creating enterprise applications is Spring Security. It offers some vital features like user authentication - which establishes your identity, and authorization - which determines whether you have the right to fetch a specific request. Let's think about a simple user and administrator login project.
In this project, defining the MySQL default schema would be crucial. The Authority class uses the username from the User class as a foreign key.
Making a Project Object Model file, which will include the project configuration information, is the first step if we use Maven.
Additionally, all database-related configurations will be made in an application.properties file. We can use the default MySQL schema, which defines the users and the authorities assigned to them, to create the schema file for the database configuration.
This is a sample table:
CREATE TABLE UsersTable(
username VARCHAR(50) NOT NULL PRIMARY KEY,
PASSWORD VARCHAR(200) NOT NULL,
email VARCHAR(100) NOT NULL,
enabled BOOLEAN NOT NULL
);
Next, we'll develop the spring security configuration class, wherein the configure() method is used for all HttpSecurity configurations. The fundamental controller class will also need to be created. To obtain information about users currently logged in, use principal in spring security.
An instance of the SecurityContext interface makes up the object returned by the getContext() function. In Spring Security, the getPrincipal() method typically returns the UserDetails object, which contains all the information about the logged-in user.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String logged_in_username = ((UserDetails)principal).getUsername();
} else {
String logged_in_username = principal.toString();
}
Authorities with the ROLE prefix are Spring roles. It's also important to understand that authorities are designed for more precise management while roles are intended for broad sets of permissions. But that is just one application. The developer is in charge of carrying it out in practice. In the code example below, authorities are used to map to authorization groups.
@PreAuthorize("hasAuthority('Admin')")
@RequestMapping("/fetch-users")
@ResponseBody
public String protectedUserPage() {
return "TechGeekNext User";
}
------------------------------------------
@PreAuthorize("hasRole('admin')")
@RequestMapping("/fetch-users")
public String protectedUserPage() {
return "TechGeekNext User";
}
An important thing to keep in mind is that the authority name in the claim must start with ROLE_ to use hasRole(). If you created the ROLE ADMIN group and included your user, you might use hasRole('ADMIN') as an example.
The @Secured annotation specifies a set of security configuration parameters for business methods. After the security requirements (roles/permissions, etc.) have been established using the @Secured annotation, only users with the appropriate roles and permissions can call a method.
If someone tries to call a method without having the required roles or permissions, an AccessDeniedException will be thrown.
Here is a simple example of the @Secured annotation:
@Secured({"ROLE_ADMIN"})
public String showTrades() {
return "secure/trades";
}
The @Secured is a holdover from earlier releases of Spring. Its lack of support for Spring EL expressions is a limitation.
Thus, it is preferable to use the @PreAuthorize annotation, which supports Spring EL, instead of the @Secured annotation. As an illustration, the following code can be written using @PreAuthorize:
@PreAuthorize("hasRole('ROLEADMIN')")
public String showTrades() {
return "secure/trades";
}
On the other hand, the @RolesAllowed JSR 250 annotation lists the security roles that can access a method or a selection of methods in an application. For those unfamiliar, JSR 250 aims to define standard annotations for the Java platform.
Note: Commonly asked Spring Security interview questionThe Spring Security framework applies several security concerns using a series of filters, such as
- intercepting the request,
- identifying (lack of) authentication,
- rerouting to the authentication entry point,
- or passing the request to the authorization service before letting the request either hit the servlet or throw a security exception (unauthenticated or unauthorized).
The security filter chain is created by the DelegatingFitlerProxy, which joins these filters. Because of this, when we declare DelegatingFilterProxy as a filter in web.xml, you see the name "springSecurityFilterChain."
To secure URLs in your Java web application using Spring security, you must use the intercept-URL. It also specifies what kind of access a user must have to view a page or URL.
The login and login-error screens, as well as some public website areas, require unauthenticated or anonymous access, both of which can be obtained by intercepting a few URL patterns. But then, everything else is ROLE_USER, and there is frequently an admin section for administrative tasks like creating roles, users, or permissions. Unfortunately, due to their minimal and basic security requirements, most web applications that use Spring Security only have a few intercept URLs.
Here is one of the examples of basic Spring security using intercept URL:
<http realm="Contacts Realm" use-expressions="false">
<intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/admin/*" access="ROLE_ADMIN"/>
<intercept-url pattern="/trade/*" access="ROLE_TRADER"/>
<intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN,ROLE_TRADER"/>
<http-basic/>
</http>
You can see that index.jsp and admin.jsp is allowed to be accessed without authentication. However, anything with admin in the URL requires ROLE_ADMIN access, and any URL with trade-in requires ROLE_TRADER access.
Spring also allows expression-based access control from Spring 3.0 but is not mandatory, giving you more power to implement complex access mechanisms.
Note: Commonly asked Spring Security interview questionAfter the Spring Boot application has started, you can run code using the Application Runner and Command-Line Runner interfaces. You can use these interfaces to carry out any actions as soon as the application launches. The code snippet, as mentioned earlier, demonstrates how to incorporate the Application Runner interface into the main class file.
Application Runner: After the Spring Boot application has launched, code is executed using the Application Runner interface. You use it when you want to run some code precisely before the launch of the application is complete. Additionally, by using service discovery, we can use Application Runners to obtain data from other microservices.
The code above shows the syntax for basic authentication in Spring Security. By including a username and password in the request and using the HTTP [Authorization] header, basic authentication enables authentication and grants access to the resource.
Spring Security's InMemoryUserDetailsManager implements UserDetailsService to support username/password-based authentication stored in memory. InMemoryUserDetailsManager provides management of UserDetails by implementing the UserDetailsManager interface. User details-based authentication is used when Spring Security is configured to accept a username and password for authentication.
Let us take a look at an example:
@Bean
public UserDetailsService users() {
UserDetails user = User.builder()
.username("user")
.password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
.roles("USER")
.build();
UserDetails admin = User.builder()
.username("admin")
.password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
.roles("USER", "ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
We employ the Spring Boot CLI to encrypt the password in this example. Although the passwords in the example above are kept in a secure format, the user interface is far from ideal when a user first logs in.
Java 8 or a later Runtime Environment is needed for Spring Security.
You don't need to add unique configuration files to your Java Runtime Environment because Spring Security aims to function independently. You don't need to install Spring Security in standard classpath locations or configure a special Java Authentication and Authorization Service (JAAS) policy file, for example.
Similarly, you do not need to include Spring Security in a server classloader or place special configuration files anywhere if you use an EJB or Servlet Container. Your application contains all the necessary files.
This design allows for the most flexible deployment times because your target artifact (whether a JAR, WAR, or EAR) can be copied from one system to another and start working immediately.
Caching is disabled by default in Spring Security to safeguard user content. We don't want a malicious user to be able to use the back button to view sensitive information, for instance, if a user authenticates to view sensitive information and then logs out. The following describes a cache-control header that is automatically sent:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
This implies that the SecurityContext is lost when work is done on a new Thread. Users will find this to be much simpler, thanks to the infrastructure that Spring Security offers. Working with Spring Security in multi-threaded environments is made possible by low-level abstractions provided by Spring Security.