Spring Security : HttpSecurity vs WebSecurity - java

I'm unable to differentiate between the following HttpSecurity and WebSecurity methods.
#Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity
.ignoring()
.antMatchers(HttpMethod.POST, "/api/v1/register");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers(HttpMethod.POST, "/api/v1/register").permitAll();
}
ignoring() and permitAll() makes the URLs as open URL, thus giving access to un-authenticated users also.
But when to use which method ?
HttpSecurity.authenticated() method gives access to all authenticated users, irrespective of role.
But, what is the difference between WebSecurity. ignoring() and HttpSecurity.permitAll() ?

Related

Setup Spring security to redirect user to login page if not authenticated

I have a Spring boot application with Spring security.
My problem is similar to this one, but in my case I want to redirect the user to the login page if he's not authenticated when he tries to access any page of the application.
The following image shows the architecture of the application:
My config class looks like this:
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**").hasAnyRole("USER")
.and().formLogin().loginPage("/login").permitAll()
.and().authorizeRequests().antMatchers("/resources/**").permitAll().anyRequest().permitAll();
}
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}
With this configuration, no resource will be loaded.
How can I configure my project to redirect the user to the login page if he's not authenticated and at the same time having my resources folder loaded?
plz checkout configure method
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/login*").permitAll()
.anyRequest().authenticated()
.and().formLogin().loginPage("/login");
}
and implements WebMvcConfigurer Class like below
#Configuration
#EnableWebMvc
public class WebMvcConfiguration implements WebMvcConfigurer {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
}
addResourceHandlers means find resources in /static.
Spring security is not allowing your css when a "GET" request to it is made allow it by changing the following line to the next line
this line = .antMatchers("/*.js").permitAll()
this line = .antMatchers("/*.js", "/*.css").permitAll()
Update your method by using authenticated() like below.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login*").
.antMatchers("/resources/**").permitAll()
.antMatchers("/*.js").permitAll()
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin();
}
Refer this article
I had this problem in my login page before authentication, I found it and resolved my problem by overrode this method in SecurityConfig
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/resources/**");
}
afterward login page knew .js and .css

Spring: Config API using ResourceServerConfigurerAdapter

I have some APIs like this: api/{id}/action/{action} and want to add them to security.
#Override
public void configure(HttpSecurity http) throws Exception {
.antMatchers(HttpMethod.PUT, "api/*/action/*").access("hasAnyRole('View_account','Search_account')");
}
when I use the account without role: View_account and Search_account. This API still works well not response 403. Please advise me how to config security with multiple path variable.
You should use regexp for path variables:
#Override
public void configure(HttpSecurity http) throws Exception {
.antMatchers(HttpMethod.PUT, "api/{\\d+}/action/**")
.access("hasAnyRole('View_account','Search_account')");
}
In this case {\\d+} means that your id is digit

Spring Security with JWT

I am trying to develop Spring Security project with JWT.
I want access Login api with out Spring Security (without JWT token). But with below configuration, every time (for login api as well) it is checking for JWT token giving me 403 error.
Below is my WebSecurityConfig.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthFilter jwtAuthFilter;
#Autowired
private TokenAuthenticationService jwtAuthenticationProvider;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jwtAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/api/v1/login");
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/api/v1/login")
.permitAll()
.and()
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Thanks in advance
For login path configuration something like this can be used:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
.usernameParameter("username") // default is username
.passwordParameter("password") // default is password
.loginPage("/authentication/login") // default is /login with an HTTP get
.failureUrl("/authentication/login?failed") // default is /login?error
.loginProcessingUrl("/authentication/login/process"); // default is /login
// with an HTTP
// post
}
If some paths need to be ignored configure(WebSecurity web) can be overridden:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/v1/somepath").antMatchers("/static/**");
}
There is filter class named JwtAuthFilter that is being executed before every service you call.
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
this code provides to be executed filter before every request, but its okay, you have to see this FilterClass there must be some check if token doesnt exist filter class must be returned and request will directly go to the login service. if you can show that Filter class and I will help you.

Spring Security ignore path for filter

How can I configure Spring Security to use a custom filter for all requests except the ones I whitelist in the same level, e.g. "/login" skips my filter but every thing else "/**" goes through the filter.
As a workaround I could use different prefixes, "/secured/**" vs "/whitelist/**" or ignore the whitelisted ones in the filter, but that does not seem to be a clean solution.
I already tried setting up two configurations with #Order(1 and 2) but it didn't work.
#EnableWebSecurity
public class SpringSecurityConfig {
#Configuration
#Order(1)
#EnableGlobalMethodSecurity(securedEnabled = true)
public static class JwsSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private StatelessAuthenticationFilter statelessAuthenticationFilter;
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/login");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").authenticated()
.anyRequest().authenticated()
.and().addFilterBefore(statelessAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return authenticationManager();
}
}
}

spring-security login?logout redirects to login

I am using spring-security 3.2.0.RC2 with java config and two HttpSecurity configurations. One for REST API and one for UI.
When I post to /logout it redirects to /login?logout but then (incorrectly) redirects to /login.
When i enter username and password successfully I get redirected to login?logout and have to enter credentials a second time to get to the main page.
So it seems like the permitAll for login is not being honored for login?logout.
My security config looks like this:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Resource
private MyUserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
StandardPasswordEncoder encoder = new StandardPasswordEncoder();
auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
}
#Configuration
#Order(1)
public static class RestSecurityConfig
extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/v1/**").authorizeRequests()
.antMatchers("/v1/admin/**").hasRole("admin")
.antMatchers("/v1/account/**").hasRole("admin")
.antMatchers("/v1/plant/**").access("hasRole('admin') or hasRole('dataProvider')")
.antMatchers("/v1/upload/**").access("hasRole('admin') or hasRole('dataProvider')")
.antMatchers("/v1/**").authenticated()
.and().httpBasic();
}
}
#Configuration
#Order(2)
public static class UiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/account/**").hasRole("admin")
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/plant/**").access("hasRole('admin') or hasRole('dataProvider')")
.antMatchers("/upload/**").access("hasRole('admin') or hasRole('dataProvider')")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll();
}
}
}
Can anyone explain why this is happening or what is wrong with my configuration?
A secondary problem that I see with this configuration is that the jsp tag sec:authorize url=... does not work although sec:authorize access=... does work.
In the url=... case it always shows the content even if the user is not authorized.
I know the user is not authorized becuase hitting the link that should have been hidden by the sec:authorize tag results in a 403 Forbidden.
Any help on this greatly appreciated!
I found a workaround for this apparent bug.
I added permitAll() on /login/** as follows:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/account/request/**").permitAll()
.antMatchers("/login/**").permitAll()
.antMatchers("/account/change_password/**").authenticated()
.antMatchers("/account/**").hasAuthority("admin")
.antMatchers("/admin/**").hasAuthority("admin")
.antMatchers("/plant/**").hasAnyAuthority("admin", "dataProvider")
.antMatchers("/upload/**").hasAnyAuthority("admin", "dataProvider")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll();
}
Answering my own question in case it helps anyone else who runs into this bug.
Instead of this:
.antMatchers("/login/**").permitAll()
I think the better solution would be this:
http
.authorizeRequests()
.antMatchers("/account/request/**").permitAll()
.*antMatchers("/login").permitAll()
.antMatchers("/account/change_password/**").authenticated()
.antMatchers("/account/**").hasAuthority("admin")
.antMatchers("/admin/**").hasAuthority("admin")
.antMatchers("/plant/**").hasAnyAuthority("admin", "dataProvider")
.antMatchers("/upload/**").hasAnyAuthority("admin", "dataProvider")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll().
.and().logout().logoutSuccessUrl("/login?logout").permitAll();
The reason being, url pattern for permitAll(), in this case has limited scope when compared to "/login/**"

Categories