How do I implement HttpSessionBindingListener? (Spring Security) - spring

I am using Spring MVC without Spring Boot and without web.xml
I need to implement HttpSessionBindingListener.
I don't know how to get this to work.
I've tried many options but this doesn't want to work.
https://github.com/romanych2021/TestBindingListener
UserActive.java
#Service
public class UserActive implements HttpSessionBindingListener {
Logger logger = LoggerFactory.getLogger(UserActive.class);
#Override
public void valueBound(HttpSessionBindingEvent event) {
logger.info("Log in : {}", event.getName() );
}
#Override
public void valueUnbound(HttpSessionBindingEvent event) {
logger.info("Log out : {}", event.getName() );
}
}
SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.mvcMatchers("/").permitAll()
.mvcMatchers("/login").anonymous()
.mvcMatchers("/user").hasAnyRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/")
.and().csrf().disable()
.logout()
.permitAll()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
}
}
RootConfig.java
#EnableWebMvc
#Configuration
#EnableWebSecurity
#ComponentScan({"com.testbindinglistener.security", "com.testbindinglistener.service"})
public class RootConfig {
#Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
}

Related

Google Signin and FormLogin spring security with a custom SuccessHandler

I'm trying to put a two way to login:
One way is useing formLogin user and password. This is de code with only one configuration and works fine:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Autowired
private UserDetailsService userDetailsService;
#Configuration
public static class WebSecurityConfigBasic extends WebSecurityConfigurerAdapter {
#Autowired
private LoginSuccessHandler loginSuccessHandler;
#Order(2)
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(...).permitAll()
.antMatchers(HttpMethod.POST, ...).permitAll()
.antMatchers(HttpMethod.GET,...).permitAll()
.antMatchers(...).permitAll()
.antMatchers(Constantes.INTERNO_SUCESSO, "/").access("hasRole('...')")
.antMatchers(Constantes.EXTERNO_SUCESSO).access("hasRole('...')")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.successHandler(loginSuccessHandler)
.failureUrl("/login-error")
.and()
.logout().logoutSuccessUrl("/");
http.headers().frameOptions().disable();
}
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
#Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy = "... > ... > ... > ... > ... > ...";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
}
This is the code with oAuth configuration, and if only this configuration actived, works fine too:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Autowired
private UserDetailsService userDetailsService;
#Configuration
public static class WebSecurityConfigOAuth extends WebSecurityConfigurerAdapter {
#Autowired
private LoginSuccessHandler loginSuccessHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(...).permitAll()
.antMatchers(HttpMethod.POST, ...).permitAll()
.antMatchers(HttpMethod.GET,...).permitAll()
.antMatchers(...).permitAll()
.antMatchers(Constantes.INTERNO_SUCESSO, "/").access("hasRole('...')")
.antMatchers(Constantes.EXTERNO_SUCESSO).access("hasRole('...')")
.anyRequest().authenticated()
.and()
.oauth2Login()
.loginPage("/login").permitAll()
.successHandler(loginSuccessHandler)
.failureUrl("/login-error")
.and()
.logout().logoutSuccessUrl("/");
http.headers().frameOptions().disable();
}
#Bean
public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
return new HttpSessionOAuth2AuthorizationRequestRepository();
}
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
#Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy = "... > ... > ... > ... > ... > ...";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
}
And if actived thw two configuration, only works the formlogin with user and password:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Autowired
private UserDetailsService userDetailsService;
#Order(1)
#Configuration
public static class WebSecurityConfigBasic extends WebSecurityConfigurerAdapter {
#Autowired
private LoginSuccessHandler loginSuccessHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(...).permitAll()
.antMatchers(HttpMethod.POST, ...).permitAll()
.antMatchers(HttpMethod.GET,...).permitAll()
.antMatchers(...).permitAll()
.antMatchers(Constantes.INTERNO_SUCESSO, "/").access("hasRole('...')")
.antMatchers(Constantes.EXTERNO_SUCESSO).access("hasRole('...')")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.successHandler(loginSuccessHandler)
.failureUrl("/login-error")
.and()
.logout().logoutSuccessUrl("/");
http.headers().frameOptions().disable();
}
}
#Order(2)
#Configuration
public static class WebSecurityConfigOAuth extends WebSecurityConfigurerAdapter {
#Autowired
private LoginSuccessHandler loginSuccessHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(...).permitAll()
.antMatchers(HttpMethod.POST, ...).permitAll()
.antMatchers(HttpMethod.GET,...).permitAll()
.antMatchers(...).permitAll()
.antMatchers(Constantes.INTERNO_SUCESSO, "/").access("hasRole('...')")
.antMatchers(Constantes.EXTERNO_SUCESSO).access("hasRole('...')")
.anyRequest().authenticated()
.and()
.oauth2Login()
.loginPage("/login").permitAll()
.successHandler(loginSuccessHandler)
.failureUrl("/login-error")
.and()
.logout().logoutSuccessUrl("/");
http.headers().frameOptions().disable();
}
#Bean
public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
return new HttpSessionOAuth2AuthorizationRequestRepository();
}
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
#Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy = "... > ... > ... > ... > ... > ...";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
}
At thw antmatchers on the both configuration is the same.

Configure antMatchers in Spring Security

I have this Spring Security configuration in Wildfly server:
#Configuration
#EnableWebSecurity
#Import(value= {Application.class, ContextDatasource.class})
#ComponentScan(basePackages= {"org.rest.api.server.*"})
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private RestAuthEntryPoint authenticationEntryPoint;
#Autowired
MyUserDetailsService myUserDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService);
auth.authenticationProvider(authenticationProvider());
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(myUserDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/v1/notification")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
I want to configure Spring security to permit all requests send to
http://localhost:8080/war_package/v1/notification but unfortunately I get always Unauthorized. Do you know what is the proper way to configure this?
You need to enable ResourceServer and add configure(HttpSecurity http) there.
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/v1/notification")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
}
}

404 error for login page in spring boot security... I am working in intellj idea community version

I am trying to implement spring boot security.And it is not able to find login page
This is my folder structure.
resources
static
home.html
login.html
templates
index.html
This is security Config file
enter code here
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
public void configureAuth(AuthenticationManagerBuilder auth) throws
Exception{
auth
.inMemoryAuthentication()
.withUser("dan")
.password("password")
.roles("ADMIN")
.and()
.withUser("joe")
.password("password")
.roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll();
http.csrf().disable();
}
}
this is my webconfig file
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/home").setViewName("home.html");
registry.addViewController("/login").setViewName("login.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
Please help. How to solve this error
It is working fine while specifying html file instead of just writing name of file.
Modifying above code.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll();
http.csrf().disable();
}
Also remove .html from setviewname
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/home").setViewName("home");
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}

SessionRegistry returns an empty list of authenticated users

I have an event listener, which when it receive the event that the user has changed their password invalidates the session. This is the code:
#Component
public class UserListener {
private static Logger logger = LoggerFactory.getLogger(UserListener.class);
#Autowired
private SessionRegistry sessionRegistry;
#EventListener
public void handleChangePasswordEvent(ChangePasswordEvent event) {
logger.info("handleChangePasswordEvent for : " + event.getUsername());
List<Object> loggedUsers = sessionRegistry.getAllPrincipals();
logger.info("loggedUsers : " + loggedUsers.size());
for (Object principal : loggedUsers) {
if (principal instanceof User) {
final User loggedUser = (User) principal;
logger.info("loggedUser : " + loggedUser.getUsername());
if (event.getUsername().equals(loggedUser.getUsername())) {
List<SessionInformation> sessionsInfo = sessionRegistry.getAllSessions(principal, false);
if (null != sessionsInfo && sessionsInfo.size() > 0) {
for (SessionInformation sessionInformation : sessionsInfo) {
logger.info("Exprire now :" + sessionInformation.getSessionId());
sessionInformation.expireNow();
sessionRegistry.removeSessionInformation(sessionInformation.getSessionId());
// User is not forced to re-logging
}
}
}
}
}
}
}
The listener works fine, the problem is that the list of authenticated users that returns me sessionRegistry is empty.
I've tried all the solutions I've seen for the same problem and they have not worked for me.
Here I put all the configuration of Spring Security.
#Configuration
#EnableGlobalMethodSecurity(securedEnabled = true)
#EnableWebSecurity
#ComponentScan(value = { "security" })
public class SecurityConfig extends GlobalAuthenticationConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private CustomLogoutHandler logoutHandler;
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationEventPublisher(authenticationEventPublisher())
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Bean
public DefaultAuthenticationEventPublisher authenticationEventPublisher() {
return new DefaultAuthenticationEventPublisher();
}
/**
* Security Configuration for Admin zone
*/
#Configuration
#Order(1)
public class AdminConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationSuccessHandler successHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**")
.hasAuthority(AuthorityEnum.ROLE_ADMIN.name())
.and()
.formLogin()
.loginPage("/admin/login")
.usernameParameter("username")
.passwordParameter("password")
.successHandler(successHandler)
.permitAll()
.and()
.logout()
.addLogoutHandler(logoutHandler)
.logoutRequestMatcher(new AntPathRequestMatcher("/admin/logout"))
.logoutSuccessUrl("/admin/login?logout")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf()
.disable();
}
}
/**
* Security Configuration for Frontend zone
*/
#Configuration
#Order(2)
public class FrontendConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/*.*")
.permitAll()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.addLogoutHandler(logoutHandler)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
}
#Configuration
#Order(3)
public class GlobalWebConfiguration extends WebSecurityConfigurerAdapter {
private SessionRegistry sessionRegistry;
#Autowired
private MessageSource messageSource;
#Override
public void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionAuthenticationStrategy(compositeSessionAuthenticationStrategy())
.sessionFixation()
.changeSessionId()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.expiredUrl("/login?expired")
.sessionRegistry(sessionRegistry())
.and()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/");
// Here we protect site from:
// 1. X-Content-Type-Options
http.headers().contentTypeOptions();
// 2. Web Browser XSS Protection
http.headers().xssProtection();
http.headers().cacheControl();
http.headers().httpStrictTransportSecurity();
// 3. X-Frame-Options
http.headers().frameOptions();
}
#Bean
public SessionRegistry sessionRegistry() {
if (sessionRegistry == null) {
sessionRegistry = new SessionRegistryImpl();
}
return sessionRegistry;
}
#Bean
#Order(1)
public ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy() {
ConcurrentSessionControlAuthenticationStrategy strategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
strategy.setExceptionIfMaximumExceeded(true);
strategy.setMessageSource(messageSource);
return strategy;
}
#Bean
#Order(2)
public SessionFixationProtectionStrategy sessionFixationProtectionStrategy(){
return new SessionFixationProtectionStrategy();
}
#Bean
#Order(3)
public RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy(){
RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy = new RegisterSessionAuthenticationStrategy(sessionRegistry());
return registerSessionAuthenticationStrategy;
}
#Bean
public CompositeSessionAuthenticationStrategy compositeSessionAuthenticationStrategy(){
List<SessionAuthenticationStrategy> sessionAuthenticationStrategies = new ArrayList<>();
sessionAuthenticationStrategies.add(concurrentSessionControlAuthenticationStrategy());
sessionAuthenticationStrategies.add(sessionFixationProtectionStrategy());
sessionAuthenticationStrategies.add(registerSessionAuthenticationStrategy());
CompositeSessionAuthenticationStrategy compositeSessionAuthenticationStrategy = new CompositeSessionAuthenticationStrategy(sessionAuthenticationStrategies);
return compositeSessionAuthenticationStrategy;
}
}
}
I have a WebSecurityConfigurerAdapter for the admin zone with its own login page and another for normal users.
At the end is GlobalWebConfiguration to configure the session manager for both zones (admin and users).
Hope someone can help me

how to define the secured URLs within an application dynamically

I am using Spring framework version: 3.2.3.RELEASE and
Spring security version: 3.2.3.RELEASE
I want to define the secured URLs within an application dynamically,and I have tried for several ways . I just can't make it,please help me!
According to http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/faq.html#faq-dynamic-url-metadata ,
I learn that dynamically defining access control to URLs needs using an explicitly declared security filter chain in order to customize the FilterSecurityInterceptor bean.
My question is
how to explicitly declared security filter chain?are there any example?
according to the book Spring security 3.1
which said"We can use a custom BeanPostProcessor to replace the standard FilterInvocationServiceSecurityMetadataSource with our custom implementation."
I followed this way and it dosen't work, I wondering if I have done something wrong?
the Java config class looks like this:
public class MessageSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
#Configuration
#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
#Configuration
#Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
#Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
}
}
}
#Component
public class KpiFilterInvocationSecurityMetadataSourceBeanPostProcessor implements BeanPostProcessor {
#Autowired
private KpiFilterInvocationSecurityMetadataSource metadataSource;
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof FilterInvocationSecurityMetadataSource) {
return metadataSource;
}
if(bean instanceof FilterChainProxy.FilterChainValidator) {
return new FilterChainProxy.FilterChainValidator() {
#Override
public void validate(FilterChainProxy filterChainProxy) {
}
};
}
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
I found a method withObjectPostProcessor,and try to do the following,it still doesn't worked. so what is best way to leverage this method?
#Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private KpiFilterInvocationSecurityMetadataSource metadataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/signup/**", "/about", "/login/**", "/index")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll()
.loginPage("/login/form")
.loginProcessingUrl("/login")
.usernameParameter("policeNo")
.passwordParameter("password")
.failureUrl("/login/form?error")
.defaultSuccessUrl("/default")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login/form?logout")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.withObjectPostProcessor(
new ObjectPostProcessor<FilterSecurityInterceptor>() {
public <O extends FilterSecurityInterceptor> O postProcess(
O fsi) {
fsi.setSecurityMetadataSource(metadataSource);
return fsi;
}
});
}
#Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("/resources/**");
}
}

Resources