404 error using Spring MVC Security Java Config on JBoss - spring-mvc

I wrote a small Spring MVC application with Java Config and secured it with Spring Security 3.2.5. It is working perfectly fine on Tomcat but not on JBoss EAP 6.2. It gets successfully deployed on JBoss but I get this warning when I request any page defined by Spring MVC and 404 error in browser.
WARN [org.springframework.web.servlet.PageNotFound] (http-/127.0.0.1:8080-1) No mapping found for HTTP request with URI [/example-web/pages/login.jsp] in DispatcherServlet with name 'dispatcher'
Since Spring Security is used, for any request that needs authenticated user e.g. http://localhost:8080/example-web/start, Spring Security redirects to https://localhost:8443/example-web/login That is when I see the warning and 404 error.
Here you can see my code:
public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfiguration.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/*" };
}
#Override
protected Filter[] getServletFilters() {
return new Filter[] { new HiddenHttpMethodFilter() };
}
}
Here is my Spring MVC configuration:
#EnableWebMvc
#ComponentScan("com.spring.example.w.controller")
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
#Bean
public InternalResourceViewResolver getInternalResourceViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/pages/");
resolver.setSuffix(".jsp");
return resolver;
}
}
Below is my Spring Security configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.addFilter(myUsernamePasswordAuthenticationFilter())
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/admin/**").hasRole("Admin")
.antMatchers("/start/**").hasRole("Viewer")
.antMatchers("/user/**").hasRole("User")
.antMatchers("/**").hasRole("User")
.and()
.httpBasic().authenticationEntryPoint(loginUrlAuthenticationEntryPoint())
.and()
.logout()
.permitAll()
.and()
.requiresChannel()
.anyRequest().requiresSecure();
}
#Bean
public LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint(){
LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint = new LoginUrlAuthenticationEntryPoint("/login");
return loginUrlAuthenticationEntryPoint;
}
#Bean
public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider(){
ActiveDirectoryLdapAuthenticationProvider authProvider = new ActiveDirectoryLdapAuthenticationProvider(my_domain, my_url);
authProvider.setConvertSubErrorCodesToExceptions(true);
authProvider.setUseAuthenticationRequestCredentials(true);
authProvider.setUseAuthenticationRequestCredentials(true);
authProvider.setUserDetailsContextMapper(userDetailsContextMapper());
return authProvider;
}
#Bean
public UserDetailsContextMapper userDetailsContextMapper(){
CustomUserDetailsContextMapper myAuthoritiesPopulator = new CustomUserDetailsContextMapper();
return myAuthoritiesPopulator;
}
#Bean
public CustomUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter()
throws Exception {
CustomUsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new CustomUsernamePasswordAuthenticationFilter();
usernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
usernamePasswordAuthenticationFilter.setAllowSessionCreation(true);
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
usernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(successHandler);
usernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/login?error"));
usernamePasswordAuthenticationFilter.afterPropertiesSet();
return usernamePasswordAuthenticationFilter;
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
}
Then SecurityWebApplicationInitializer:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
And RootConfig:
#Configuration
#ComponentScan
public class RootConfiguration {
}
And below is how I configured JBoss for SSL:
<subsystem xmlns="urn:jboss:domain:web:1.5" default-virtual-server="default-host" native="false">
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http" redirect-port="8443"/>
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" enable-lookups="false" secure="true">
<ssl name="ssl" password="<my_password>" certificate-key-file="c:\mykeystore.jks" protocol="TLSv1" verify-client="false"/>
</connector>
<virtual-server name="default-host" enable-welcome-root="true">
<alias name="localhost"/>
<alias name="example.com"/>
</virtual-server>
</subsystem>
During deployment, I can see in the log that the requests do get mapped:
INFO [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] (ServerService Thread Pool -- 71) Mapped "{[/start],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView com.spring.example.w.controller.StartController.handleStart() throws javax.servlet.ServletException,java.io.IOException
INFO [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping] (ServerService Thread Pool -- 71) Mapped URL path [/login] onto handler of type [class org.springframework.web.servlet.mvc.ParameterizableViewController]
INFO [org.springframework.web.context.ContextLoader] (ServerService Thread Pool -- 71) Root WebApplicationContext: initialization completed in 2530 ms
INFO [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/example-web]] (ServerService Thread Pool -- 71) Initializing Spring FrameworkServlet 'dispatcher'
INFO [org.springframework.web.servlet.DispatcherServlet] (ServerService Thread Pool -- 71) FrameworkServlet 'dispatcher': initialization started
Any help about why I get 404 error and this warning is highly appreciated. Once again I should emphasize that it is working on Tomcat. Thanks in advance.

Can you check if the connector port is enabled for SSL. This link has some details.
Redirecting from non ssl port 8080 to ssl port 8443
hope it helps

Related

Spring Boot with Jersey and Spring Security OAuth2

Following the sample from Spring Boot: example code from GitHub everything seems to work fine.
But when I integrate Spring Boot Security OAuth2 in the project, my OAuth2 endpoints stop working. There's a warning in the logs:
2017-05-04 08:56:24.109 WARN 2827 --- [nio-8080-exec-1] o.glassfish.jersey.servlet.WebComponent : A servlet request to the URI http://127.0.0.1:8080/oauth/token contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
Which makes me think even though I'm not registering the endpoint, Jersey is capturing it and processing the body, making Spring MVC unable to accept the request...
My Jersey Config is:
#Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(InfoController.class);
}
}
And my info controller is very simple:
#Component
#Path("/me")
#Produces("application/json")
public class InfoController {
#GET
public String meAction() {
return "Hi";
}
}
And finally, the call I'm trying to make and it's causing the warning in the logs:
curl -X POST -u CLIENT_APPLICATION:123456789 http://127.0.0.1:8080/oauth/token -H "Accept: application/json" -d "password=aaa&username=aa&grant_type=password&client_id=CLIENT_APPLICATION"
Is there a known incompatibility between the two projects (spring-boot-starter-jersey and spring-security-oauth2 in that sense?
Removing the Jersey configuration makes it all work, but I need to use it on my controllers.
My configuration for OAuth2 is:
#Configuration
public class OAuth2ServerConfiguration {
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("OAuth2 Server");
}
#Override
public void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.authorizeRequests()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/*").authenticated();
// #formatter:on
}
}
}
Then there's the security configuration itself:
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final ApiUserDetailsService userDetailsService;
#Autowired
public WebSecurityConfiguration(ApiUserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Thanks in advance!
It seems that Jersey is trying the handle the OAuth endpoint, which it shouldn't be. The reason is that the default mapping for Jersey is /*, which means that it will handle requests for all URLs. You can change that in a couple of ways:
Add an #ApplicationPath on top of your ResourceConfig subclass with a different mapping
#Component
#ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig {}
You can add the mapping in your application.properties file
spring.jersey.application-path=/api
What this will do is prefix /api to all your Jersey endpoints, and also cause Jersey not to handle all request, only ones that begin with /api.

Spring OAuth2 uses wrong authentication details for a token

I am having following configuration in Spring Security wiht OAuth2:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
//#EnableOAuth2Sso
public class FVSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("secret")
.roles("USER", "ROLE1")
.and()
.withUser("admin")
.password("password")
.roles("ADMIN","USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").hasRole("USER")
.anyRequest().authenticated()
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler())
.and()
.formLogin();
}
Resource server configuraion:
#Configuration
#EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.inMemory()
.withClient("sampleClient")
.authorizedGrantTypes("implicit")
.scopes("read")
.autoApprove(true)
.accessTokenValiditySeconds(30)
.and()
.withClient("user")
.secret("secret")
.scopes("read", "write")
.autoApprove(true)
.authorizedGrantTypes(
"password","authorization_code", "refresh_token")
.and()
.withClient("admin")
.secret("password")
.scopes("read", "write", "custom")
.autoApprove(true)
.authorizedGrantTypes(
"password","authorization_code", "refresh_token");
}
And the following Rest Controller
#RestController
public class OAuthTestController {
#PreAuthorize("hasRole('ROLE_ROLE1') and #oauth2.hasScope('read')")
#RequestMapping(value="/api/user/test1", method = RequestMethod.GET)
public String testGETWithRole() {
return "[GET] Needs role ROLE1";
}
#RequestMapping(value="/api/admin/test1", method = RequestMethod.GET)
public String testWithAdminRole() {
return "[GET] Needs Admin role";
}
And the resource server:
#Configuration
#EnableResourceServer
public class ResourceServer extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my_rest_api";
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.requestMatchers().antMatchers("/api/**")
.and().authorizeRequests()
.antMatchers("/api/**").access("hasRole('USER')")
.antMatchers("/api/admin/**").access("hasRole('ADMIN')")
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
Basically I am expecting Spring to use OAuth2 for authentication and use spring security roles to allow resource access.
I generated and admin token and afterwards an user token. I am expecting when using admin token to be able to access /api/admin resource and when using user token to not be able.
I just noticed that the form login is not prompted always, so I suppose Spring remembers the authenticated user.
When I used the admin token I got access denied. When debugging in Spring sources I noticed that the authentication was an instance of UserNamePasswordAuthenticationPassword with the user details, not admin as expected. I suppose is because last time I used those credentials in login form.
Is it a way to force spring to use credentials for corresponding token, or to force Spring show login form each time?
P.S. I use Postman to test the API.
Thanks.

spring security webSecurity.ignoring()

I am using spring security via spring boot.
I have two kinds of rest services.
public/** --> Every one can access and use these services
secure/** --> Only authenticated users can use.
#Slf4j
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("/public/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(requestHeaderAuthenticationFilter(authenticationManager()),
BasicAuthenticationFilter.class)
.authorizeRequests().antMatchers("/secure/**").fullyAuthenticated();
}
#Bean
public RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter(
final AuthenticationManager authenticationManager) {
RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager);
filter.setExceptionIfHeaderMissing(true);
filter.setPrincipalRequestHeader("MY_HEADER");
filter.setInvalidateSessionOnPrincipalChange(true);
filter.setCheckForPrincipalChanges(false);
filter.setContinueFilterChainOnUnsuccessfulAuthentication(false);
return filter;
}
When i want to access a resource under public i got exception.
exception: "org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException"
message: "MY_HEADER header not found in request."
Why does my filter activated under public resource while it is configured as ignored resource?
Thanks is advance
This is an issue in WebSecurity.ignoring() as discussed in Spring Security Github when using Beans as Filters.
You can work around this by removing the #Bean annotation in your Filter declaration.
// #Bean - Remove or Comment this
public RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter(
final AuthenticationManager authenticationManager) {
RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager);
filter.setExceptionIfHeaderMissing(true);
filter.setPrincipalRequestHeader("MY_HEADER");
filter.setInvalidateSessionOnPrincipalChange(true);
filter.setCheckForPrincipalChanges(false);
filter.setContinueFilterChainOnUnsuccessfulAuthentication(false);
return filter;
}

Spring Oauth2 Authorization Server

I setting the Spring Configuration Below:
#EnableAuthorizationServer
#EnableWebSecurity
#Configuration
public class Oauth2Provider extends WebSecurityConfigurerAdapter implements
AuthorizationServerConfigurer {
/*
* #Autowired private TokenStore tokenStore;
*/
#Configuration
protected static class AuthenticationConfiguration extends
GlobalAuthenticationConfigurerAdapter {
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password")
.roles("USER").and().withUser("admin").password("password")
.roles("USER", "ADMIN");
}
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security)
throws Exception {
// TODO Auto-generated method stub
security.allowFormAuthenticationForClients();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
// TODO Auto-generated method stub
clients.inMemory()
.withClient("my-trusted-client")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT", "ROLE_ANONYMOUS")
.scopes("read", "write", "trust")
.secret("secret")
.accessTokenValiditySeconds(60);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
// TODO Auto-generated method stub
}
}
And Maven Setting is Below:
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
I Access :
http://localhost:8080/oauth/token
Payload
grant_type=password&password=password&username=user&scope=read&client_id=my-trusted-client&client_secret=secret
But I receive error below:
{
error: "unsupported_grant_type"
error_description: "Unsupported grant type: password"
}
To use password grant you need to provide an authentication manager to the authorization server (in the empty method with the TODO in your example), so it can authenticate users. If it's a Spring Boot application there is always an AuthenticationManager available to be #Autowired.

Serving static web resources in Spring Boot & Spring Security application

I am trying to develop Spring Boot web application and securing it using Spring security java configuration.
After placing my static web resources in 'src/main/resources/public' as advised here in Spring blog, I am able to get the static resources. i.e hitting https://localhost/test.html in browser do serves the html content.
Problem
After I enabled Spring Security, hitting the static resource URL requires authentication.
My relevent Spring Security Java config looks like this:-
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.
authorizeRequests()
.antMatchers("/","/public/**", "/resources/**","/resources/public/**")
.permitAll()
.antMatchers("/google_oauth2_login").anonymous()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/home")
.and()
.csrf().disable()
.logout()
.logoutSuccessUrl("/")
.logoutUrl("/logout") // POST only
.and()
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.addFilterAfter(oAuth2ClientContextFilter(),ExceptionTranslationFilter.class)
.addFilterAfter(googleOAuth2Filter(),OAuth2ClientContextFilter.class)
.userDetailsService(userService);
// #formatter:on
}
How should I configure antMatchers to permit static resources placed inside src/main/resources/public ?
There are a couple of things to be aware of:
The Ant matchers match against the request path and not the path of the resource on the filesystem.
Resources placed in src/main/resources/public will be served from the root of your application.
For example src/main/resources/public/hello.jpg would be served from http://localhost:8080/hello.jpg
This is why your current matcher configuration hasn't permitted access to the static resources. For /resources/** to work, you would have to place the resources in src/main/resources/public/resources and access them at http://localhost:8080/resources/your-resource.
As you're using Spring Boot, you may want to consider using its defaults rather than adding extra configuration. Spring Boot will, by default, permit access to /css/**, /js/**, /images/**, and /**/favicon.ico. You could, for example, have a file named src/main/resources/public/images/hello.jpg and, without adding any extra configuration, it would be accessible at http://localhost:8080/images/hello.jpg without having to log in. You can see this in action in the web method security smoke test where access is permitted to the Bootstrap CSS file without any special configuration.
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**"); // #3
}
Ignore any request that starts with "/resources/". This is similar to configuring http#security=none when using the XML namespace configuration.
This may be an answer (for spring boot 2) and a question at the same time.
It seems that in spring boot 2 combined with spring security everything (means every route/antmatcher) is protected by default if you use an individual security mechanism extended from
WebSecurityConfigurerAdapter
If you don´t use an individual security mechanism, everything is as it was?
In older spring boot versions (1.5 and below) as Andy Wilkinson states in his above answer places like public/** or static/** are permitted by default.
So to sum this question/answer up - if you are using spring boot 2 with spring security and have an individual security mechanism you have to exclusivley permit access to static contents placed on any route. Like so:
#Configuration
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final ThdAuthenticationProvider thdAuthenticationProvider;
private final ThdAuthenticationDetails thdAuthenticationDetails;
/**
* Overloaded constructor.
* Builds up the needed dependencies.
*
* #param thdAuthenticationProvider a given authentication provider
* #param thdAuthenticationDetails given authentication details
*/
#Autowired
public SpringSecurityConfiguration(#NonNull ThdAuthenticationProvider thdAuthenticationProvider,
#NonNull ThdAuthenticationDetails thdAuthenticationDetails) {
this.thdAuthenticationProvider = thdAuthenticationProvider;
this.thdAuthenticationDetails = thdAuthenticationDetails;
}
/**
* Creates the AuthenticationManager with the given values.
*
* #param auth the AuthenticationManagerBuilder
*/
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(thdAuthenticationProvider);
}
/**
* Configures the http Security.
*
* #param http HttpSecurity
* #throws Exception a given exception
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers("/management/**").hasAnyAuthority(Role.Role_Engineer.getValue(),
Role.Role_Admin.getValue())
.antMatchers("/settings/**").hasAnyAuthority(Role.Role_Engineer.getValue(),
Role.Role_Admin.getValue())
.anyRequest()
.fullyAuthenticated()
.and()
.formLogin()
.authenticationDetailsSource(thdAuthenticationDetails)
.loginPage("/login").permitAll()
.defaultSuccessUrl("/bundle/index", true)
.failureUrl("/denied")
.and()
.logout()
.invalidateHttpSession(true)
.logoutSuccessUrl("/login")
.logoutUrl("/logout")
.and()
.exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler());
}
}
Please mind this line of code, which is new:
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
If you use spring boot 1.5 and below you don´t need to permit these locations (static/public/webjars etc.) explicitly.
Here is the official note, what has changed in the new security framework as to old versions of itself:
Security changes in Spring Boot 2.0 M4
I hope this helps someone.
Thank you!
Have a nice day!
Here is the ultimate solution, after 20+ hours of research.
Step 1. Add 'MvcConfig.java' to your project.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
}
Step 2. Add configure(WebSecurity web) override to your SecurityConfig class
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
Step 3. Place all static resources in webapp/resources/..
If you are using webjars. You need to add this in your configure method:
http.authorizeRequests().antMatchers("/webjars/**").permitAll();
Make sure this is the first statement. For example:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/webjars/**").permitAll();
http.authorizeRequests().anyRequest().authenticated();
http.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.usernameParameter("email")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("remember-me")
.logoutSuccessUrl("/")
.permitAll()
.and()
.rememberMe();
}
You will also need to have this in order to have webjars enabled:
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
...
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
...
}
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
String[] resources = new String[]{
"/", "/home","/pictureCheckCode","/include/**",
"/css/**","/icons/**","/images/**","/js/**","/layer/**"
};
http.authorizeRequests()
.antMatchers(resources).permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout().logoutUrl("/404")
.permitAll();
super.configure(http);
}
}
i had the same issue with my spring boot application, so I thought it will be nice if i will share with you guys my solution. I just simply configure the antMatchers to be suited to specific type of filles. In my case that was only js filles and js.map. Here is a code:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/index.html", "/", "/home",
"/login","/favicon.ico","/*.js","/*.js.map").permitAll()
.anyRequest().authenticated().and().csrf().disable();
}
}
What is interesting. I find out that resources path like "resources/myStyle.css" in antMatcher didnt work for me at all. If you will have folder inside your resoruces folder just add it in antMatcher like "/myFolder/myFille.js"* and it should work just fine.
In the latest Spring Security 6, the WebSecurityConfigurerAdapter is deprecated.
Declare a WebSecurityCustomizer bean instead.
#Bean
public WebSecurityCustomizer ignoringCustomizer() {
return (web) -> web.ignoring().requestMatchers("...");
}
It,s work for spring security 6.0.*
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeHttpRequests()
.requestMatchers(
"/home/**",
"/login/**",
"/account/starter/**",
"/register/**",
"/plugins/**",
"/dist/**",
"/js/**",
"/**/favicon.ico").permitAll()
.and()
.httpBasic()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
return http.build();
}
"/plugins/**",
"/dist/**",
"/js/**",
... they are located in resources/
plugins, dist, js - these are the names of directories with resources

Resources