I have this in:
main/resources/log4j.properties
# Define the root logger with appender file
log4j.rootLogger = INFO
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
and I call it using:
package huru.middleware;
import huru.MainVerticle;
import io.vertx.core.Handler;
import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.impl.BodyHandlerImpl;
import org.apache.log4j.Logger;
public class JWTHandler implements Handler<RoutingContext> {
private final Logger log = Logger.getLogger(MainVerticle.class);
public void handle(RoutingContext ctx) {
HttpServerRequest request = ctx.request();
log.info("in the jwt middleware");
System.out.println("DOOOOF");
System.out.println(ctx.request().method());
ctx.next();
}
}
System.out.println calls will get logged, but log.info() doesn't log anything. Anyone know what might be wrong with my configuration?
A quickfix would be to change the log4j.properties a tiny bit:
log4j.rootLogger = INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
Related
I want to use swagger client generator and feed the json generated by "../v2/api-docs" from the jHipster application. The problem is that without the security definitions the generated code will not work. The JWT token is not added to the API requests, the code is generated without authentication. The http://petstore.swagger.io/v2/swagger.json example has security and securityDefinitions. Where to modify/configure the jhipster application so that the security and security definitions are generated in the json file? {I manually added the security and security definitions to the json file and after that the generated code works and JWT is enabled in the jHipster application, but I don't want to edit the file each time the API changes... } The "securityDefinitions" and "security":[{"petstore_auth":["write:pets","read:pets"]}] sections are completely missing from the generated json file from the jHipster application, even if JWT is enabled and needed to make API requests.
Update 28-09-2020:
Since the update to SpringFox 3, classes are now called
SpringfoxCustomizer
JHipsteSpringfoxCustomizer
Better late than never.
JHipster applications depend on the JHipster Framework, which is in charge of the springfox's Docket configuration.
JHipster Framework's SwaggerAutoConfiguration customizes the springfox Docket with every SwaggerCustomizer bean registered in the application. JHipster registers it's own swagger customizer for the default docket configuration.
This said, you need to add your own docket customizer ir order to include the desired security definitions and any other additional configuration to the springfox's docket. In order to do this you need to:
Create the swagger pacakage inside the already existing config package. Inside it, create a CustomSwaggerConfig class:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class CustomSwaggerConfig {
public CustomSwaggerConfig() {
}
#Bean
public ApplicationSwaggerCustomizer applicationSwaggerCustomizer() {
return new ApplicationSwaggerCustomizer();
}
}
And create the ApplicationSwaggerCustomizer class:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.github.jhipster.config.apidoc.customizer.SwaggerCustomizer;
import springfox.documentation.spring.web.plugins.Docket;
public class ApplicationSwaggerCustomizer implements SwaggerCustomizer {
private final Logger log = LoggerFactory.getLogger(ApplicationSwaggerCustomizer.class);
public ApplicationSwaggerCustomizer() {
}
#Override
public void customize(Docket docket) {
log.debug("Customizing springfox docket...");
// TODO Here you can add all the configurations to the docket
}
}
Now you can add any additional docket configuration.
You can clone default implementation with:
package <YOUR_PACKAGE>;
import static io.github.jhipster.config.JHipsterConstants.SPRING_PROFILE_SWAGGER;
import static springfox.documentation.builders.PathSelectors.regex;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import io.github.jhipster.config.JHipsterProperties;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.ApiKeyVehicle;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Springfox Swagger configuration.
* <p>
* Warning! When having a lot of REST endpoints, Springfox can become a performance issue.
* In that case, you can use the "no-swagger" Spring profile, so that this bean is ignored.
*/
#Configuration
#Profile(SPRING_PROFILE_SWAGGER)
#EnableSwagger2
public class SwaggerConfiguration {
static final String STARTING_MESSAGE = "Starting Swagger with JWT";
static final String STARTED_MESSAGE = "Started Swagger with JWT in {} ms";
static final String MANAGEMENT_TITLE_SUFFIX = "Management API";
static final String MANAGEMENT_GROUP_NAME = "management";
static final String MANAGEMENT_DESCRIPTION = "Management endpoints documentation";
public static final String AUTHORIZATION_HEADER = "Authorization";
private final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);
private final JHipsterProperties.Swagger properties;
public SwaggerConfiguration(JHipsterProperties jHipsterProperties) {
this.properties = jHipsterProperties.getSwagger();
}
/**
* Springfox configuration for the API Swagger with JWT docs.
*
* #return the Swagger Springfox configuration
*/
#Bean
public Docket swaggerSpringfoxApiDocket() {
log.debug(STARTING_MESSAGE);
StopWatch watch = new StopWatch();
watch.start();
Docket docket = createDocket();
Contact contact = new Contact(
properties.getContactName(),
properties.getContactUrl(),
properties.getContactEmail()
);
ApiInfo apiInfo = new ApiInfo(
properties.getTitle(),
properties.getDescription(),
properties.getVersion(),
properties.getTermsOfServiceUrl(),
contact,
properties.getLicense(),
properties.getLicenseUrl(),
new ArrayList<>()
);
docket.host(properties.getHost())
.protocols(new HashSet<>(Arrays.asList(properties.getProtocols())))
.securitySchemes(Arrays.asList((apiKey())))
.securityContexts(Arrays.asList(
SecurityContext.builder()
.securityReferences(
Arrays.asList(SecurityReference.builder()
.reference("JWT")
.scopes(new AuthorizationScope[0])
.build()
)
)
.build())
)
.apiInfo(apiInfo)
.useDefaultResponseMessages(properties.isUseDefaultResponseMessages())
.forCodeGeneration(true)
.directModelSubstitute(ByteBuffer.class, String.class)
.genericModelSubstitutes(ResponseEntity.class)
.ignoredParameterTypes(Pageable.class)
.select()
.paths(regex(properties.getDefaultIncludePattern()))
.build();
watch.stop();
log.debug(STARTED_MESSAGE, watch.getTotalTimeMillis());
return docket;
}
/**
* Springfox configuration for the management endpoints (actuator) Swagger docs.
*
* #param appName the application name
* #param managementContextPath the path to access management endpoints
* #return the Swagger Springfox configuration
*/
#Bean
#ConditionalOnMissingBean(name = "swaggerSpringfoxManagementDocket")
public Docket swaggerSpringfoxManagementDocket(#Value("${spring.application.name:application}") String appName,
#Value("${management.endpoints.web.base-path}") String managementContextPath) {
ApiInfo apiInfo = new ApiInfo(
StringUtils.capitalize(appName) + " " + MANAGEMENT_TITLE_SUFFIX,
MANAGEMENT_DESCRIPTION,
properties.getVersion(),
"",
ApiInfo.DEFAULT_CONTACT,
"",
"",
new ArrayList<>()
);
return createDocket()
.apiInfo(apiInfo)
.useDefaultResponseMessages(properties.isUseDefaultResponseMessages())
.groupName(MANAGEMENT_GROUP_NAME)
.host(properties.getHost())
.protocols(new HashSet<>(Arrays.asList(properties.getProtocols())))
.securitySchemes(Arrays.asList((apiKey())))
.securityContexts(Arrays.asList(
SecurityContext.builder()
.securityReferences(
Arrays.asList(SecurityReference.builder()
.reference("JWT")
.scopes(new AuthorizationScope[0])
.build()
)
)
.build())
)
.forCodeGeneration(true)
.directModelSubstitute(ByteBuffer.class, String.class)
.genericModelSubstitutes(ResponseEntity.class)
.ignoredParameterTypes(Pageable.class)
.select()
.paths(regex(managementContextPath + ".*"))
.build();
}
protected Docket createDocket() {
return new Docket(DocumentationType.SWAGGER_2);
}
private ApiKey apiKey() {
return new ApiKey("JWT", AUTHORIZATION_HEADER, ApiKeyVehicle.HEADER.getValue());
}
} // END
At first i got a similar problem like yours and i searched to find your post.
But my project uses .net core,and from the url below i found a solution.
Hope it could help you if you haven't got your problem fixed.
https://github.com/domaindrivendev/Swashbuckle.AspNetCore#add-security-definitions-and-requirements
When I run my Grails project in my local environment everything works fine however when I use grails package and deploy it to our test server it isn't able to load the page because it throws a NoClassDefFoundError
This is the code for the loading of the specific page:
package com.x.scheduledReport
import com.x.Account
import com.x.XUtil
import com.x.ResponseList
import com.x.ScheduledReport
import com.x.UserService
import com.x.scheduledReports.ScheduledReportDeleteAllCommand
import com.x.scheduledReports.ScheduledReportDeleteCommand
import com.x.scheduledReports.ScheduledReportResponse
import com.x.scheduledReports.ScheduledReportUpdateCommand
import com.x.scheduledReports.ScheduledReportsCommand
import grails.transaction.Transactional
import com.x.scheduledreport.ScheduledReportUtil
#Transactional
class ScheduledReportBusinessService {
ScheduledReportService scheduledReportService
UserService userService
def list(Map params) {
if (params.start) {
params.offset = params.start
}
if (params.length) {
params.max = Math.min(params.length ? params.length as Integer : 100, 1000)
}
params.columns = XUtil.getSearchMap(params)
Account account = userService.getAccountForCurrentUser()
def scheduledReports = scheduledReportService.findAllByAccount(params, account)
params.total = scheduledReports.count
List<ScheduledReportResponse> scheduledReportResponseList = ScheduledReportUtil.toScheduledReportResponseList(scheduledReports.list)
new ResponseList(recordsTotal: scheduledReports.count, recordsFiltered: scheduledReports.count,
data: scheduledReportResponseList, draw: params.draw ? params.draw as int : 0)
}
}
This is the error thrown in the logs
ERROR 2018-04-05 14:18:42,242
org.springframework.boot.context.web.ErrorPageFilter - Forwarding to
error page from request [/rest/scheduledreport/list/true] due to
exception [com/x/scheduledreport/ScheduledReportUtil]
java.lang.NoClassDefFoundError:
com/x/scheduledreport/ScheduledReportUtil at
com.x.scheduledReport.ScheduledReportBusinessService.$tt__list(ScheduledReportBusinessService.groovy:33)
at
com.x.scheduledReport.ScheduledReportBusinessService$_list_closure1.doCall(ScheduledReportBusinessService.groovy)
There were inconsistensies with the folder names for ScheduledReport making all the names the same fixed the issue.
I've been starting to use GraphAware timetree for neo4j, and so far its working out pretty well. Now I'm trying to work out how I can unit / integration test my code that uses neo4j timetree.
I've put together some code as below... but still I'm getting the message:
org.neo4j.ogm.exception.CypherException: Error executing Cypher "Neo.ClientError.Procedure.ProcedureNotFound"; Code: Neo.ClientError.Procedure.ProcedureNotFound; Description: There is no procedure with the name `ga.timetree.events.attach` registered for this database instance. Please ensure you've spelled the procedure name correctly and that the procedure is properly deployed.
Am I sort of on the right track?
package myproject.core;
import java.util.ArrayList;
import java.util.HashMap;
import javax.inject.Inject;
import org.junit.After;
import org.junit.runner.RunWith;
import org.neo4j.graphdb.DynamicLabel;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.neo4j.ogm.testutil.MultiDriverTestClass;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.neo4j.template.Neo4jOperations;
import org.springframework.test.context.junit4.SpringRunner;
import com.graphaware.common.policy.NodeInclusionPolicy;
import com.graphaware.module.timetree.module.TimeTreeConfiguration;
import com.graphaware.module.timetree.module.TimeTreeModule;
import com.graphaware.runtime.GraphAwareRuntime;
import com.graphaware.runtime.GraphAwareRuntimeFactory;
import myproject.core.context.TestPersistenceContext;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = TestPersistenceContext.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AbstractTest extends MultiDriverTestClass {
#Inject
private Neo4jOperations neo4jOperations;
public AbstractTest() {
new SessionFactory("myproject.model.pojos").openSession();
TimeTreeConfiguration timeTreeConfiguration = TimeTreeConfiguration.defaultConfiguration();
TimeTreeModule timeTreeModule = new TimeTreeModule("TT.1", timeTreeConfiguration, super.getGraphDatabaseService());
GraphAwareRuntime runtime = GraphAwareRuntimeFactory.createRuntime(super.getGraphDatabaseService());
runtime.registerModule(timeTreeModule);
runtime.start();
}
#After
public void clearDatabase() {
neo4jOperations.query("match (n) detach delete n;", new HashMap<>());
neo4jOperations.clear();
}
}
Please change your AbstractTest() constructor to read as follows:
public AbstractTest() {
new SessionFactory("myproject.model.pojos").openSession();
TimeTreeConfiguration timeTreeConfiguration = TimeTreeConfiguration.defaultConfiguration();
TimeTreeModule timeTreeModule = new TimeTreeModule("TT.1", timeTreeConfiguration, super.getGraphDatabaseService());
TimeTreeProcedures.register(super.getGraphDatabaseService());
GraphAwareRuntime runtime = GraphAwareRuntimeFactory.createRuntime(super.getGraphDatabaseService());
runtime.registerModule(timeTreeModule);
runtime.start();
}
Note the added line: TimeTreeProcedures.register(super.getGraphDatabaseService());
I have started working on Spring Security. I am doing a HelloWorld application from this link.
My question is, why do we need the #Import annotation?
While working on Spring MVC, I used to define a similar configuration file, but since it was in the same package, I did not need to import it. Why am I importing the SecurityConfig.java file here, then?
The place where I have used the #Import annotation is here
AppConfig.java:
package com.mkyong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
#EnableWebMvc
#Configuration
#ComponentScan({ "com.mkyong.web.*" })
#Import({ SecurityConfig.class })
public class AppConfig {
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver
= new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
You need to import the security into the main app config class because it won't be picked up by the #ComponentScan because the class is not within the package for scanning #ComponentScan({ "com.mkyong.web.*" }). The security config is not defined in there. You register your main class like:
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
If you don't import the security class into it then the security won't be registered in the application.
I'm new to Spring and I try to create a secured rest application using Spring Boot and Spring Security. I'm searching for weeks for a solution now...
I'm using Spring Boots embedded web container (Tomcat) and the spring-boot-starter-parent 1.2.6.RELEASE in my pom.
My endpoints:
/login (to authenticate)
/application/{id} (some service which I want to secure)
I configured my servlet path in my application.properties like this:
server.servletPath: /embedded
so I expect my services e.g. on //localhost/embedded/login
Ok so now the problem: If I run the application without security everything is fine, I can call http//localhost/embedded/application and get an answer.
If I now add my security configuration like this:
import javax.servlet.ServletContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#Configuration
#EnableWebMvcSecurity
#EnableScheduling
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private TokenAuthenticationService tokenAuthenticationService;
#Value("${server.servletPath}")
private String servletPath;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/hello/**", "/login").permitAll()
.antMatchers("/application/**").authenticated().and()
.addFilterBefore(new TokenAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.httpBasic().disable();
}
}
when running the application //localhost/application/{id} is secured instead of
//localhost/embedded/application/{id} as I would have expected.
For some reason the servlet path is ignored there. I tought "ok so I just add the servlet path manually" and make it look like this:
...antMatchers(servletPath+"/application/**").authenticated()...
This works in my application. However I also use MockMvc to test my services and for some reason there the servlet path is correctly added to the matchers. So if I start the tests the security filters are mapped to //localhost/embedded/embedded/application/{id} while the controllers themselves still are mapped to //localhost/embedded/application/{id} which is very annoying...
I took a look at here http://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/ and thought I could fix the issue by using AbstractSecurityWebApplicationInitializer instead of SpringBootServletInitializer but it changed nothing.
This is my application class by the way:
com.sebn.gsd.springservertemplate.service.security.WebSecurityConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
System.out.println("Run from main");
SpringApplication.run(applicationClass, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass, WebSecurityConfig.class);
}
private static Class<Application> applicationClass = Application.class;
}
The application.properties doesn't contain any more interesting information I think. To be complete this is my MockMvc testing class:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sebn.gsd.springservertemplate.service.api.LoginData;
import com.sebn.gsd.springservertemplate.service.security.Session_model;
import com.sebn.gsd.springservertemplate.service.security.WebSecurityConfig;
import java.util.Arrays;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.Matchers.notNullValue;
import org.junit.Assert;
import org.junit.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.web.servlet.ResultActions;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import org.springframework.web.context.WebApplicationContext;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {Application.class, WebSecurityConfig.class })
#WebAppConfiguration
#ActiveProfiles(profiles = "development")
public class SecurityTests {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
private HttpMessageConverter mappingJackson2HttpMessageConverter;
private ObjectMapper o = new ObjectMapper();
#Autowired
private FilterChainProxy filterChainProxy;
#Value("${server.servletPath}")
private String servletPath;
#Before
public void setup() throws Exception {
this.mockMvc = webAppContextSetup(webApplicationContext).addFilter(filterChainProxy).build();
}
#Test
public void testLoginSecurity() throws Exception {
int applicationId = 1;
// Try to access secured api
ResultActions actions = mockMvc.perform(get("/application/" + applicationId))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isForbidden());
//login
String username = "user";
LoginData loginData = new LoginData();
loginData.setPasswordBase64("23j4235jk26=");
loginData.setUsername(username);
actions = mockMvc.perform(post("/login").content(o.writeValueAsString(loginData)).contentType(MediaType.APPLICATION_JSON_VALUE))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.login", Matchers.equalTo(username)))
.andExpect(jsonPath("$.token", notNullValue()))
.andExpect(jsonPath("$.expirationDate", notNullValue()));
Session_model session = getResponseContentAsJavaObject(actions.andReturn().getResponse(), Session_model.class);
Assert.assertNotNull(session);
// Try to access secured api again
actions = mockMvc.perform(get("/application/" + applicationId).header("X-AUTH-TOKEN", session.getToken()))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk());
}
private <T> T getResponseContentAsJavaObject(MockHttpServletResponse response, Class<T> returnType) throws Exception{
return o.readValue(response.getContentAsString(), returnType);
}
#Autowired
void setConverters(HttpMessageConverter<?>[] converters) {
this.mappingJackson2HttpMessageConverter = Arrays.asList(converters).stream().filter(
hmc -> hmc instanceof MappingJackson2HttpMessageConverter).findAny().get();
Assert.assertNotNull("the JSON message converter must not be null",
this.mappingJackson2HttpMessageConverter);
}
}
Maybe I misunderstood something. I hope you can tell me.
Summary
In short you need to map Spring Security to use include the servlet path. Additionally, you need to include the servlet path in your MockMvc requests. To do so you can perform something like:
#Before
public void setup() throws Exception {
this.mockMvc = webAppContextSetup(webApplicationContext)
// ADD LINE BELOW!!!
.defaultRequest(get("/").servletPath(servletPath))
.addFilter(filterChainProxy)
.build();
}
Detailed Response
Spring Security Matches Based on Context Root
Spring Security's matchers are relative to the application's context root. It is not relative to the servlet path. This is deliberate because it should protect all the servlets (not just Spring MVC). If it were relative to the servlet, consider the following:
servlet1-path/abc -> Only users with role ROLE_ADMIN can access
servlet2-path/abc -> Only users with role ROLE_USER can access
How would you differentiate between these two mappings if Spring Security were relative to the servlet path?
Working in Mock MVC
The reason Spring Security is working in MockMvc is because when you are using MockMvc the servlet path is no longer considered. Your requests are being sent to Spring Security and Spring MVC as though the servlet path is "". To fix this you need to include the servlet path in the request.
#Before
public void setup() throws Exception {
this.mockMvc = webAppContextSetup(webApplicationContext)
// ADD LINE BELOW!!!
.defaultRequest(get("/").servletPath(servletPath))
.addFilter(filterChainProxy)
.build();
}