I am trying to implement a Spring Boot version of Pet Clinic overriding as little of Spring Boot defaults as possible.
At this point, my logout link doesn't seem to work and I've been told that it is because I haven't properly added HttpSessionEventPublisher to my application.
How can I add HttpSessionEventPublisher to my application?
I've tried the following:
#Component
#Configuration
public class WebXmlConfig implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.addListener(new HttpSessionEventPublisher());
}
}
and
#Bean
public ServletListenerRegistrationBean<HttpSessionEventPublisher> getHttpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}
My main class does not extend any classes. If that is required for me to add HttpSessionEventPublisher, I would need to know which class also.
None of the Spring Boot examples log out properly, so I have nothing to based on off of.
Any help would be appreciated.
Related
I am new to spring security and I am trying to build a restful API based sample Spring Security based example and I have used Spring Boot to create project.But I am getting following error when I send a request url:-
Request Url:-
http://localhost:8080/message
Response Got: -
{"timestamp":1505139451257,"status":401,"error":"Unauthorized","message":"Full authentication is required to access this resource","path":"/message"}
The Below is the code I have added:-
1] Main Class
#SpringBootApplication
#ComponentScan("com.srikss.controller")
public class SrikSsApplication {
public static void main(String[] args) {
SpringApplication.run(SrikSsApplication.class, args);
}
Controller:-
#RestController
public class HelloWorldController {
#RequestMapping(value="/message",method=RequestMethod.GET,headers="Accept=application/json")
public String messageLoad()
{
return "hello";
}
}
Configuration Class: -
#Configuration
#EnableWebSecurity
public class SrikSSConfiguration extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity httpsecurity) throws Exception
{
httpsecurity.authorizeRequests().anyRequest().permitAll().and()
.httpBasic();
httpsecurity.csrf().disable();
}
}
Can anyone help me to figure out what I am doing wrong here.
Thanks in advance.
Finally got the reason what I was doing wrong.
with the help of this reference link:-
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-security.html
actually spring boot defines default password which generated randomly and the default user name is "user".
After I update the password in application.properties file got the desired result,
security.user.password=aaa
I am going to use springfox (2.6.1v) with swagger-ui in my Spring Boot (1.4.2v).
The configuration for it looks:
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.genericModelSubstitutes(ResponseEntity.class);
}
}
The problem is that my swagger is behind spring security and I need to allow access there only by admin.
Question is what should be the set of matchers to allow swagger-ui to work within my application?
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("??? <<<what_should_be_here>>> ???") // what should be here?
.hasRole("TENANT_ADMIN");
}
}
Ok first I have found the solution here so following lines:
.antMatchers("/admin/system/state/*", "/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**")
But still sth did not work and because of that I have asked this question. But after deeper investigation it occured that spring-fox does not support GSON. When you use GSON as "to json" converter swagger-ui receives a slightly different JSON format what causes problems...
When we changed converter to Jackson and added above paths to spring-config it works without any problems.
I have even requested the new feature on spring-fox github here.
While testing Spring Boot (1.3.3) with a simple web app using spring-boot-starter-security:1.3.3:RELEASE I observed the following behaviour:
In order to override the default Spring web security configuration, I supplied a custom Java configuration class like so:
#Configuration
// #EnableWebSecurity apparently obsolete ?
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// http security checking left out for brevity ...
}
#Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception {
// user authentication left out for brevity ...
}
}
After startup, the application redirects to the login page and checks username/password correctly whether the #EnableWebSecurity annotation is provided or not (like in the example above). Is this annotation in this context therefore obsolete ? If so, why ?
The auto configuration of Spring Boot automatically enables web security and retrieves all beans of the type WebSecurityConfigurerAdapter to customize the configuration if certain conditions are met (spring-boot-starter-security on the classpath etc.). The auto configuration for web security is enabled in the class org.springframework.boot.autoconfigure.security.SpringBootWebSecurityConfiguration (Spring Boot 1.2.7, class name may have changed in newer versions).
I have a rest webservice configured as a spring boot application.
All my rest urls have a base path "/api/...".
I am also serving static content from my application.
I need to configure security ONLY for the web service i.e., URLs that start with "/api/..." but give the other static content w/o applying security.
I've only seen examples where we filter some url patterns via:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/*");
}
but not otherwise ...
Use the antMatcher method of HttpSecurity class:
#Configuration
#EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**");
// add security constraints for /api/... here
}
/* rest of config */
}
Instead of antMatcher, you can you regexMatcher wich can be a negation pattern
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().regexMatchers(XXXXX);
}
Answer to your last comment, if you are using latest spring framework and spring security then define below class and security config as per the config standards.
package org.springframework.security.samples.config;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class MessageSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
Also, look at below URL if you still find it difficult to get started with spring security.
http://docs.spring.io/spring-security/site/docs/3.2.6.RELEASE/reference/htmlsingle/#hello-web-security-java-configuration
I'm having some trouble testing a Spring Boot application with MockMvc.
I have the following test class:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {SpringConfiguration.class, SecurityConfiguration.class})
#IntegrationTest({"server.port=8080"})
#WebAppConfiguration
public class DemoTest {
#Autowired
private EmbeddedWebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void testGetAccountUnauthenticated() throws Exception {
mockMvc.perform(get("/accounts/1").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
}
}
This results in a HTTP 200 not a 401. I have component scanning and autoconfiguration enabled and spring security is configured in my SecuityConfiguration class as follows:
#Configuration
#EnableWebSecurity
#EnableWebMvcSecurity // required for use of #AuthenticationPrincipal in MVC controllers.
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) {
web.debug(true);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//set up authentication.
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
// set up form login
}
}
If I use a RestTemplate to access http://localhost:8080/accounts/1 then I get the expected behaviour (HTTP 401).
I have seen other examples (e.g. Spring Boot setup security for testing) that suggest that I autowire the FilterChainProxy and add the filter manually using the WebApplicationContext.addFilters(filterChainProxy) method. However, this actually fails for me (org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.web.FilterChainProxy] found).
I have two questions:
Why does the injected WebApplicationContext not automatically use the SpringSecurity filters? Even if I could get the FilterChainProxy and add it manually, the JavaDoc for EmbeddedWebApplicationContext states
any {#link Servlet} or {#link Filter} beans defined in the context will be automatically registered with the embedded Servlet container
As a result I wouldn't expect to have to manually add the security filter chain since I (incorrectly?) expect this to "just work" due to the Auto Configuration magic in Spring Boot?
Why is there no FilterChainProxy in the application context? Again, perhaps my expectations of the AutoConfiguration is incorrect - but I thought that this would be configured as part of the context configuration.
Thanks in advance for any advice.
Edits
The reason a FilterChainProxy doesn't get injected was because I has my configuration set to
public void configure(WebSecurity web) {
web.debug(true);
}
This actually configures a org.springframework.security.web.debug.DebugFilter instead. The way I have now managed to get the Filter regardless of this debug setting is as follows:
#Resource(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
private Filter securityFilter;
If I add this to the MockMvcBuilder as follows:
MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilters(securityFilter)
then it does work as expected.
But, I don't understand why MockMVC would ignore the filters as this seems important for testing a request since anything could happen in a Filter that might impact the outcome of the test. Furthermore, it means that to test properly I'd need to lookup all Filters in the servlet context and establish their priority/url mapping and add them appropriately. This seems error prone and unnecessary.
I agree that MockMVC is perhaps more for testing SpringMVC and custom code in controllers, as commented by #dave-syer. So in cases when one wants to test spring MVC infrastructure with your custom controller code at the same time (correctness of controllers mapped to URLs; mapping and validation of input and output objects; standard controllers; your controllers) without leveraging the Servlet container part of the stack, MockMVC is there for you.
But MockMVC also does have methods to add filters, so it is designed with a possibility to engage Filters in the described type of testing. Sometimes filter may play functional role for code inside of a controller and that would be otherwise not testable with MockMVC.
With all that theory in mind I was trying to mimic Boot behaviour for my tests where filters would be set up in Spring Boot way and picked up by my tests to be used with MockVMC. Here is a snippet that I ended up using. It can surely be enhanced to mimic Boot behaviour in more precisely and extracted to some custom MockMVCBuilder.
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setUp() {
Collection<Filter> filterCollection = wac.getBeansOfType(Filter.class).values();
Filter[] filters = filterCollection.toArray(new Filter[filterCollection.size()]);
mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(filters).build();
}
Have you tried this?
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
...
#Slf4j
#RunWith(SpringRunner.class)
#SpringBootTest
public class AuthorizeTest {
#Autowired
private WebApplicationContext wac;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.apply(springSecurity())
.build();
}
...
}
In my case it is 403, not 401, but you get the idea.