I am developing a project using spring boot with spring security, below is my security configuration
#Configuration
#EnableWebMvcSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource datasource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
http
.authorizeRequests()
.antMatchers("/ideate","/homecreate").permitAll()
.anyRequest().authenticated();
http
.authorizeRequests().anyRequest().authenticated();
http
.formLogin().failureUrl("/login?error")
.defaultSuccessUrl("/")
.loginPage("/login")
.permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login")
.permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager();
userDetailsService.setDataSource(datasource);
PasswordEncoder encoder = new BCryptPasswordEncoder();
auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
auth.jdbcAuthentication().dataSource(datasource);
}
}
After successful Log in of the user, i am calling a request mapping "/" written in the controller, the method will return a page which should contain username as model attribute how do i get the current logged in username?
Use the below code in your jsp ...
<%# taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<sec:authentication property="principal.username" />
This bit of code helped me to fetch the user information to the jsp.
Related
This question already has answers here:
Spring Security : Multiple HTTP Config not working
(2 answers)
Closed 1 year ago.
I have the following configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfig {
#Configuration
#Order(1)
public static class SamlConfig extends WebSecurityConfigurerAdapter {
#Value("${enable_csrf}")
private Boolean enableCsrf;
#Autowired
private SamlUserService samlUserService;
public SamlWebSecurityConfig() {
super();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/secure/sso").permitAll()
.antMatchers("/saml/**").permitAll()
.anyRequest().authenticated()
.and()
.apply(saml())
.userDetailsService(samlUserService)
.serviceProvider()
.keyStore()
.storeFilePath("path")
.password("password")
.keyname("alias")
.keyPassword("password")
.and()
.protocol("https")
.hostname(String.format("%s:%s","localhost", "8080"))
.basePath("/")
.and()
.identityProvider()
.metadataFilePath("metadata");
if (!enableCsrf) {
http.csrf().disable();
}
}
}
#Configuration
#Order(2)
public static class BasicConfig extends WebSecurityConfigurerAdapter {
public BasicWebSecurityConfig() {
super();
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/secure/basic").permitAll()
.anyRequest().authenticated();
if (!enableCsrf) {
http.csrf().disable();
}
}
}
This works for the SAML, but the basic login returns an error: 403 forbidden.
I modified the BasicConfig with this, and SAML doesn't work anymore but basic authentication works. All the endpoints are for both SAML and basic authentication, just different login page.
public static class BasicConfig extends WebSecurityConfigurerAdapter {
public BasicWebSecurityConfig() {
super();
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/secure/basic").permitAll()
.antMatchers("/**").permitAll()
.anyRequest().authenticated();
if (!enableCsrf) {
http.csrf().disable();
}
}
}
For some reasons sometimes it works, sometimes not. I also tried to modify the #Order and still not working.
In Spring Security, there are two things that are alike but do things completely differently, requestMatchers().antMatchers() and authorizeRequests().antMatchers().
The requestMatchers tells HttpSecurity to only invoke the SecurityFilterChain if the provided RequestMatcher was matched.
The authorizeRequests allows restricting access based upon the HttpServletRequest using RequestMatcher implementations.
In your case, you have two SecurityFilterChains. But only the one with the highest priority is being invoked, this happens because you did not give any requestMatchers to it, therefore it will match every request. And only one SecurityFilterChain is called per request, thus it will not invoke the next one.
So, you should inform the requestMatchers for your configurations, like so:
http
.requestMatchers((requests) -> requests
.antMatchers("/secure/sso", "/saml/**")
)
.authorizeRequests()
.antMatchers("/secure/sso").permitAll()
.antMatchers("/saml/**").permitAll()
.anyRequest().authenticated()
...
http
.requestMatchers((requests) -> requests
.antMatchers("/secure/basic", "/**")
)
.authorizeRequests()
.antMatchers("/secure/basic").permitAll()
.anyRequest().authenticated();
I rewrite the security configuration class from this tutorial.
I try to enter the entries without login, the server redirect to the login page well, but submit the user credentials to login processing URL return page not found. How should I fix it?
My Spring Security configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration {
#Autowired
#Qualifier("customUserDetailsService")
UserDetailsService userDetailsService;
#Autowired
PersistentTokenRepository tokenRepository;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
#Configuration
#Order(1)
ublic static class MobileSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/mobile/**")
.authorizeRequests()
.anyRequest().hasRole("MOBILE")
.and()
.formLogin()
.loginPage("/mobile_login")
.loginProcessingUrl("/mobile_login_processing_url")
.usernameParameter("ssoId")
.passwordParameter("password")
.defaultSuccessUrl("/mobile/menu")
.and()
.logout()
.logoutUrl("/mobile_logout")
.logoutSuccessUrl("/mobile_login?logout")
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling()
.accessDeniedPage("/Access_Denied")
.defaultAuthenticationEntryPointFor(authenticationEntryPoint(), new AntPathRequestMatcher("/mobile/**"));
}
#Bean
Public AuthenticationEntryPoint authenticationEntryPoint(){
return new LoginUrlAuthenticationEntryPoint("/mobile_login");
}
}
#Configuration
#Order(2)
public static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
PersistentTokenRepository tokenRepository;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/web/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/web_login")
.loginProcessingUrl("/web_login_processing_url")
.usernameParameter("ssoId")
.passwordParameter("password")
.defaultSuccessUrl("/web/list")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/web_login?logout")
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
#Bean
public PersistentTokenBasedRememberMeServices getPersistentTokenBasedRememberMeServices() {
PersistentTokenBasedRememberMeServices tokenBasedservice = new PersistentTokenBasedRememberMeServices(
"remember-me", userDetailsService, tokenRepository);
return tokenBasedservice;
}
#Bean
public AuthenticationTrustResolver getAuthenticationTrustResolver() {
return new AuthenticationTrustResolverImpl();
}
}
Your login processing URL /mobile_login_processing_url is unavailable.
You configured a formLogin, which adds a UsernamePasswordAuthenticationFilter for a HttpSecurity, see FormLoginConfigurer:
The following Filters are populated
UsernamePasswordAuthenticationFilter
but your HttpSecurityis restricted to the pattern /mobile/**, see HttpSecurity#antMatcher:
Allows configuring the HttpSecurity to only be invoked when matching the provided ant pattern.
so with URL /mobile_login_processing_url the HttpSecurityis not invoked and therefore the UsernamePasswordAuthenticationFilter is never applied. Without this filter, the form login is not processible, see UsernamePasswordAuthenticationFilter:
Processes an authentication form submission.
You have to change your login processing URL to /mobile/mobile_login_processing_url. See your modified configuration:
#Configuration
#Order(1)
ublic static class MobileSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/mobile/**")
.authorizeRequests()
.anyRequest().hasRole("MOBILE")
.and()
.formLogin()
.loginPage("/mobile_login")
.loginProcessingUrl("/mobile/mobile_login_processing_url")
.usernameParameter("ssoId")
.passwordParameter("password")
.defaultSuccessUrl("/mobile/menu")
.and()
.logout()
.logoutUrl("/mobile_logout")
.logoutSuccessUrl("/mobile_login?logout")
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling()
.accessDeniedPage("/Access_Denied")
.defaultAuthenticationEntryPointFor(authenticationEntryPoint(), new AntPathRequestMatcher("/mobile/**"));
}
#Bean
Public AuthenticationEntryPoint authenticationEntryPoint(){
return new LoginUrlAuthenticationEntryPoint("/mobile_login");
}
}
I have added "spring-boot-starter-actuator" dependency to my spring-boot project.
The project already has form based security.
The root context for the application is "/".
I have added the actuator at the context root "/actuators" by adding to application.yaml:
management:
context-path: /actuators
The non-sensitive actuators are working, such as "health".
When I try to access the sensitive actuators, the popup appears for username/password. The authentication takes place, but then I see "403" Access is Denied.
Here is the configuration for Web security:
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private AuthenticationLookupService authenticationLookupService;
private AuthenticationManagerBuilder authenticationManagerBuilder;
private UrlSuccessAuthenticationHandler successHandler;
#Autowired
public void setAuthenticationLookupService(AuthenticationLookupService authenticationLookupService) {
this.authenticationLookupService = authenticationLookupService;
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
this.authenticationManagerBuilder = auth;
}
#Autowired
public void setSuccessHandler(UrlSuccessAuthenticationHandler successHandler) {
this.successHandler = successHandler;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/index.html", "/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/index.html").successHandler(successHandler)
.permitAll()
.and()
.logout()
.permitAll();
http.csrf().disable(); // todo: fix later
}
#PostConstruct
public void process() throws Exception {
this.authenticationManagerBuilder.userDetailsService(this.authenticationLookupService).passwordEncoder(new ShaPasswordEncoder());
}
}
Add below values in application.properties or application.yml and then when popup asks for username and password provide this credentials
security.user.name=admin
security.user.password=secret
If you are providing your values check if that user has ADMIN role, because actuator needs ADMIN role user to access sensitive end points.
Update
If you are using spring-boot 1.5.*+ then user should have ACTUATOR role
We would like to apply Oauth2 based security for the Rest Controllers while the rest of the application will have Spring Security. Will that be possible? Can you provide any examples please?
It seems like WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter conflicting when both configured.
Thank you in advance.
Yes it's possible. Here the example template configuration code is given. Please change the required configs to your need. The key is to define Sub static classes of configuration with different order. Here i have considered any requests which is orginating from \api as a REST API call.
I have not checked the code by compiling it.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Order(1)
#Configuration
public static class ApiWebSecurityConfig extends OAuth2ServerConfigurerAdapter{
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//Write the AuthenticationManagerBuilder codes for the OAuth
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.apply(new OAuth2ServerConfigurer())
.tokenStore(new InMemoryTokenStore())
.resourceId(applicationName);
}
}
}
#Order(2)
#Configuration
public static class FormWebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
//Write the AuthenticationManagerBuilder codes for the Normal authentication
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //HTTP with Disable CSRF
.authorizeRequests() //Authorize Request Configuration
.anyRequest().authenticated()
.and() //Login Form configuration for all others
.formLogin()
.loginPage("/login").permitAll()
.and() //Logout Form configuration
.logout().permitAll();
}
}
}
My current java security config looks as follows:
#Configuration
#EnableWebSecurity
public class RootConfig extends WebSecurityConfigurerAdapter {
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication()
.withUser("tester").password("passwd").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeUrls()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}
When I perform a GET request using a browser, I'll get an error 403.
I would expect to get a browser popup asking me for a username / password.
What might be the problem?
UPDATE: This is fixed in Spring Security 3.2.0.RC1+
This is a bug in the Security Java Configuration that will be resolved for the next release. I have created SEC-2198 to track it. For now, a work around is to use something like the following:
#Bean
public BasicAuthenticationEntryPoint entryPoint() {
BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
basicAuthEntryPoint.setRealmName("My Realm");
return basicAuthEntryPoint;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(entryPoint())
.and()
.authorizeUrls()
.anyRequest().authenticated()
.and()
.httpBasic();
}
PS: Thanks for giving Spring Security Java Configuration a try! Keep the feedback up :)
With Spring Security 4.2.3 and probably before you can simply use this configuration:
#Configuration
#EnableWebSecurity
public class CommonWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
#Autowired
public void dlcmlUserDetails(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("tom").password("111").roles("USER");
}
}