I've been struggling for a few days over this. Aside from quirky things that seem to be happening inconsistently and unpredictably by simply commenting out a bit of code, running the program, and then uncommenting and running again, I'm failing to understand how overriding various configure methods are working.
I want WebSecurity to always ignore "/static/**".
Upon launching the application and navigating to the homepage, I can access all of the pages for which I have permitted all, but all of the content in "/static/**" is being ignored until after I have navigated to the login page and logged in as an authenticated user. So the application just appears as white pages with text, without any of the styling at all until logged in.
Here is the code for my AppSecurityConfig class. I have omitted the helper methods for handling success and failure of logging in, and I also have to different account types that serve different roles, so I have only included one account here for simplification. The part where I believe the problem exists is in the configure(WebSecurity web) method where I am calling the .ignoring() method and passing the "/static/**" arg. Thank you in advance:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CompanyService companyService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(companyService);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/static/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/",
"/account_registration",
"/candidate_registration",
"/addCandidate",
"/company_registration",
"/addCompany",
"/select_account_type",
"/candidate_login",
"/company_login").permitAll()
.antMatchers("/company_profile").hasRole("COMPANY")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/company_login")
.permitAll()
.successHandler(companyLoginSuccessHandler())
.failureHandler(companyLoginFailureHandler())
.and()
.logout()
.logoutSuccessUrl("/");
}
}
The path to my static folder is "src/main/resources/static", but I did what Sam said and opened the developer tools and realized that all of the contents within the "static" directory were being referenced directly. For example, there are directories referenced in this way: "/vendor/..." and "/images/...", that were being referenced but ignored due to security. There are also some files in the "static" directory like "app.css", "app.js" and "favicon.png" that are having some strange behavior. It appears that they are not being ignored but different colors and styling are being displayed unless I also add them as arguments to the .gitIgnoring() method like "/app.css" etc. This project was built by working through a TeamTreehouse tutorial and then refactoring and adding custom styling between a few people on my 6 person team, and I'm pretty sure there are multiple things under the hood inherited in this project that myself and the front end people are not understanding when it comes to the styling.
The fix that seems to work, although maybe not ideal, was removing "/static/**" from the .ignoring() method and replacing it with all of the contents that were actually inside the "static/" directory:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers( "/images/**",
"/vendor/**",
"/app.css",
"/app.js",
"/favicon.png");
}
Related
Currently in my SecurityConfig.java class file where I define my KeycloakWebSecurityConfigurerAdapter I want to define so that every GET request can be done by two different roles. But only one role can do the other types of HTTP requests (POST, PUT, PATCH etc). How can this be achieved in my code below:
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers(HttpMethod.GET).hasAnyRole("user", "admin")
.anyRequest().hasRole("admin");
}
What happens is that when trying to do POST request I get access denied 403. GET requests works fine. Any ideas?
You should disable csrf on your configure method :
public void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.csrf().disable().authorizeRequests().anyRequest().authenticated();
}
}
You should not use KeycloakWebSecurityConfigurerAdapter nor anything else from Keycloak libs for Spring, it is deprecated.
Instead, you can follow this tutorial which proposes two solutions based on:
spring-boot-starter-oauth2-resource-server which requires quite some Java conf
spring-addons-webmvc-jwt-resource-server which enables to configure most of security from properties (way simpler than preceding)
All tutorials linked here show how to map Keycloak roles to spring-security authorities (and will keep CSRF protection enabled, even for stateless resource-servers).
I have a quick issue which am not really sure how to sort this out yet.
The issue is that, I'm using Thymeleaf, and was working perfectly fine until I've introduced the Springboot security. Since then, the styling isn't working at all. Looks like the static folder isn't seen for some reason. I've tried several structures to make it work but still no luck. I've tried to include in resource folder static folder, then resource folder (again) with no luck. I've also tried to rename the static into public, still no luck. I've noticed that if you include the URL somewhere on the web it works but if you include the URL somewhere on your local machine doesn't work. So I'm 100% sure there is a problem with the structure of the folders or the Spring configuration.
Any help, would be really much appreciated.
Spring security configuration class:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin()
.loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.failureUrl("/login?error")
.defaultSuccessUrl("/default")
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/", "/static/**").permitAll()
.antMatchers("/createUser").hasRole("ADMIN")
.anyRequest().authenticated();
}
}
WebConfig class:
#Configuration
#EnableWebMvc
public class WebAppConfig {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
I want to restrict certain rest endpoints to be only for LDAP users in a certain group.
I followed the guide https://spring.io/guides/gs/authenticating-ldap/ to setup LDAP authentication which is working perfectly. So how do I restrict certain rest endpoints?
I tried
#PreAuthorize("hasRole('developers')")
#RequestMapping("/foo")
public String foo(HttpServletRequest request) {
return "Welcome to FOO " + request.getRemoteUser();
}
but it still lets users not in the developers group access that endpoint
You can modify your WebSecurityConfigurerAdapter configuration to something like:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.antMatchers("/foo").hasRole("developers")
.and()
.formLogin();
}
I am not exactly sure of the syntax and if that first rule will override your second rule, but it will be similar to that.
Or, you can try configuring security on a method by method basis like this sample.
#EnableGlobalMethodSecurity(securedEnabled=true) needed to be added to the webSecurityConfig. Once I did that I was able to use #Secured("ROLE_DEVELOPERS") and that method was then restricted to that role.
I would like to protect just a single URL, while allowing anonymous access for everything else.
The Java configuration examples i'm seeing in the internet all seem to indicate that you need to explicitly permitAll each and every URL, and appropriate hasRole for URLs that need to be protected. This in my case, creates a really unwieldy java code which I have modify every time I add a new URL to the application. Is there an easier java configuration that I can use.
And note also that in my case, the URL i'm protecting is a sub-resource, say employee/me, I would like employee/list, etc., to be anonymously accessible.
If you're using Java Configuration, you can use something like following in your configure method:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/employee/me").authenticated()
.antMatchers("/**").permitAll();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/employee/me").authenticated()
.antMatchers("/**").permitAll();
}
I am trying to secure my webapp such that all requests need to be made using https. I am using a Java based configuration, in particular I have a class which extends WebSecurityConfigurerAdapter. I have attempted to configure my security using the #Override protected void configure(HttpSecurity http) {} method as detailed here and here.
I've tried both of those and many variants of configuring the HttpSecurity object, as well as several variants of authentication. In almost all cases, I come up with the following issue:
[nio-8080-exec-2] o.a.coyote.http11.Http11NioProcessor : Error parsing HTTP request header
I tried doing some reading into this but a lot of the search results turned out to be dead ends for me. My assumption was that the solution that was hinted at in the two posts I referenced would give me roughly the correct answer, but is there any additional configuration I need to do before I can get https working? If so what is it, and if not, what am I missing here?
Below is my current configuration, which replicates the error described above (it is basically the default one plus the https channel):
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
// Specify the authentication mechanisms that will allow user access to the site.
#Autowired
public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
builder.inMemoryAuthentication()
.withUser("user").password("password").roles("ROLES_USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic()
.and()
.requiresChannel().anyRequest().requiresSecure();
}
}
On the front end I am getting an SSL Connection Error : Unable to make a secure connection to the server. This may be a problem with the server, or it may be requiring a client authentication certificate that you don't have.
As #M.Deinum mentioned in comments, the difficulty was in the fact that I had not configured SSL in my application.properties. Creating one akin to the following:
server.port=9090
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password={password}
security.require-ssl=true
Resolved the issue.