Is there a way to configure Spring Security (with Java config) in order to secure custom pages only, or even work upon #PreAuthorized annotation?
The idea is that I want to secure custom calls like /admin and other stuff (without hardcoding every call in the security configuration), which is set up in the controller under the mentioned annotation, but the other stuff shouldn't use authentication at all.
I had a hard time finding something which would work for me. That does the trick and it's also very readable.
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ADMIN')")
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin();
}
and the full Class for those who are still not on the same page
package com.your.package.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.*;
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ADMIN')")
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}
Note that not calling the formLogin() method would make the default "/login" return a 404 error.
I am not sure if this answers your question, but you could use ant matchers to identify certain pages and ignore others in your security configuration, like so:
.antMatchers("/**").permitAll()
or
.antMatcher("/admin/**")
.authorizeRequests()
.anyRequest().authenticated()
Related
My aim is to add security class to my Java project except paths like "api/public/*".
When I request in POSTMAN
http://localhost:8080/api/public/signup
with a json body, I get 401. Here's my security class which permits all matchers of api/public/*:
What am I missing?
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// we don't need CSRF because our token is invulnerable
.cors()
.and()
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
// don't create session
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.anyRequest().authenticated();
// Custom JWT based security filter
JwtAuthorizationTokenFilter authenticationTokenFilter = new JwtAuthorizationTokenFilter(userDetailsService(), jwtTokenUtil);
httpSecurity
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// disable page caching
httpSecurity
.headers()
.frameOptions().sameOrigin() // required to set for H2 else H2 Console will be blank.
.cacheControl();
}
#Override
public void configure(WebSecurity web) throws Exception {
// AuthenticationTokenFilter will ignore the below paths
web
.ignoring()
.antMatchers("/api/public/*");
}
Mvn clean solved my problem. It seems build somehow stuck in a previous state.
mvn clean
I am having an issue in my spring app, basically I have overridden the configure method for WebSecurity in angular to use SAMEORIGIN as the X-FRAME-OPTION which works and applies the header.
#EnableWebSecurity
#Order(95)
public class CCWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN));
}
}
However I include a usersecurity library which also overrides the configure method, the method for this can be seen below:
Am I correct in saying it is the 'csrf().disable()' that is responsible for the X-FRAME-OPTIONS - DENY being applied?
Ideally I wanted to avoid changing the usersecurity library as there are many other of my spring apps relying on this.
You can allow multiple URLs as follows, But I don't know weather this is the proper way or not. but it works properly.
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable().authorizeRequests().anyRequest().permitAll()
.and()
.headers().defaultsDisabled()
.and()
.cors()
.and()
.headers()
.cacheControl()
.and()
.contentTypeOptions()
.and()
.httpStrictTransportSecurity().disable()
.and()
.headers()
.frameOptions().disable()
.addHeaderWriter(new StaticHeadersWriter("X-FRAME-OPTIONS",
"ALLOW-FROM example1.com",
"ALLOW-FROM example2.com",
"ALLOW-FROM example3.com",
"ALLOW-FROM example4.com",
"ALLOW-FROM example5.com"));
}
We use the Spring MVC framework (incl. Spring Security) to implement both a web page and a REST web service. Both are supposed to support username/password authentication. However, they should implement two separate security realms with separate user databases.
The problem we're facing is that Spring security merges the two separate authentication providers into a single list of authentication providers and checks all username/password pairs against both providers. How can we have separate authentication providers for the two realms?
We have tried to separate the realms by using separate roles/authorities. However, if the credentials of the web pages are used to authenticate against the web service, it results in a 403 error (Forbidden) instead of a 401 error (Unauthorized). And since we have to keep perfect backward compatibility with pre-Spring implementation, this is a problem.
Furthermore, we've also tried to split the configuration into several non-inner classes (as proposed in https://stackoverflow.com/a/32756938/413337). However, that didn't help either.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Configuration
#Order(1)
public static class WebServiceConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new WebServiceUsernamePasswordAuthenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/service/**")
.hasRole("SERVICE")
.and()
.anonymous().disable()
.httpBasic();
}
}
#Configuration
#Order(2)
public static class WebPagesConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new WebPagesUsernamePasswordAuthenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/", false);
}
}
}
Update:
We have implemented a solution by creating a copy of the BasicAuthenticationFilter and UsernamePasswordAuthenticationToken class and using them for the web service only. However, we would still prefer a solution without code duplication. Could the approach be to create separate authentication manager instances for the two realms?
So I'm new to Spring, and learning in the way as I develop a web application using Spring-Boot.
Currently my page consists of two html pages: index.html and login.html. I'm also using Spring-Security.
Here's my current MvcConfig:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/login").setViewName("login");
}
}
The way the website is designed, an user goes to the url http://localhost:8080, then he/she is presented with the initial page, there's a login tab there where he/she can log in, and move to the dashboard view (which I will add later).
However, when I load the initial, the page is totally misconfigured (css / js / images resources aren't loaded). After I go to http://localhost:8080/login, perform the login and everything works again.
Therefore, any url of the form http://localhost:8080 is to be allowed (index.html), but anything else would require login.
Here's my Spring-Security config:
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.regexMatchers("/", "/index").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
How can I correctly configure my webpage?
*** Notes:
* I currently don't have any Controller class.
problem with regex matchers that i found is any resource loaded from your server you will need to account for in the mapping.
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login", "/admin").hasRole('ADMIN') // e.g. for pages that need to be authenticated
.anyRequest().permitAll() // all the others will be accessable by all
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
The most simplest way to do matching is following steps:
Declare your resource files by overriding addResourceHandlers
Use antmatchers to handle url security (simpler and easier), unless you have extremely dynamic urls with critical parameter
sorry guy, I will try to make it clear
anyRequest().authenticated() make your request to html resource need to authorized. You only permitAll to '/' & '/login'
so, add permitAll to css, js, image too
http
.authorizeRequests()
.regexMatchers("/", "/index").permitAll()
.antMatchers("/**/*.js", "/**/*.css").permitAll()
or more easy, make a style for login page. no depend on other static resource.
I've been playing around with Spring for the last few days and things are getting to be fun. I'm working with security right now and I've run into a slight snag. Basically, I want the authentication to happen via an API call rather than a form. Is there a neat way to do this?
I've extended the WebSecurityConfigurerAdapter like so -
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.antMatchers("/openapi/**").hasRole("USER")
.anyRequest().authenticated();
http
.formLogin()
.defaultSuccessUrl("/hello")
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
authManagerBuilder.inMemoryAuthentication()
.withUser("manager").password("password").roles("MANAGER");
}
}
Is there a way to pick up the the usernames and passwords from a database and can I perform the authentication with an API call?
Spring Security 3 database authentication with Hibernate
This seems promising. It needs a custom authentication manager created.
You can use jdbc authentication with Java configuration as described in the reference http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#jc-authentication-jdbc