Spring boot: Log file has get requests to static files - spring

I have configured my app using
#Configuration
#EnableWebSecurity
#Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {...}
Inside configure method, allowed the static content.
http .httpBasic().and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/**/*.js", "/resources/static/**", "/static/**", "/**/*.jpg", "/**/*.svg", "/**/*.ico", "/**/*.gif", "/**/*.css", "/register")
.permitAll()
application.properties :
logging.level.web=debug
logging.level.org.springframework.web=debug
The problem i am having is that my log file is crowded by get requests to the static resources
I am just interested in logging access to controllers and not static files.
Is there something i need to configure to exclude the logging of access to static resources?
I have also tried
#Configuration
public class StaticConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/static/**")) {
registry.addResourceHandler("/static/**")
.addResourceLocations("/static/");
}
}
}

Issue
You have enabled debug level logging for org.springframework.web package, so it will log everything
Try this solution
Remove the debug level logging for org.springframework.web
Create a subclass of CommonsRequestLoggingFilter
public class CustomRequestLoggingFilter extends CommonsRequestLoggingFilter {
#Override
protected boolean shouldLog(HttpServletRequest request) {
return logger.isDebugEnabled() &&
!request.getRequestURL().toString().contains("/static")
}
}
Create that filter as a bean
#Configuration
public class RequestLoggingFilterConfig {
#Bean
public CustomRequestLoggingFilter logFilter() {
CustomRequestLoggingFilter filter
= new CustomRequestLoggingFilter();
filter.setIncludeQueryString(true);
filter.setIncludePayload(false);
filter.setMaxPayloadLength(10000);
filter.setIncludeHeaders(false);
filter.setAfterMessagePrefix("REQUEST DATA : ");
return filter;
}
}
Add the following to application.properties
logging.level.<package of your filter>.CustomRequestLoggingFilter=DEBUG

Related

Can not get user info with Spring Security SAML WITHOUT Spring Boot

I´m working on SAML integration in an older project but I can´t get the user information.
I've guided me with the response of this question:
https://stackoverflow.com/questions/70275050/spring-security-saml-identity-metadata-without-spring-boot
The project has these versions:
spring framework 5.3.24
spring security 5.6.10
opensaml 3.4.6
This is my code:
#Configuration
public class SAMLSecurityConfig {
private static final String URL_METADATA = "https://auth-dev.mycompany.com/app/id/sso/saml/metadata";
#Bean("samlRegistration")
public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations.fromMetadataLocation(URL_METADATA)
.registrationId("id")
.build();
return new InMemoryRelyingPartyRegistrationRepository(relyingPartyRegistration);
}
}
#EnableWebSecurity
public class WebSecurity {
#Configuration
#Order(2)
public static class SAMLSecurityFilter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.saml2Login(Customizer.withDefaults())
.antMatcher("/login/assertion")
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
}
#Controller("loginController")
public class BoCRLoginController {
#RequestMapping(value = "/login/assertion", method = {RequestMethod.POST},
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<String> assertLoginData(#AuthenticationPrincipal Saml2AuthenticatedPrincipal principal) {
System.out.println(principal); //here I get a null
return new ResponseEntity<>(HttpStatus.OK);
}
}
Once I did the login on okta the class: Saml2AuthenticatedPrincipal comes null value.
Could you help me to know why I received null value on the object Saml2AuthenticatedPrincipal where suppose have to receive the user information?

ServerHttpSecurity bean not found

I have a Security config class that has a SecurityWebFilterChain bean in it. This bean requires a ServerHttpSecuirty instance but spring says that it cannot find any beans of that type though there is one created in the external library (org.springframework.security.config.annotation.web.reactive.ServerHttpSecurityConfiguration). I have seen this issue on a github page and they said try a different version but I am using spring boot 2.4.5 so it should work.
My Security Config class:
#Configuration
public class SecurityConfig {
#Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http,
JwtTokenProvider tokenProvider,
ReactiveAuthenticationManager reactiveAuthenticationManager) {
final String TAG_SERVICES = "/api/**";
return http.csrf(ServerHttpSecurity.CsrfSpec::disable)
.httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
.authenticationManager(reactiveAuthenticationManager)
.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
.authorizeExchange(it -> it
.pathMatchers(HttpMethod.POST, TAG_SERVICES).hasAnyRole("USER","ADMIN")
.pathMatchers(HttpMethod.PUT, TAG_SERVICES).hasAnyRole("USER","ADMIN")
.pathMatchers(HttpMethod.GET, TAG_SERVICES).hasAnyRole("USER","ADMIN")
.pathMatchers(HttpMethod.DELETE, TAG_SERVICES).hasAnyRole("USER","ADMIN")
.pathMatchers(TAG_SERVICES).authenticated()
.anyExchange().permitAll()
)
.addFilterAt(new JwtTokenAuthenticationFilter(tokenProvider), SecurityWebFiltersOrder.HTTP_BASIC)
.build();
}
}
My application class
#ConfigurationPropertiesScan
#SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class TestPlatformBackendApplication {
public static void main(String[] args) {
SpringApplication.run(TestPlatformBackendApplication.class, args);
}
}
External Library Bean:
#Bean({"org.springframework.security.config.annotation.web.reactive.HttpSecurityConfiguration.httpSecurity"})
#Scope("prototype")
ServerHttpSecurity httpSecurity() {
ServerHttpSecurityConfiguration.ContextAwareServerHttpSecurity http = new ServerHttpSecurityConfiguration.ContextAwareServerHttpSecurity();
return http.authenticationManager(this.authenticationManager()).headers().and().logout().and();
}
As Toerktumlare recommended in the comments (1, 2) I added #EnableWebFluxSecurity to my security config:
#Configuration
#EnableWebFluxSecurity
public class SecurityConfig {
But I also added the following to my exclude in the #SpringBootApplication annotation.
#ConfigurationPropertiesScan
#SpringBootApplication(exclude={DataSourceAutoConfiguration.class, SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class})
public class TestPlatformBackendApplication {
public static void main(String[] args) {
SpringApplication.run(TestPlatformBackendApplication.class, args);
}
}

PreAuthorize not getting honored over ResourceServerConfigurerAdaptor

I have a Spring Resource Server with Spring Security enabled. In Resource Server, i am extending the ResourceServerConfigurerAdaptor, some like the following.
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.anonymous().disable().requestMatcher(new OAuthRequestedMatcher()).authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/admin/**").hasAnyRole("ADMIN")
.anyRequest().authenticated();
}
private static class OAuthRequestedMatcher implements RequestMatcher {
public boolean matches(HttpServletRequest request) {
String auth = request.getHeader("Authorization");
boolean haveOauth2Token = (auth != null) && auth.toLowerCase().startsWith("bearer");
boolean haveAccessToken = request.getParameter("access_token") != null;
return haveOauth2Token || haveAccessToken;
}
}
}
Here i am expecting /api/admin/** to be accessible to ADMIN Role only.
Everything works fine till now.
But now i am trying to override this behavior at the method level using #PreAuthorize method level annotation.
Following is the RestController
#RestController
#RequestMapping("/api/admin/event")
public class ShunyaEventResource {
#Autowired
private ShunyaEventService eventService;
#PreAuthorize("hasRole('ADMIN') or #oauth2.hasScope('write')")
#PostMapping
public void createEvent(#RequestBody ShunyaEvent event, Principal user) {
eventService.create(event);
}
}
So, i want to allow /api/admin/event to be accessible to #oauth2 write scope as well. But this does not work, unless either i remove /api/admin/** from antmatcher altogether or i add #oauth2.hasScope('write') in antmatcher itself.
I have already defined the below configuration
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
Here my question is why Method Level security not working for an endpoint that is already covered by ResourceServerConfigurerAdapter? What is precedence of security filter when same endpoint is covered by MethodLevel Security (using PreAuthorize) and HttpSecurity antMatcher?
Really appreciate any help on this.

Adding patterns to addResourceHandler always returned error when want to serve static content

I went through all question here, all docs according to Spring and couldn't find solution which make my case work.
The case is that I would like to secure my application (Spring Boot with Angular 4) by Spring Security. So the first things which I did was to add two Configuration classes, ex:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.anyRequest().permitAll().and().httpBasic();
}
#Configuration
#EnableWebMvc
#ComponentScan("com.inventory")
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/", "/#/", "/resources/static/**")
.addResourceLocations("/resources/static/index.html", "/resources/static/index.html", "/resources/static/index.html");
}
}
#Controller
public class ViewController {
#RequestMapping(value = "/#/")
public String index() {
return "forward:/resources/static/index.html";
}
#RequestMapping(value = "/")
public String home() {
return "index.html";
}
}
As you see in Controller I tried to use to diffrent attempts to serve static content. Unfortunately all this returns:
There was an unexpected error (type=Internal Server Error, status=500).
Could not resolve view with name 'index.html' in servlet with name 'dispatcherServlet'
What am I doing wrong? Why I can't get this static content? Of course my static content is under resources/static and there are .js files and ex. index.html.

Configure spring boot to redirect 404 to a single page app [duplicate]

This question already has answers here:
Spring Boot with redirecting with single page angular2
(12 answers)
Closed 2 years ago.
I want to configure my Spring Boot app to redirect any 404 not found request to my single page app.
For example if I am calling localhost:8080/asdasd/asdasdasd/asdasd which is does not exist, it should redirect to localhost:8080/notFound.
The problem is that I have a single page react app and it runs in the root path localhost:8080/. So spring should redirect to localhost:8080/notFound and then forward to / (to keep route).
This is the full Spring Boot 2.0 example:
#Configuration
public class WebApplicationConfig implements WebMvcConfigurer {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/notFound").setViewName("forward:/index.html");
}
#Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer() {
return container -> {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
"/notFound"));
};
}
}
This should do the trick: Add an error page for 404 that routes to /notFound, and forward that to your SPA (assuming the entry is on /index.html):
#Configuration
public class WebApplicationConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/notFound").setViewName("forward:/index.html");
}
#Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return container -> {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
"/notFound"));
};
}
}
In case anyone stumbles here looking for how to handle Angular/React/other routes and paths in a Spring Boot app - but not always return index.html for any 404 - it can be done in a standard Spring controller RequestMapping. This can be done without adding view controllers and/or customizing the container error page.
The RequestMapping supports wild cards, so you can make it match against a set of well known paths (ie. angular routes etc.) in your application and only then return forward index.html:
#Controller
public class Html5PathsController {
#RequestMapping( method = {RequestMethod.OPTIONS, RequestMethod.GET}, path = {"/path1/**", "/path2/**", "/"} )
public String forwardAngularPaths() {
return "forward:/index.html";
}
}
Another option (borrowed from an old Spring article here: https://spring.io/blog/2015/05/13/modularizing-the-client-angular-js-and-spring-security-part-vii) is to use a naming convention:
#Controller
public class Html5PathsController {
#RequestMapping(value = "/{[path:[^\\.]*}")
public String redirect() {
return "forward:/index.html";
}
}
The above configuration will match all paths that do not contain a period and are not already mapped to another controller.
//add this controller : perfect solution(from jhipster)
#Controller
public class ClientForwardController {
#GetMapping(value = "/**/{path:[^\\.]*}")
public String forward() {
return "forward:/";
}
}
Here the security configuration (SecurityConfig.java)
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private Environment env;
#Autowired
private UserSecurityService userSecurityService;
private BCryptPasswordEncoder passwordEncoder() {
return SecurityUtility.passwordEncoder();
}
private static final String[] PUBLIC_MATCHERS = {
"/css/**",
"/js/**",
"/data/**",
"/sound/**",
"/img/**",
"/",
"/login",
"/logout,
"/error",
"/index2",
};
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().
/* antMatchers("/**").*/
antMatchers(PUBLIC_MATCHERS).
permitAll().anyRequest().authenticated();
//.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login");
http
.csrf().disable().cors().disable()
.formLogin().failureUrl("/login?error")
.defaultSuccessUrl("/index2")
.loginPage("/login").permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/?logout").deleteCookies("remember-me").permitAll()
.and()
.rememberMe()
.and()
.sessionManagement().maximumSessions(3600)
.and().
invalidSessionUrl("/login");
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
}
}
If not found any resource redirect to error page
#Controller
public class IndexController implements ErrorController{
private static final String PATH = "/error";
#RequestMapping(value = PATH)
public String error() {
return PATH;
}
#Override
public String getErrorPath() {
return PATH;
}
}
Error page like
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1000/xhtml"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<meta http-equiv="refresh" content="5;url=/login" />
<body>
<h1>Page not found please login the system!</h1>
</body>
</html>
Simply implementing the org.springframework.boot.web.servlet.error.ErrorController did the trick for me. I use SpringBoot 2.0 with React. (If you are interested in how to do that here is a boilerplate project made by me: https://github.com/archangel1991/react-with-spring)
#Controller
public class CustomErrorController implements ErrorController {
#Override
public String getErrorPath() {
return "/error";
}
}
I am not sure why is this working though.

Resources