[BAEL-9552] - Create spring-security-modules folder

This commit is contained in:
catalin-burcea
2019-12-13 13:04:59 +02:00
parent 3517462948
commit 0110c0eec5
712 changed files with 1140 additions and 1141 deletions

View File

@@ -0,0 +1,13 @@
*.class
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
# Packaged files #
*.jar
*.war
*.ear

View File

@@ -0,0 +1,18 @@
## Spring Security REST
This module contains articles about REST APIs with Spring Security
### Courses
The "REST With Spring" Classes: http://bit.ly/restwithspring
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
- [Spring REST Service Security](https://www.baeldung.com/2011/10/31/securing-a-restful-web-service-with-spring-security-3-1-part-3/)
- [Setting Up Swagger 2 with a Spring REST API](https://www.baeldung.com/swagger-2-documentation-for-spring-rest-api)
- [Custom Error Message Handling for REST API](https://www.baeldung.com/global-error-handler-in-a-spring-rest-api)
- [Spring Security Context Propagation with @Async](https://www.baeldung.com/spring-security-async-principal-propagation)
- [Servlet 3 Async Support with Spring MVC and Spring Security](https://www.baeldung.com/spring-mvc-async-security)
- [Intro to Spring Security Expressions](https://www.baeldung.com/spring-security-expressions)
- [Spring Security for a REST API](https://www.baeldung.com/securing-a-restful-web-service-with-spring-security)
- [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic)

View File

@@ -0,0 +1,286 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-security-rest</artifactId>
<version>0.1-SNAPSHOT</version>
<name>spring-security-rest</name>
<packaging>war</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-spring-5</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-spring-5</relativePath>
</parent>
<dependencies>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring-security.version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- web -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${javax.validation.version}</version>
</dependency>
<!-- marshalling -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- util -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<!-- test scoped -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>${spring-security.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest-assured.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-swagger.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons-fileupload.version}</version>
</dependency>
</dependencies>
<build>
<finalName>spring-security-rest</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>${cargo-maven2-plugin.version}</version>
<configuration>
<container>
<containerId>jetty8x</containerId>
<type>embedded</type>
<systemProperties>
<!-- <provPersistenceTarget>cargo</provPersistenceTarget> -->
</systemProperties>
</container>
<configuration>
<properties>
<cargo.servlet.port>8082</cargo.servlet.port>
</properties>
</configuration>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-server</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>none</exclude>
</excludes>
<includes>
<include>**/*LiveTest.java</include>
</includes>
<systemPropertyVariables>
<webTarget>cargo</webTarget>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<!-- various -->
<javax.validation.version>1.1.0.Final</javax.validation.version>
<!-- util -->
<guava.version>26.0-jre</guava.version>
<commons-fileupload.version>1.3.2</commons-fileupload.version>
<!-- testing -->
<rest-assured.version>2.9.0</rest-assured.version>
<!-- swagger -->
<springfox-swagger.version>2.9.2</springfox-swagger.version>
<!-- Maven plugins -->
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
</properties>
</project>

View File

@@ -0,0 +1,64 @@
package org.baeldung.errorhandling;
import java.util.Arrays;
import java.util.List;
import org.springframework.http.HttpStatus;
public class ApiError {
private HttpStatus status;
private String message;
private List<String> errors;
//
public ApiError() {
super();
}
public ApiError(final HttpStatus status, final String message, final List<String> errors) {
super();
this.status = status;
this.message = message;
this.errors = errors;
}
public ApiError(final HttpStatus status, final String message, final String error) {
super();
this.status = status;
this.message = message;
errors = Arrays.asList(error);
}
//
public HttpStatus getStatus() {
return status;
}
public void setStatus(final HttpStatus status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(final String message) {
this.message = message;
}
public List<String> getErrors() {
return errors;
}
public void setErrors(final List<String> errors) {
this.errors = errors;
}
public void setError(final String error) {
errors = Arrays.asList(error);
}
}

View File

@@ -0,0 +1,169 @@
package org.baeldung.errorhandling;
import java.util.ArrayList;
import java.util.List;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@ControllerAdvice
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler {
// 400
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final List<String> errors = new ArrayList<String>();
for (final FieldError error : ex.getBindingResult().getFieldErrors()) {
errors.add(error.getField() + ": " + error.getDefaultMessage());
}
for (final ObjectError error : ex.getBindingResult().getGlobalErrors()) {
errors.add(error.getObjectName() + ": " + error.getDefaultMessage());
}
final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors);
return handleExceptionInternal(ex, apiError, headers, apiError.getStatus(), request);
}
@Override
protected ResponseEntity<Object> handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final List<String> errors = new ArrayList<String>();
for (final FieldError error : ex.getBindingResult().getFieldErrors()) {
errors.add(error.getField() + ": " + error.getDefaultMessage());
}
for (final ObjectError error : ex.getBindingResult().getGlobalErrors()) {
errors.add(error.getObjectName() + ": " + error.getDefaultMessage());
}
final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors);
return handleExceptionInternal(ex, apiError, headers, apiError.getStatus(), request);
}
@Override
protected ResponseEntity<Object> handleTypeMismatch(final TypeMismatchException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final String error = ex.getValue() + " value for " + ex.getPropertyName() + " should be of type " + ex.getRequiredType();
final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error);
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
}
@Override
protected ResponseEntity<Object> handleMissingServletRequestPart(final MissingServletRequestPartException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final String error = ex.getRequestPartName() + " part is missing";
final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error);
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
}
@Override
protected ResponseEntity<Object> handleMissingServletRequestParameter(final MissingServletRequestParameterException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final String error = ex.getParameterName() + " parameter is missing";
final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error);
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
}
//
@ExceptionHandler({ MethodArgumentTypeMismatchException.class })
public ResponseEntity<Object> handleMethodArgumentTypeMismatch(final MethodArgumentTypeMismatchException ex, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final String error = ex.getName() + " should be of type " + ex.getRequiredType().getName();
final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error);
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
}
@ExceptionHandler({ ConstraintViolationException.class })
public ResponseEntity<Object> handleConstraintViolation(final ConstraintViolationException ex, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final List<String> errors = new ArrayList<String>();
for (final ConstraintViolation<?> violation : ex.getConstraintViolations()) {
errors.add(violation.getRootBeanClass().getName() + " " + violation.getPropertyPath() + ": " + violation.getMessage());
}
final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors);
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
}
// 404
@Override
protected ResponseEntity<Object> handleNoHandlerFoundException(final NoHandlerFoundException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final String error = "No handler found for " + ex.getHttpMethod() + " " + ex.getRequestURL();
final ApiError apiError = new ApiError(HttpStatus.NOT_FOUND, ex.getLocalizedMessage(), error);
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
}
// 405
@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(final HttpRequestMethodNotSupportedException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final StringBuilder builder = new StringBuilder();
builder.append(ex.getMethod());
builder.append(" method is not supported for this request. Supported methods are ");
ex.getSupportedHttpMethods().forEach(t -> builder.append(t + " "));
final ApiError apiError = new ApiError(HttpStatus.METHOD_NOT_ALLOWED, ex.getLocalizedMessage(), builder.toString());
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
}
// 415
@Override
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(final HttpMediaTypeNotSupportedException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
logger.info(ex.getClass().getName());
//
final StringBuilder builder = new StringBuilder();
builder.append(ex.getContentType());
builder.append(" media type is not supported. Supported media types are ");
ex.getSupportedMediaTypes().forEach(t -> builder.append(t + " "));
final ApiError apiError = new ApiError(HttpStatus.UNSUPPORTED_MEDIA_TYPE, ex.getLocalizedMessage(), builder.substring(0, builder.length() - 2));
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
}
// 500
@ExceptionHandler({ Exception.class })
public ResponseEntity<Object> handleAll(final Exception ex, final WebRequest request) {
logger.info(ex.getClass().getName());
logger.error("error", ex);
//
final ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex.getLocalizedMessage(), "error occurred");
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
}
}

View File

@@ -0,0 +1,78 @@
package org.baeldung.persistence.model;
import java.io.Serializable;
import javax.validation.constraints.Size;
public class Foo implements Serializable {
private static final long serialVersionUID = -5422285893276747592L;
private long id;
@Size(min = 5, max = 14)
private String name;
public Foo() {
super();
}
public Foo(final String name) {
super();
this.name = name;
}
// API
public long getId() {
return id;
}
public void setId(final long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
//
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Foo other = (Foo) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("Foo [name=").append(name).append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,80 @@
package org.baeldung.security;
import org.baeldung.security.web.MySavedRequestAwareAuthenticationSuccessHandler;
import org.baeldung.security.web.RestAuthenticationEntryPoint;
import org.baeldung.web.error.CustomAccessDeniedHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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 org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan("org.baeldung.security")
public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAccessDeniedHandler accessDeniedHandler;
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
private MySavedRequestAwareAuthenticationSuccessHandler mySuccessHandler;
private SimpleUrlAuthenticationFailureHandler myFailureHandler = new SimpleUrlAuthenticationFailureHandler();
public SecurityJavaConfig() {
super();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password(encoder().encode("adminPass")).roles("ADMIN")
.and()
.withUser("user").password(encoder().encode("userPass")).roles("USER");
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/api/csrfAttacker*").permitAll()
.antMatchers("/api/customer/**").permitAll()
.antMatchers("/api/foos/**").authenticated()
.antMatchers("/api/async/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.and()
.formLogin()
.successHandler(mySuccessHandler)
.failureHandler(myFailureHandler)
.and()
.httpBasic()
.and()
.logout();
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}

View File

@@ -0,0 +1,43 @@
package org.baeldung.security.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private RequestCache requestCache = new HttpSessionRequestCache();
@Override
public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws ServletException, IOException {
final SavedRequest savedRequest = requestCache.getRequest(request, response);
if (savedRequest == null) {
clearAuthenticationAttributes(request);
return;
}
final String targetUrlParameter = getTargetUrlParameter();
if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
requestCache.removeRequest(request, response);
clearAuthenticationAttributes(request);
return;
}
clearAuthenticationAttributes(request);
}
public void setRequestCache(final RequestCache requestCache) {
this.requestCache = requestCache;
}
}

View File

@@ -0,0 +1,27 @@
package org.baeldung.security.web;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
/**
* The Entry Point will not redirect to any sort of Login - it will return the 401
*/
@Component
public final class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(
final HttpServletRequest request,
final HttpServletResponse response,
final AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}

View File

@@ -0,0 +1,10 @@
package org.baeldung.spring;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc
@Configuration
public class ClientWebConfig implements WebMvcConfigurer {
}

View File

@@ -0,0 +1,14 @@
package org.baeldung.spring;
import org.springframework.context.annotation.ComponentScan;
// @Configuration
// @ImportResource({ "classpath:webSecurityConfig.xml" })
@ComponentScan("org.baeldung.security")
public class SecurityXmlConfig {
public SecurityXmlConfig() {
super();
}
}

View File

@@ -0,0 +1,40 @@
package org.baeldung.spring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@ComponentScan("org.baeldung.web")
@EnableWebMvc
@EnableAsync
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Bean
public ViewResolver viewResolver() {
final InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController("/csrfAttacker.html");
}
}

View File

@@ -0,0 +1,46 @@
package org.baeldung.swagger2;
import static com.google.common.collect.Lists.newArrayList;
import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("org.baeldung.web.controller"))
.paths(PathSelectors.ant("/foos/*"))
.build()
.apiInfo(apiInfo())
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET, newArrayList(new ResponseMessageBuilder().code(500)
.message("500 message")
.responseModel(new ModelRef("Error"))
.build(),
new ResponseMessageBuilder().code(403)
.message("Forbidden!!!!!")
.build()));
}
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo("My REST API", "Some custom description of API.", "API TOS", "Terms of service", new Contact("John Doe", "www.example.com", "myeaddress@company.com"), "License of API", "API license URL", Collections.emptyList());
return apiInfo;
}
}

View File

@@ -0,0 +1,39 @@
package org.baeldung.web.controller;
import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.baeldung.web.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class AsyncController {
private static final Logger log = LoggerFactory.getLogger(AsyncService.class);
@Autowired
private AsyncService asyncService;
@RequestMapping(method = RequestMethod.GET, value = "/async")
@ResponseBody
public Object standardProcessing() throws Exception {
log.info("Outside the @Async logic - before the async call: {}", SecurityContextHolder.getContext().getAuthentication().getPrincipal());
asyncService.asyncCall();
log.info("Inside the @Async logic - after the async call: {}", SecurityContextHolder.getContext().getAuthentication().getPrincipal());
return SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
@RequestMapping(method = RequestMethod.GET, value = "/async2")
@ResponseBody
public Callable<Boolean> springMVCAsyncTest() {
return asyncService.checkIfPrincipalPropagated();
}
}

View File

@@ -0,0 +1,14 @@
package org.baeldung.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class CustomController {
@RequestMapping(value = "/custom", method = RequestMethod.POST)
public String custom() {
return "custom";
}
}

View File

@@ -0,0 +1,49 @@
package org.baeldung.web.controller;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.baeldung.persistence.model.Foo;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.util.UriComponentsBuilder;
import com.google.common.collect.Lists;
@Controller
@RequestMapping(value = "/foos")
public class FooController {
// API
// read - single
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ResponseBody
public Foo findById(@PathVariable("id") final Long id, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) {
return new Foo(randomAlphabetic(6));
}
// read - multiple
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public List<Foo> findAll() {
return Lists.newArrayList(new Foo(randomAlphabetic(6)));
}
// write - just for test
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public Foo create(@RequestBody final Foo foo) {
return foo;
}
}

View File

@@ -0,0 +1,30 @@
package org.baeldung.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class RootController {
public RootController() {
super();
}
// API
@RequestMapping(value = "/admin/x", method = RequestMethod.GET)
@ResponseBody
public String sampleAdminPage() {
return "Hello";
}
@RequestMapping(value = "/my-error-page", method = RequestMethod.GET)
@ResponseBody
public String sampleErrorPage() {
return "Error Occurred";
}
}

View File

@@ -0,0 +1,23 @@
package org.baeldung.web.error;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(final HttpServletRequest request, final HttpServletResponse response, final AccessDeniedException ex) throws IOException, ServletException {
response.getOutputStream().print("Error Message Goes Here");
response.setStatus(403);
// response.sendRedirect("/my-error-page");
}
}

View File

@@ -0,0 +1,74 @@
package org.baeldung.web.error;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
//import org.springframework.security.access.AccessDeniedException;
@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
public RestResponseEntityExceptionHandler() {
super();
}
// API
// 400
@ExceptionHandler({ DataIntegrityViolationException.class })
public ResponseEntity<Object> handleBadRequest(final DataIntegrityViolationException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
// ex.getCause() instanceof JsonMappingException, JsonParseException // for additional information later on
return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
}
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
}
// 403
@ExceptionHandler({ AccessDeniedException.class })
public ResponseEntity<Object> handleAccessDeniedException(final Exception ex, final WebRequest request) {
System.out.println("request" + request.getUserPrincipal());
return new ResponseEntity<Object>("Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
}
// 409
@ExceptionHandler({ InvalidDataAccessApiUsageException.class, DataAccessException.class })
protected ResponseEntity<Object> handleConflict(final RuntimeException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}
// 412
// 500
@ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class })
/*500*/public ResponseEntity<Object> handleInternal(final RuntimeException ex, final WebRequest request) {
logger.error("500 Status Code", ex);
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
}

View File

@@ -0,0 +1,21 @@
package org.baeldung.web.exception;
public final class MyResourceNotFoundException extends RuntimeException {
public MyResourceNotFoundException() {
super();
}
public MyResourceNotFoundException(final String message, final Throwable cause) {
super(message, cause);
}
public MyResourceNotFoundException(final String message) {
super(message);
}
public MyResourceNotFoundException(final Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,11 @@
package org.baeldung.web.service;
import java.util.concurrent.Callable;
public interface AsyncService {
void asyncCall();
Callable<Boolean> checkIfPrincipalPropagated();
}

View File

@@ -0,0 +1,36 @@
package org.baeldung.web.service;
import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger log = LoggerFactory.getLogger(AsyncService.class);
@Async
@Override
public void asyncCall() {
log.info("Inside the @Async logic: {}", SecurityContextHolder.getContext().getAuthentication().getPrincipal());
}
@Override
public Callable<Boolean> checkIfPrincipalPropagated() {
Object before = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("Before new thread: {}", before);
return new Callable<Boolean>() {
public Boolean call() throws Exception {
Object after = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("New thread: {}", after);
return before == after;
}
};
}
}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Spring Security Configurations are managed in SecurityJavaConfig class -->
<!--
<http use-expressions="true" entry-point-ref="restAuthenticationEntryPoint">
<intercept-url pattern="/admin/*" access="hasAnyRole('ROLE_ADMIN')"/>
<intercept-url pattern="/api/**" access="isAuthenticated()" />
<csrf disabled="true" />
<form-login authentication-success-handler-ref="mySuccessHandler"
authentication-failure-handler-ref="myFailureHandler" />
<access-denied-handler error-page="/my-error-page" />
<access-denied-handler ref="customAccessDeniedHandler" />
<logout />
</http>
<beans:bean id="mySuccessHandler"
class="org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler" />
<beans:bean id="myFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler" />
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="temporary" password="temporary" authorities="ROLE_ADMIN" />
<user name="user" password="userPass" authorities="ROLE_USER" />
<user name="user1" password="user1Pass" authorities="ROLE_USER"/>
<user name="admin" password="adminPass" authorities="ROLE_ADMIN"/>
</user-service>
</authentication-provider>
</authentication-manager>
<global-method-security pre-post-annotations="enabled"/>
-->
</beans:beans>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1000000" />
</bean>
</beans>

View File

@@ -0,0 +1,16 @@
<html>
<head></head>
<body>
<h1>CSRF Attacker</h1>
<a href="http://localhost:8080/spring-security-rest-full/transfer?accountNo=5678&amount=1000">Show Kittens Pictures</a>
<img src="http://localhost:8080/spring-security-rest-full/transfer?accountNo=5678&amount=1000"/>
<form action="http://localhost:8080/spring-security-rest-full/transfer" method="POST">
<input name="accountNo" type="hidden" value="5678"/>
<input name="amount" type="hidden" value="1000"/>
<input type="submit" value="Show Kittens Picture">
</form>
</body>
</html>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Spring MVC Application</display-name>
<!-- Spring root -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.baeldung.spring</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring child -->
<servlet>
<servlet-name>api</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>api</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ASYNC</dispatcher>
</filter-mapping>
<!-- <welcome-file-list> -->
<!-- <welcome-file>index.html</welcome-file> -->
<!-- </welcome-file-list> -->
</web-app>

View File

@@ -0,0 +1,20 @@
package org.baeldung;
import org.baeldung.security.SecurityJavaConfig;
import org.baeldung.spring.ClientWebConfig;
import org.baeldung.spring.WebConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = { ClientWebConfig.class, SecurityJavaConfig.class, WebConfig.class })
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}

View File

@@ -0,0 +1,88 @@
package org.baeldung.errorhandling;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.baeldung.errorhandling.ApiError;
import org.baeldung.web.TestConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.response.Response;
import com.jayway.restassured.specification.RequestSpecification;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class)
public class FooLiveTest {
private static final String URL_PREFIX = "http://localhost:8080/spring-security-rest";
// private FormAuthConfig formConfig = new FormAuthConfig(URL_PREFIX + "/login", "temporary", "temporary");
private String cookie;
private RequestSpecification givenAuth() {
// return RestAssured.given().auth().form("user", "userPass", formConfig);
// if (cookie == null) {
// cookie = RestAssured.given().contentType("application/x-www-form-urlencoded").formParam("password", "userPass").formParam("username", "user").post(URL_PREFIX + "/login").getCookie("JSESSIONID");
// }
// return RestAssured.given().cookie("JSESSIONID", cookie);
return RestAssured.given()
.auth().preemptive()
.basic("user", "userPass");
}
@Test
public void whenTry_thenOK() {
final Response response = givenAuth().get(URL_PREFIX + "/api/foos");
assertEquals(200, response.statusCode());
System.out.println(response.asString());
}
@Test
public void whenMethodArgumentMismatch_thenBadRequest() {
final Response response = givenAuth().get(URL_PREFIX + "/api/foos/ccc");
final ApiError error = response.as(ApiError.class);
assertEquals(HttpStatus.BAD_REQUEST, error.getStatus());
assertEquals(1, error.getErrors().size());
assertTrue(error.getErrors().get(0).contains("should be of type"));
}
@Test
public void whenNoHandlerForHttpRequest_thenNotFound() {
final Response response = givenAuth().delete(URL_PREFIX + "/api/xx");
final ApiError error = response.as(ApiError.class);
assertEquals(HttpStatus.NOT_FOUND, error.getStatus());
assertEquals(1, error.getErrors().size());
assertTrue(error.getErrors().get(0).contains("No handler found"));
System.out.println(response.asString());
}
@Test
public void whenHttpRequestMethodNotSupported_thenMethodNotAllowed() {
final Response response = givenAuth().delete(URL_PREFIX + "/api/foos/1");
final ApiError error = response.as(ApiError.class);
assertEquals(HttpStatus.METHOD_NOT_ALLOWED, error.getStatus());
assertEquals(1, error.getErrors().size());
assertTrue(error.getErrors().get(0).contains("Supported methods are"));
System.out.println(response.asString());
}
@Test
public void whenSendInvalidHttpMediaType_thenUnsupportedMediaType() {
final Response response = givenAuth().body("").post(URL_PREFIX + "/api/foos");
final ApiError error = response.as(ApiError.class);
assertEquals(HttpStatus.UNSUPPORTED_MEDIA_TYPE, error.getStatus());
assertEquals(1, error.getErrors().size());
assertTrue(error.getErrors().get(0).contains("media type is not supported"));
System.out.println(response.asString());
}
}

View File

@@ -0,0 +1,48 @@
package org.baeldung.web;
import org.baeldung.security.SecurityJavaConfig;
import org.baeldung.spring.ClientWebConfig;
import org.baeldung.spring.WebConfig;
import org.baeldung.web.controller.AsyncController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = { ClientWebConfig.class, SecurityJavaConfig.class, WebConfig.class })
public class AsyncControllerIntegrationTest {
@Autowired
WebApplicationContext wac;
@Autowired
MockHttpSession session;
@Mock
AsyncController controller;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
public void testAsync() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/async")).andExpect(status().is5xxServerError());
}
}

View File

@@ -0,0 +1,20 @@
package org.baeldung.web;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.response.Response;
public class SwaggerLiveTest {
private static final String URL_PREFIX = "http://localhost:8080/spring-security-rest/api";
@Test
public void whenVerifySpringFoxIsWorking_thenOK() {
final Response response = RestAssured.get(URL_PREFIX + "/v2/api-docs");
assertEquals(200, response.statusCode());
System.out.println(response.asString());
}
}

View File

@@ -0,0 +1,19 @@
package org.baeldung.web;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
@Configuration
@ComponentScan({ "org.baeldung.web" })
public class TestConfig {
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
return multipartResolver;
}
}

View File

@@ -0,0 +1,13 @@
*.class
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
# Packaged files #
*.jar
*.war
*.ear