Posting a request of a DTO which has a file in it.
/** * User @ModelAttribute instead of @RequestBody * @param userCreateDTO * @return */ @ApiOperation(value = "Post file in DTO") @PostMapping(value="/withdto") public ResponseEntity<User> postWithDTO(@ApiParam(name = "user", required = true, value = "user") @ModelAttribute UserCreateDTO userCreateDTO){ log.info("postWithDTO(..)"); log.info("name: {}, email: {}",userCreateDTO.getName(),userCreateDTO.getEmail()); log.info("file size:{}, name:{}", userCreateDTO.getFile().getSize(),userCreateDTO.getFile().getOriginalFilename()); return new ResponseEntity<>(userService.create(new User(null,null,userCreateDTO.getName(),userCreateDTO.getEmail(),null)), HttpStatus.OK); }
Using @RequestPart
/** * post json object with a file using @RequestPart */ @ApiOperation(value = "Post file with RequestPart") @PostMapping("/withrequestpart") public ResponseEntity<User> postWithRequestPart(@ApiParam(name = "file", required = true, value = "file") @RequestPart(value = "file", required = true) MultipartFile file, @RequestPart("user") User user){ log.info("postWithRequestPart(..)"); log.info(user.toJson()); log.info("file size:{}, name:{}", file.getSize(),file.getName()); return new ResponseEntity<>(userService.create(user), HttpStatus.OK); }
Frontend Code
var formData = new FormData(); formData.append("file", document.forms["userForm"].file.files[0]); formData.append('user', new Blob([JSON.stringify({ "firstName": document.getElementById("firstName").value, "lastName": document.getElementById("lastName").value })], { type: "application/json" })); fetch('/upload', { method: 'post', body: formData }).then(function (response) { if (response.status !== 200) { alert("There was an error!"); } else { alert("Request successful"); } }).catch(function (err) { alert("There was an error!"); });;August 31, 2019
Aurora is a fully managed relational database engine that’s compatible with MySQL and PostgreSQL. It can deliver up to five times the throughput of MySQL and up to three times the throughput of PostgreSQL without requiring changes to most of your existing applications.
When connecting to Aurora instance, it is recommended that you use a custom endpoint(endpoint that does not change) instead of the instance endpoint in such cases. Doing so simplifies connection management and high availability as you add more DB instances to your cluster.
For clusters where high availability is important, where practical use the cluster endpoint for read-write connections and the reader endpoint for read-only connections. These kinds of connections manage DB instance failover better than instance endpoints do.
DB instance types: Aurora supports two types of instance classes: Memory-Optimized and Burstable Performance.
With Aurora Serverless, you can create a database endpoint without specifying the DB instance class size. You set the minimum and maximum capacity. With Aurora Serverless, the database endpoint connects to a proxy fleet that routes the workload to a fleet of resources that are automatically scaled. Because of the proxy fleet, connections are continuous as Aurora Serverless scales the resources automatically based on the minimum and maximum capacity specifications. Database client applications don’t need to change to use the proxy fleet. Aurora Serverless manages the connections automatically. Scaling is rapid because it uses a pool of “warm” resources that are always ready to service requests. Storage and processing are separate, so you can scale down to zero processing and pay only for storage.
You can specify the minimum and maximum ACU. The minimum Aurora capacity unit is the lowest ACU to which the DB cluster can scale down. The maximum Aurora capacity unit is the highest ACU to which the DB cluster can scale up. Based on your settings, Aurora Serverless automatically creates scaling rules for thresholds for CPU utilization, connections, and available memory.
Aurora Serverless manages the warm pool of resources in an AWS Region to minimize scaling time. When Aurora Serverless adds new resources to the Aurora DB cluster, it uses the proxy fleet to switch active client connections to the new resources. At any specific time, you are only charged for the ACUs that are being actively used in your Aurora DB cluster.
Aurora clusters across regions
Do you use Spring in a unit test?
You don’t necessarily need spring for unit tests.
@RunWith(SpringRunner.class) @SpringBootTest public class SidecarApiNotificationApplicationTests { @Autowired UserService userService; @Test public void testLoadAllUsers() { List<User> users = userService.getAllUsers(); assertNotNull(users); } }
What type of tests typically use Spring?
How can you create a shared application context in a JUnit integration test?
Spring’s integration testing support has the following primary goals:
To access the Context with the TestContext Framework in JUnit, two options to access the managed application context.
1. The first option is by implementing the ApplicationContextAware
interface or using @Autowired
on a field of the ApplicationContext
type. You can specify this in the @RunWith
annotation at the class level.
@RunWith(SpringRunner.class) @ContextConfiguration(classes = BankConfiguration.class) public class AccountServiceJUnit4ContextTests implements ApplicationContextAware { }
SpringRunner
class, which is an alias for SpringJUnit4ClassRunner
, is a custom JUnit runner helping to load the Spring ApplicationContext by using @ContextConfiguration(classes=AppConfig.class)
. In JUnit, you can simply run your test with the test runner SpringRunner
to have a test context manager integrated.@RunWith(SpringRunner.class) @ContextConfiguration(classes = BankConfiguration.class) public class AccountServiceJUnit4ContextTests { }
2. The second option to access the managed application context is by extending the TestContext support class specific to JUnit: AbstractJUnit4SpringContextTests
.
Note that if you extend this support class, you don’t need to specify SpringRunner in the @RunWith
annotation because this annotation is inherited from the parent.
@ContextConfiguration(classes = BankConfiguration.class) public class AccountServiceJUnit4ContextTests extends AbstractJUnit4SpringContextTests { }
When and where do you use @Transactional in testing?
defaultRollback
attribute of @TransactionConfiguration
.@Rollback
annotation, which requires a Boolean value, @Rollback(false)
, This is equivalent to another annotation introduced in Spring @Commit
.How are mock frameworks such as Mockito or EasyMock used?
Mockito lets you write tests by mocking the external dependencies with the desired behavior. Mock objects have the advantage over stubs in that they are created dynamically and only for the specific scenario tested.
Steps of using Mockito:
public class SimpleReviewServiceTest { private ReviewRepo reviewMockRepo = mock(ReviewRepo.class); // (1) private SimpleReviewService simpleReviewService; @Before public void setUp(){ simpleReviewService = new SimpleReviewService(); simpleReviewService.setRepo(reviewMockRepo); //(2) } @Test public void findByUserPositive() { User user = new User(); Set<Review> reviewSet = new HashSet<>(); when(reviewMockRepo.findAllForUser(user)).thenReturn(reviewSet);// (3) Set<Review> result = simpleReviewService.findAllByUser(user); // (4) assertEquals(result.size(), 1); //(5) } }
Mockito with Annotations
@Mock
: Creates mock instance of the field it annotates@InjectMocks
has a behavior similar to the Spring IoC, because its role is to instantiate testing object instances and to try to inject fields annotated with @Mock
or @Spy
into private fields of the testing object.@RunWith(MockitoJUnitRunner.class)
to initialize the mock objects.MockitoAnnotations.initMocks(this)
in the JUnit @Before
method.public class MockPetServiceTest { @InjectMocks SimplePetService simplePetService; @Mock PetRepo petRepo; @Before public void initMocks() { MockitoAnnotations.initMocks(this); } @Test p ublic void findByOwnerPositive() { Set<Pet> sample = new HashSet<>(); sample.add(new Pet()); Mockito .when(petRepo.findAllByOwner(owner)) .thenReturn(sample); Set<Pet> result = simplePetService.findAllByOwner(owner); assertEquals(result.size(), 1); } } }
Mockito in Spring Boot
@MockBean
@SpringBootTest
), this feature is automatically enabled.How is @ContextConfiguration used?
In spring-test
library, @ContextConfiguration
is a class-level annotation, that defines the location configuration file, which will be loaded for building up the application context for integration tests.
if @ContextConfiguration
is used without any attributes defined, the default behavior of spring is to search for a file named {testClassName}-context.xml
in the same location as the test class and load bean definitions from there if found.
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes={KindergartenConfig.class, HighschoolConfig.class}) @ActiveProfiles("kindergarten") public class ProfilesJavaConfigTest { @Autowired FoodProviderService foodProviderService; }
Spring Boot provides a @SpringBootTest
annotation, which can be used as an alternative to the standard spring-test @ContextConfiguration
annotation when you need Spring Boot features. The annotation works by creating the ApplicationContext used in your tests through SpringApplication.
@RunWith(SpringRunner.class) @SpringBootTest(properties = "spring.main.web-application-type=reactive") public class MyWebFluxTests { }
How does Spring Boot simplify writing tests?
spring-boot-starter-test
pulls in the following all within test scope:
testCompile('org.springframework.boot:spring-boot-starter-test')
What does @SpringBootTest do? How does it interact with @SpringBootApplication and @SpringBootConfiguration?
Spring Boot features like loading external properties and logging, are available only if you create ApplicationContext using the SpringApplication
class, which you’ll typically use in your entry point class. These additional Spring Boot features won’t be available if you use @ContextConfiguration
.
@SpringBootTest
uses SpringApplication behind the scenes to load ApplicationContext so that all the Spring Boot features will be available.
@ContextConfiguration
, it uses org. springframework.boot.test.context.SpringBootContextLoader
by default.@Configuration
classes are used.org.springframework.boot.test.web.client.TestRestTemplate
bean for use in web tests that use a fully running container.@RunWith(SpringRunner.class) @SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {"app.port=9090"}) public class CtxControllerTest { }How to define a testing class in Spring?
In order to define a test class for running in a Spring context, the following have to be done:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
in order to tell the runner class where the bean definitions come from@Autowired
to inject beans to be tested.
1. What does REST stand for?
REpresentational State Transfer. It is for stateless communication between a client(Web, Mobile, Server, etc) and a server.
2. What is a resource?
An entity, model, or data that you interact with. It is basically any information, like data, Json, xml, html, file, image, etc.
Resource can be identified by a Uniform Resource Identifier (URI).
3. What does CRUD mean?
C – create
R – read
U – update
D – delete
4. Is REST secure? What can you do to secure it?
REST is not secure by default.
To secure it, can use:
We also use Spring Security to secure our REST API.
5. What are safe REST operations?
Safe methods are HTTP methods that do not modify resources. Spring Security implements CSRF protection with a synchronizer token. Statechanging requests(not safe methods) will be intercepted and checked for a CSRF token.
Not Safe:
6. What are idempotent operations? Why is idempotency important?
Idempotent means you can repeat these operations over and over again, but the end result should be the same.
Idempotency operations:
Idempotency is important for understanding the limits of effect some operation has on resources.
7. Is REST scalable and/or interoperable?
Because of the stateless nature of REST, it is easily scalable and due to its HTTP usage, it is highly interoperable because many systems support HTTP.
Scalability
REST is scalable, because it is stateless, its Cacheability and layered system.
Statelessness ensures that requests can be processed by any node in a cluster of services without having to consider server-side state
Cacheability allows for creating responses from cached information without the request having to proceed to the actual service, which improves network efficiency and reduces the load on the service.
A layered system allows for introducing intermediaries such as a load balancer without clients having to modify their behavior as far as sending requests to the service is concerned. The load balancer can then distribute the requests between multiple instances of the service in order to increase the request-processing capacity of the service.
Interoperability
The ability to exchange and make use of information.
8. Which HTTP methods does REST use?
9. What is an HttpMessageConverter?
HttpMessageConverters convert HTTP requests to objects and back from objects to HTTP responses. Spring has a list of converters that is registered by default but it is customizable – additional implementations may be plugged in.
HttpMessageConverter
interface.
HttpInputMessage
to an object of specified type.HttpOutputMessage
.consumes
and produces
annotation attributes of the @RequestMapping
the consumable media types of the mapped request (defined on the server)
the value of the Content-Type header (defined on the client side) must match at least one of the values of this property in order for a method to handle a specific REST request.
@Configuration @EnableWebMvc @ComponentScan(basePackages = {"com.ps.web", "com.ps.exs"}) public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { super.configureMessageConverters(converters); converters.add(mappingJackson2HttpMessageConverter()); } @Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); // when client is a browser JSON response is displayed indented mappingJackson2HttpMessageConverter.setPrettyPrint(true); //set encoding of the response mappingJackson2HttpMessageConverter.setDefaultCharset (StandardCharsets.UTF_8); mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper()); return mappingJackson2HttpMessageConverter; } }
10. Is REST normally stateless?
REST is stateless because according to its definition it HAS to be stateless; meaning each request must contain all the required information to interact with the server without the server needing to store some context between requests. The same can be said about authentication – each request holds the authentication info required for interacting with the server.
11. What does @RequestMapping do?
@RequestMapping defines a handler method or class to process HTTP calls.
Annotate both for class and handler methods.
@RequestMapping
mehtods are handler method, it provides information regarding when method should be called.
Has various attributes to match by:
12. Is @Controller a stereotype? Is @RestController a stereotype?
@Controller is a stereotype whilst @RestController is not and is declared in a different package.
What is a stereotype annotation? What does that mean?
Stereotype annotations are annotations that are applied to classes that fulfills a certain, distinct, role.
@Component
.@Controller
and @RestController
are stereotypes@Controller
+ @ResponseBody
= @RestController
13. What is the difference between @Controller and @RestController?
@Controller result is passed to a view.
@RestController result is processed by a HttpMessageConverter.
For a @Controller to act as a @RestController it has to be combined with @ResponseBody.
14. When do you need @ResponseBody?
@ResponseBody is required when you want a controller result to pass to a message converter rather than to a view resolver. For example, you want a JSON object instead of a view.
With Spring 4.0, the @ResponseBody
annotation has been moved to the type level, so it can be added to interfaces, classes, or other annotations.
on class: the controller becomes restcontroller.
on method: return serialized data througth HttpMessageConverter to response body, rather than passing the model and view.
@RequestMapping(value="/test", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}) public @ResponseBody List<Journal> getJournal(){ return repo.findAll(); } @ResponseStatus(HttpStatus.OK) @RequestMapping(value = "/listdata", method = RequestMethod.GET) @ResponseBody public Singers listData() { return new Singers(singerService.findAll()); }
15. What does @PathVariable do?
@PathVariable
maps a part of the URL, an URI template variable, to a handler method argument.
@GetMapping("/api/employees/{id}/{name}") @ResponseBody public String getEmployeesByIdAndName(@PathVariable String id, @PathVariable String name) { return "ID: " + id + ", name: " + name; }
@GetMapping(value = { "/api/employeeswithrequired", "/api/employeeswithrequired/{id}" }) @ResponseBody public String getEmployeesByIdWithRequired(@PathVariable String id) { return "ID: " + id; }
@GetMapping(value = { "/api/employeeswithoptional", "/api/employeeswithoptional/{id}" }) @ResponseBody public String getEmployeesByIdWithOptional(@PathVariable Optional<String> id) { if (id.isPresent()) { return "ID: " + id.get(); } else { return "ID missing"; } }
16. What are the HTTP status return codes for a successful GET, POST, PUT or DELETE operation?
200 for success
400 for error
HTTP response codes
HTTP method
17. When do you need @ResponseStatus?
@ResponseStatus will prevent DispatcherServlet from trying to find a view for the result and will set a status for the response. So when you need another form of response instead of a view you use @ResponseStatus.
It’s always a good idea to use @ResponseStatus
where appropriate to communicate the most descriptive and accurate HTTP status code to the client.
18. Where do you need @ResponseBody? What about @RequestBody? Try not to get these muddled up!
@ResponseBody is required when you want a controller result to be passed to a message converter rather than to a view resolver.
@RequestBody annotation maps the HttpRequest body to a transfer or domain object, enabling automatic deserialization of the inbound HttpRequest body onto a Java object.
@PostMapping("/signup") public ResponseEntity<SessionDTO> signUp(@Valid @RequestBody MemberSignupCreateDTO memberCreateDTO){ ... }
@RequestBody
@RequestBody
to have the web request body read and deserialized into an Object through an HttpMessageConverter
to method parameter.@RequestBody
can be combined with @Validated
.@ResponseBody
HttpMessageConverter
.@ResponseStatus
can be combined to specify response status.If you saw example Controller code, would you understand what it is doing? Could you tell if it was annotated correctly?
yes
@RestController @RequestMapping(value = "/singer") public class SingerController { final Logger logger = LoggerFactory.getLogger(SingerController.class); @Autowired private SingerService singerService; @ResponseStatus(HttpStatus.OK) @GetMapping(value = "/listdata") public List<Singer> listData() { return singerService.findAll(); } @ResponseStatus(HttpStatus.OK) @GetMapping(value = "/{id}") public Singer findSingerById(@PathVariable Long id) { return singerService.findById(id); } @ResponseStatus(HttpStatus.CREATED) @PostMapping(value="/") public Singer create(@RequestBody Singer singer) { logger.info("Creating singer: " + singer); singerService.save(singer); logger.info("Singer created successfully with info: " + singer); return singer; } @PostMapping public Book create(@RequestBody Book book, UriComponentsBuilder uriBuilder) { Book created = bookService.create(book); URI newBookUri = uriBuilder .path("/books/{isbn}") .build(created.getIsbn()); return ResponseEntity .created(newBookUri) .body(created); } }
19. Do you need Spring MVC in your classpath?
Yes. Spring MVC is the core component of REST.
spring-mvc.jar
is not part of spring-core
.spring-web
module must be present on the classpath.20. What Spring Boot starter would you use for a Spring REST application?
spring-boot-starter-web: “Starter for building web, including RESTful, applications using Spring MVC.”
21. What are the advantages of the RestTemplate?
RestTemplate is used to make HTTP Rest Calls (REST Client).
Without RestTemplate, If we want to make an HTTP call, we need to create an HttpClient, pass request and form parameters, setup accept headers and perform unmarshalling of response, all by yourself. Spring RestTemplate tries to take that pain away by abstracting all these details from you.
RestTemplate has methods specific to HTTP methods:
So it is very convenient for REST calls.
RestTemplate
implements a synchronous HTTP client that simplifies sending requests and also enforces RESTful principles.
%20
using percent-encoding.22. If you saw an example using RestTemplate would you understand what it is doing?
yes.
String uriTemplate = "http://example.com/hotels/{hotel}"; URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42); RequestEntity<Void> requestEntity = RequestEntity.get(uri) .header(("MyRequestHeader", "MyValue") .build(); ResponseEntity<String> response = template.exchange(requestEntity, String.class); String responseHeader = response.getHeaders().getFirst("MyResponseHeader"); String body = response.getBody();
Authentication comes first before Authorization because the authorization process needs a principal object with authority votes to decide the user is allowed to perform an action for the secured resource.
Authentication is the process of establishing that a principal is who they claim to be (a “principal” generally means a user, device or some other system which can perform an action in your application). Usually, a user authenticates to a system by using his username and password.
Authorization refers to the process of deciding whether a principal is allowed to perform an action within your application. To arrive at the point where an authorization decision is needed, the identity of the principal has already been established by the authentication process. For example, certain endpoints in your API can only be accessed by certain roles. When you call these endpoints with a role that does not have the privilege, the endpoint should throw an exception.
Yes, security is a cross-cutting concern. Spring Security internally is implemented using AOP – the same way as Transactions management.
The cross-cutting concern is a concern which is applicable throughout the application and it affects the entire application. For example: logging, security and transactions.
Spring Security tackles security from two angles:
HttpServletRequest
s and HttpServletResponse
s and doesn’t care whether the requests come from a browser, a web service client, or AJAX.FilterChainProxy
.Spring Security Configuration
Spring Security WebMvc under the hood
A user tries to access the application by making a request. The application requires the user to provide the credentials so it can be logged in.
The credentials are verified by the Authenticaltion Manager and the user is granted access to the application. The authorization rights for this user are loaded into the Spring Security context.
The user makes a resource request (view, edit, insert, or delete information) and the Security Interceptor intercepts the request before the user accesses a protected/secured resource.
The Security Interceptor extracts the user authorization data from the security context and…
…delegates the decision to the Access Decision Manager.
The Access Decision Manager polls a list of voters to return a decision regarding the rights of the authenticated user to system resources.
Access is granted or denied to the resource based on the user rights and the resource attributes.
Securing RESTful-WS three-step process:
a security filter named springSecurityFilterChain needs to be added, the filter is replaced by a class extending AbstractSecurityWebApplicationInitializer
. This class registers DelegatingFilterProxy
to use springSecurityFilterChain
before any other registered Filter.
add a Spring configuration class for security where we will declare who can access the application and what they are allowed to do. In the case of this application, things are easy: we are using in-memory authentication for teaching purposes, so add a user named prospring5 with the password prospring5 and the role REMOTE.
@Configuration @EnableWebSecurity //enable secured behavior public class SecurityConfig extends WebSecurityConfigurerAdapter { private static Logger logger = LoggerFactory.getLogger(SecurityConfig.class); @Autowired protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("prospring5") .password("prospring5") .roles("REMOTE"); } @Override protected void configure(HttpSecurity http) throws Exception { http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/**") .permitAll() .antMatchers("/rest/**") .hasRole("REMOTE") .anyRequest() .authenticated() .and() .formLogin() .and() .httpBasic() .and() .csrf() .disable(); } }
3. add the rest application context, besides adding SecurityConfig to the root context application.
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[]{ DataServiceConfig.class, SecurityConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[]{ WebConfig.class}; } @Override protected String[] getServletMappings() { return new String[]{"/rest/**"}; } }
Securing a Web Application //todo
Spring Security in Sprint Boot
If library spring-boot-starter-security
is in the classpath, Spring Boot automatically secures all HTTP endpoints with basic authentication. This will add the
dependencies to your project.
DelegatingFilterProxy is the entry point for spring security. The DelegatingFilterProxy is a servlet filter and It should delegate the request to the spring managed bean that must implement the servlet Filter interface.
Delegating filter proxy is a servlet filter registered with the web container that delegates the requests to a Filter implementation on the Spring context side. That is there a 2 places servlet filters are attached to:
As of Spring Security, all requests pass through delegating filter proxy that is registered with the container and then goes to FilterChainProxy (another filter but this time on the Spring context side).
Delegating filter proxy may be declared in 2 ways:
Delegating filter proxy will pass requests to the filter whose name is springSecurityFilterChain.
4. What is the security filter chain?
Spring Security provides a number of filters by default, and most of the time, these are enough.
Spring uses a chain of filters that is customizable by pulling in and taking out some filters as well as customizing them. This chain of filters is called the security filter chain (bean from the Spring context is called springSecurityFilterChain). Filters that build the chain are created when you enable web security.
Mandatory Filter Name Main Purpose?
5. What is the security context?
The security context in Spring Security includes details of the principal currently using the application. The security context is always available to methods in the same thread of execution, even if the security context is not explicitly passed around as an argument to those methods. This information includes details about the principal. Context is held in the SecurityContextHolder.
There are several ways to determine who the user is. These are a few of the most common ways:
@AuthenticationPrincipal
annotated method.SecurityContext
holds security information about the current thread of execution.SecurityContextHolder
.SecurityContextHolder
uses a ThreadLocal to store these details, which means that the security context is always available to methods in the same thread of execution, even if the security context is not explicitly passed around as an argument to those methods.Obtaining information about the current user:
Authentication authentication = SecurityContextHolder .getContext() .getAuthentication(); User user = (User) authentication.getPrincipal();
6. Why do you need the intercept-url?
<intercept-url/> from <http/> is used to define the URL for the requests that we want to have some security constraints. This tag has a pattern attribute that accepts either ant style paths or regex for matching the required resources. Access attribute accepts comma-separated roles that will be allowed to access the resource (any match will grant the access).
7. In which order do you have to write multiple intercept-url’s?
Most specific patterns must come first and most general last. When matching the specified patterns defined by element intercept-URL against an incoming request, the matching is done in the order in which the elements are declared. So the most specific patterns should come first and the most general should come last.
<intercept-url pattern='/secure/a/**' access='ROLE_A'/> <intercept-url pattern='/secure/b/**' access='ROLE_B'/> <intercept-url pattern='/secure/**' access='ROLE_USER'/>
8. What does the ** pattern in an antMatcher or mvcMatcher do?
antMatcher(String antPattern)
Allows configuring the HttpSecurity to only be invoked when matching the provided Ant-style pattern.
/admin/**
matches any path starting with /admin
.antMatcher(…)
method is the equivalent of the <intercept-url.../>
element from XML, and equivalent methods are available to replace the configuration for the login form, logout URL configuration, and CSRF token support.mvcMatcher(String mvcPattern)
Allows configuring the HttpSecurity to only be invoked when matching the provided Spring MVC pattern. Generally mvcMatcher is more secure than an antMatcher.
antMatchers("/secured")
matches only the exact /secured
URLmvcMatchers("/secured")
matches /secured
as well as /secured/
, /secured.html
, /secured.xyz
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/users/show/*") .hasRole("ADMIN") ... } }
@EnableWebSecurity public class DirectlyConfiguredJwkSetUri extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) { http .authorizeRequests() .mvcMatchers("/contacts/**").hasAuthority("SCOPE_contacts") .mvcMatchers("/messages/**").hasAuthority("SCOPE_messages") .anyRequest().authenticated() .and() .oauth2ResourceServer() .jwt(); } }
9. Why is a mvcMatcher more secure than an antMatcher?
MvcMatcher()
uses Spring MVC’s HandlerMappingIntrospector
to match the path and extract variables.MvcMatcher
can also restrict the URLs by HTTP methodIn which order do you have to write multiple intercept-url’s?
10. Does Spring Security support password hashing? What is salting?
Spring Security uses PasswordEncoder for encoding passwords. This interface has a Md5PasswordEncoder that allows for obtaining hashes of the password – that will be persisted. The problem is that there are “dictionaries” of hashes available on the internet and some hacker may just match the hash with a record from those dictionaries and gain unauthorized (from system’s point of view authorized) access. To avoid that you can add some “salt” to the pass before it is hashed. Perfectly that salt (which is some appended string) is some random value – a simpler implementation is to use the user id.
There is an implementation of PasswordEncoder – BCryptPasswordEncoder that generates the salt automatically and thus you don’t have to bother about this.
11. Why do you need method security? What type of object is typically secured at the method level (think of its purpose, not its Java type).
If we secure only the web layer there may be a way to access the service layer in case we expose some REST endpoints. That’s why usually services are secured at the method level.
To apply security to lower layers of an application, Spring Security uses AOP. The respective bean is wrapped in a proxy that before calling the target method, first checks the credentials of the user and calls the method only if the user is authorized to call it.
Spring Security provides three different kinds of security annotations:
@Secured
@RolesAllowed
@PreAuthorize
and @PostAuthorize
,@PreFilter
, and @PostFilter
The @Secured
and @RolesAllowed
annotations are the simplest options, restricting access based on what authorities have been granted to the user.
More flexibility in defining security rules on methods, Spring Security offers @PreAuthorize
and @PostAuthorize
. And @PreFilter
/@PostFilter
filter elements out of collections returned from or passed into a method.
@Secured
@EnableGlobalMethodSecurity(secured Enabled = true)
. Methods must be secured by annotating them with Spring Security annotation @Secured
.securedEnabled
is true, a pointcut is created such that the Spring Security aspects will wrap bean methods that are annotated with @Secured
.@Secured
annotation is that it’s a Spring-specific annotation. If you’re more comfortable using annotations defined in Java standards, then perhaps you should consider using @RolesAllowed
instead.@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { } @Service @Transactional(readOnly = true, propagation = Propagation.REQUIRED) public class UserServiceImpl implements UserService { @Secured("ROLE_ADMIN") public User findById(Long id) { return userRepo.findOne(id); } }
JSR-250
annotations
@EnableGlobalMethodSecurity(jsr250Enabled = true)
.jsr250Enabled
and securedEnabled
can be used togetherJSR-250
annotations.jsr250Enabled
set to true, a pointcut will be effected such that any methods annotated with @RolesAllowed will be wrapped with Spring Security’s aspects.@RolesAllowed
annotation is equivalent to @Secured
in almost every way@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(jsr250Enabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { } @Service @Transactional(readOnly = true, propagation = Propagation.REQUIRED) public class UserServiceImpl implements UserService { @RolesAllowed("ROLE_ADMIN") public User findById(Long id) { return userRepo.findOne(id); } }
Use SpEL to enable more security constraints on methods
@PreAuthorize
: Restricts access to a method before invocation based on the result of evaluating an expression@PostAuthorize
: Allows a method to be invoked, but throws a security exception if the expression evaluates to false@PostFilter
: Allows a method to be invoked, but filters the results of that method based on an expression@PreFilter
: Allows a method to be invoked, but filters input prior to entering the method@Secured, @PreAuthorize, or @RolesAllowed annotations at the class level as well!.
Each of these annotations accepts a SpEL expression for its value parameter. If the expression evaluates to true
, then the security rule passes; otherwise, it fails. The implications of a passing versus failing security rule differ depending on which annotation is in use. You need to enable them by setting @EnableGlobalMethodSecurity
’s prePostEnabled
attribute to true:
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter {} @Service @Transactional(readOnly = true, propagation = Propagation.REQUIRED) public class UserServiceImpl implements UserService { @PreAuthorize("hasRole(’USER’)") public void create(User user){} }
12. What do @Secured and @RolesAllowed do? What is the difference between them?
@Secured and @RolesAllowed are the same the only difference is @RolesAllowed is a standard annotation (i.e. not only spring security) whereas @Secured is spring security only.
There are annotations used to declare some methods as secured. The difference between them is that @Secured is a Spring annotation while @RolesAllowed is a JSR250 annotation. For enabling @Secured annotation you have to set the securedEnabled attribute of @EnagleGlobalMethodSecurity to true:
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled=true) // for JSR-250 use jsr250enabled="true" public class SecurityConfig { ..... }
13. What do @PreAuthorized and @RolesAllowed do? What is the difference between them?
@Secured and @RolesAllowed prevent a method from being executed unless the user has the required authority. But their weakness is that they’re only able to make their decisions based on the user’s granted authorities.
With SpEL expressions guiding access decisions, far more advanced security constraints can be written.
@PreAuthorize( "(hasRole('ROLE_SPITTER') and #spittle.text.length() <= 140) or hasRole('ROLE_PREMIUM')") public void addSpittle(Spittle spittle) { }
14. In which security annotation are you allowed to use SpEL?
For them to be accessible you have to enable the pre-post-attribute to “enabled” in the <global-method-security/> element.
hasRole(role)
: Returns true if the current user has the specified role.hasAnyRole(role1,role2)
: Returns true if the current user has any of the supplied roles.isAnonymous()
: Returns true if the current user is an anonymous user.isAuthenticated()
: Returns true if the user is not anonymous.isFullyAuthenticated()
: Returns true if the user is not an anonymous or Remember-Me user.15. Is it enough to hide sections of my output (e.g. JSP-Page or Mustache template)?
16. Spring Security offers a security tag library for JSP, would you recognize it if you saw it in an example?
Spring Security Taglibs provides basic support for accessing security information.
Enable it:
spring‐security‐taglibs
dependency. <-- before use, need to import the taglib at the top of our JSP file: -->
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
Tags<sec:authorize>
tags should be evaluated by the JSP. It can be used to display individual HTML elements—such as buttons—in the page, according to the granted authorities of the current user.
ifAllGranted
, ifNotGranted
and ifAnyGranted
were recently deprecated in favor of access attribute. “`jspauthentication
The authenticate
tag is used to access the contents of the current Authentication token in SecurityContext. It can be used to display information about the current user in the page. <sec:authentication property="principal.username"/>
<sec:authorize access="isAuthenticated()">
Welcome Back, <sec:authentication property="name"/>
</sec:authorize>