I take this error when set authenticationFailureHandler: setAuthenticationFailureHandler(authenticationFailureHandler);
java.lang.IllegalArgumentException: failureHandler cannot be null at
org.springframework.util.Assert.notNull(Assert.java:193) at
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.setAuthenticationFailureHandler(AbstractAuthenticationProcessingFilter.java:448)
fragment web.xml
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
security.xml
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<global-method-security secured-annotations="enabled" pre-post-annotations="enabled" jsr250-annotations="enabled"/>
<http use-expressions="true" entry-point-ref="loginUrlAuthenticationEntryPoint" authentication-manager-ref="authenticationManager" >
<csrf disabled="true"/>
<custom-filter before="FORM_LOGIN_FILTER" ref="authenticationFilter" />
<intercept-url pattern="/public_home/**" access="permitAll"/>
<intercept-url pattern="/js/**" access="permitAll"/>
<intercept-url pattern="/css/**" access="permitAll"/>
<intercept-url pattern="/image/**" access="permitAll"/>
<intercept-url pattern="/resources/**" access="permitAll"/>
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/**" access="isAuthenticated()"/>
</http>
<authentication-manager/>
<b:bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<b:constructor-arg name="loginFormUrl" value="/public_home"/>
</b:bean>
<b:bean id="authenticationManager" class="n4.security.CustomAuthenticationManager">
</b:bean>
<b:bean id="authenticationFilter" class="n4.security.CustomAuthenticationFilter">
<b:property name="filterProcessesUrl" value="/j_spring_security_check" />
<b:property name="authenticationManager" ref="authenticationManager" />
<b:property name="authenticationSuccessHandler" ref="authenticationSuccessHandler"/>
<b:property name="authenticationFailureHandler" ref="authenticationFailureHandler"/>
</b:bean>
<b:bean name="authenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<b:property name="defaultTargetUrl" value="/home"></b:property>
<b:property name="alwaysUseDefaultTargetUrl" value="true"></b:property>
<b:property name="useReferer" value="true"></b:property>
</b:bean>
<b:bean name="authenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<b:property name="defaultFailureUrl" value="/public_home/loginfailed"></b:property>
</b:bean>
</b:beans>
CustomAuthenticationFilter
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private SimpleUrlAuthenticationFailureHandler authenticationFailureHandler;
#Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
setAuthenticationManager(authenticationManager);
setAuthenticationFailureHandler(authenticationFailureHandler);
return super.attemptAuthentication(request, response);
}
}
CustomAuthenticationManager
public class CustomAuthenticationManager implements AuthenticationManager{
#Autowired
private UtenteDao utenteDao;
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String)authentication.getPrincipal();
String password = (String)authentication.getCredentials();
Utente utente = utenteDao.login(username, password);
AuthUserDetail principal = new AuthUserDetail(utente);
return principal.refreshGrantAuthority();
}
}
Related
After upgrading some dependencies in our maven project to make the project run with jdk11 containers, I had to update from SpringSecurity 4.0.x to 4.2.x. So I wanted to give it a shot and convert the messy XML to a proper Java-config.
the xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd" default-autowire="byName">
<!-- Spring Security Settings -->
<security:global-method-security pre-post-annotations="enabled"></security:global-method-security>
<security:http-firewall ref="defaultHttpFirewall"/>
<security:http pattern="/api/**" security="none" />
<security:http pattern="/prometheus/**" security="none" />
<security:http entry-point-ref="restEntryPoint" pattern="/login*">
<security:intercept-url pattern="/login*"/>
<security:custom-filter ref="managerRequestRedirectFilter" before="BASIC_AUTH_FILTER" />
<security:csrf disabled="true"/>
</security:http>
<security:http entry-point-ref="restEntryPoint" pattern="/login/sso*">
<security:intercept-url pattern="/login/sso*"/>
<security:custom-filter ref="managerRequestRedirectFilter" before="BASIC_AUTH_FILTER" />
<security:csrf disabled="true"/>
</security:http>
<security:http pattern="/authenticate" security="none" />
<security:http pattern="/resources/bootstrap/**" security="none" />
<security:http pattern="/resources/css/**" security="none" />
<security:http pattern="/resources/js/**" security="none" />
<security:http pattern="/WEB-INF/views/login.jsp*" security="none" />
<security:http pattern="/databaseStatus" security="none" />
<security:http pattern="/module/**" security="none" />
<security:http pattern="/myarea/**" security="none" />
<security:http pattern="/ajax/**" security="none" />
<security:http pattern="/logout/sso" security="none" />
<security:http pattern="/download/**" security="none" />
<bean id="managerRequestRedirectFilter" class="com.pany.managertemplate.authentication.service.ManagerRequestRedirectFilter"/>
<!-- Spring Security Kerberos Settings -->
<bean id="authenticationResultFilter" class="com.pany.managertemplate.authentication.service.ManagerAuthenticationResultFilter"/>
<!-- rest -->
<bean id="restAuthenticationProcessingFilter" class=" com.pany.managertemplate.authentication.service.RestAuthenticationProcessingFilter" />
<bean id="restEntryPoint" class="com.pany.managertemplate.authentication.service.RestAuthenticationEntryPoint" />
<security:http entry-point-ref="restEntryPoint" pattern="/rest/**">
<security:intercept-url pattern="/rest/**" access="hasRole('ROLE_USER')" />
<security:custom-filter ref="restAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<security:custom-filter ref="authenticationResultFilter" after="BASIC_AUTH_FILTER" />
<security:csrf disabled="true"/>
</security:http>
<security:http entry-point-ref="restEntryPoint" pattern="/hooks/**">
<security:intercept-url pattern="/hooks/**" access="hasRole('ROLE_USER')" />
<security:custom-filter ref="restAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<security:custom-filter ref="authenticationResultFilter" after="BASIC_AUTH_FILTER" />
<security:csrf disabled="true"/>
</security:http>
<security:http entry-point-ref="restEntryPoint" pattern="/get/**">
<security:intercept-url pattern="/get/**" access="hasRole('ROLE_USER')" />
<security:custom-filter ref="restAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<security:custom-filter ref="authenticationResultFilter" after="BASIC_AUTH_FILTER" />
<security:csrf disabled="true"/>
</security:http>
<security:http entry-point-ref="restEntryPoint" pattern="/hook/**">
<security:intercept-url pattern="/hook/**" access="hasRole('ROLE_USER')" />
<security:custom-filter ref="restAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<security:custom-filter ref="authenticationResultFilter" after="BASIC_AUTH_FILTER" />
<security:csrf disabled="true"/>
</security:http>
<security:http entry-point-ref="restEntryPoint" pattern="/hookhistories/**">
<security:intercept-url pattern="/hookhistories/**" access="hasRole('ROLE_USER')" />
<security:custom-filter ref="restAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<security:custom-filter ref="authenticationResultFilter" after="BASIC_AUTH_FILTER" />
<security:csrf disabled="true"/>
</security:http>
<security:http entry-point-ref="restEntryPoint" pattern="/hookcalls/**">
<security:intercept-url pattern="/hookcalls/**" access="hasRole('ROLE_USER')" />
<security:custom-filter ref="restAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<security:custom-filter ref="authenticationResultFilter" after="BASIC_AUTH_FILTER" />
<security:csrf disabled="true"/>
</security:http>
<security:http entry-point-ref="restEntryPoint" pattern="/hookversions/**">
<security:intercept-url pattern="/hookversions/**" access="hasRole('ROLE_USER')" />
<security:custom-filter ref="restAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<security:custom-filter ref="authenticationResultFilter" after="BASIC_AUTH_FILTER" />
<security:csrf disabled="true"/>
</security:http>
<!-- -->
<bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />
<bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/login"/>
</bean>
<security:http entry-point-ref="spnegoEntryPoint">
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<security:custom-filter ref="managerRequestRedirectFilter" before="BASIC_AUTH_FILTER" />
<security:custom-filter ref="spnegoAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<security:custom-filter ref="authenticationResultFilter" after="BASIC_AUTH_FILTER" />
<security:session-management session-fixation-protection="newSession">
<security:concurrency-control max-sessions="1" expired-url="/login"/>
</security:session-management>
<security:csrf disabled="true"/>
</security:http>
<bean id="spnegoEntryPoint" class="com.pany.managertemplate.authentication.service.ManagerAuthenticationEntryPoint" />
<bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="useForward" value="true"/>
<property name="defaultFailureUrl" value="/login"/>
</bean>
<bean id="authenticationSuccessHandler" class="com.pany.managertemplate.authentication.service.ManagerAuthenticationSuccessHandler" />
<bean id="spnegoAuthenticationProcessingFilter" class="com.pany.managertemplate.authentication.service.ManagerSpnegoAuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="failureHandler" ref="simpleUrlAuthenticationFailureHandler"/>
<property name="successHandler" ref="authenticationSuccessHandler"/>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="kerberosServiceAuthenticationProvider" />
<security:authentication-provider ref="kerberosAuthenticationProvider"/>
</security:authentication-manager>
<bean id="kerberosAuthenticationProvider"
class="org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider">
<property name="kerberosClient">
<bean class="org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient">
<property name="debug" value="false"/>
</bean>
</property>
<property name="userDetailsService" ref="kerberosUserDetailsService"/>
</bean>
<bean id="kerberosServiceAuthenticationProvider" class="org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider">
<property name="ticketValidator">
<bean class="org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator">
<property name="servicePrincipal"
value="HTTP/an.URL"/>
<property name="keyTabLocation"
value="file:/etc/krb5.keytab"/>
<property name="debug" value="false" />
</bean>
</property>
<property name="userDetailsService" ref="kerberosUserDetailsService" />
</bean>
<bean class="org.springframework.security.kerberos.authentication.sun.GlobalSunJaasKerberosConfig">
<property name="debug" value="false" />
<property name="krbConfLocation" value="/etc/krb5.conf"/>
</bean>
<bean id="kerberosUserDetailsService" class="com.pany.managertemplate.authentication.service.KerberosUserDetailsService"/>
</beans>
and the try of a config I used:
package com.pany.managertemplate.configuration.service;
import java.net.MalformedURLException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider;
import org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider;
import org.springframework.security.kerberos.authentication.sun.GlobalSunJaasKerberosConfig;
import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient;
import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator;
import org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.firewall.DefaultHttpFirewall;
import org.springframework.security.web.firewall.HttpFirewall;
import com.pany.managertemplate.authentication.service.KerberosUserDetailsService;
import com.pany.managertemplate.authentication.service.ManagerAuthenticationEntryPoint;
import com.pany.managertemplate.authentication.service.ManagerAuthenticationResultFilter;
import com.pany.managertemplate.authentication.service.ManagerAuthenticationSuccessHandler;
import com.pany.managertemplate.authentication.service.ManagerRequestRedirectFilter;
import com.pany.managertemplate.authentication.service.ManagerSpnegoAuthenticationProcessingFilter;
import com.pany.managertemplate.authentication.service.RestAuthenticationEntryPoint;
import com.pany.managertemplate.authentication.service.RestAuthenticationProcessingFilter;
#Configuration
#Order(1)
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter
{
#Configuration
#Order(3)
public static class GlobalSecurity extends WebSecurityConfigurerAdapter
{
#Autowired
#Qualifier("authenticationResultFilter")
private ManagerAuthenticationResultFilter authenticationResultFilter;
#Autowired
private KerberosAuthenticationProvider kerberosAuthenticationProvider;
#Autowired
private KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider;
#Autowired
private ManagerRequestRedirectFilter managerRequestRedirectFilter;
#Autowired
#Qualifier("restEntryPoint")
private RestAuthenticationEntryPoint restEntryPoint;
#Autowired
private SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter;
#Autowired
#Qualifier("spnegoEntryPoint")
private ManagerAuthenticationEntryPoint spnegoEntryPoint;
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
#Override
protected void configure(final AuthenticationManagerBuilder authManagerBuilder) throws Exception
{
authManagerBuilder.authenticationProvider(this.kerberosServiceAuthenticationProvider);
authManagerBuilder.authenticationProvider(this.kerberosAuthenticationProvider);
}
#Override
protected void configure(final HttpSecurity http) throws Exception
{
http.csrf().disable();
http.authorizeRequests().antMatchers(HttpMethod.GET, "/health").permitAll();
http.authorizeRequests().antMatchers("/authenticate").permitAll();
http.authorizeRequests().antMatchers("/resources/bootstrap/**").permitAll();
http.authorizeRequests().antMatchers("/resources/css/**").permitAll();
http.authorizeRequests().antMatchers("/resources/js/**").permitAll();
http.authorizeRequests().antMatchers("/WEB-INF/views/login.jsp*").permitAll();
http.authorizeRequests().antMatchers("/databaseStatus").permitAll();
http.authorizeRequests().antMatchers("/module/**").permitAll();
http.authorizeRequests().antMatchers("/myarea/**").permitAll();
http.authorizeRequests().antMatchers("/ajax/**").permitAll();
http.authorizeRequests().antMatchers("/logout/sso").permitAll();
http.authorizeRequests().antMatchers("/download/**").permitAll();
http.authorizeRequests().antMatchers("/api/**").permitAll();
http.authorizeRequests().antMatchers("/prometheus/**").permitAll();
http.authorizeRequests().antMatchers("/**").hasRole("USER");
http.exceptionHandling().authenticationEntryPoint(this.spnegoEntryPoint);
http.addFilterBefore(this.managerRequestRedirectFilter, BasicAuthenticationFilter.class);
http.addFilterAt(this.spnegoAuthenticationProcessingFilter, BasicAuthenticationFilter.class);
http.addFilterAfter(this.managerRequestRedirectFilter, BasicAuthenticationFilter.class);
}
}
#Configuration
#Order(1)
public static class LoginSecurity extends WebSecurityConfigurerAdapter
{
#Autowired
private KerberosAuthenticationProvider kerberosAuthenticationProvider;
#Autowired
private KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider;
#Autowired
private ManagerRequestRedirectFilter managerRequestRedirectFilter;
#Autowired
#Qualifier("restEntryPoint")
private RestAuthenticationEntryPoint restEntryPoint;
#Override
protected void configure(final AuthenticationManagerBuilder authManagerBuilder) throws Exception
{
authManagerBuilder.authenticationProvider(this.kerberosServiceAuthenticationProvider);
authManagerBuilder.authenticationProvider(this.kerberosAuthenticationProvider);
}
#Override
protected void configure(final HttpSecurity http) throws Exception
{
http.csrf().disable();
http.antMatcher("/login*").antMatcher("/login/sso*");
http.authorizeRequests().anyRequest().permitAll();
http.exceptionHandling().authenticationEntryPoint(this.restEntryPoint);
http.addFilterBefore(this.managerRequestRedirectFilter, BasicAuthenticationFilter.class);
http.sessionManagement().sessionFixation().newSession().maximumSessions(1).expiredUrl("/login");
http.authorizeRequests().anyRequest().authenticated();
http.formLogin().loginPage("/login");
}
}
#Configuration
#Order(2)
public static class RestSecurity extends WebSecurityConfigurerAdapter
{
#Autowired
#Qualifier("authenticationResultFilter")
private ManagerAuthenticationResultFilter authenticationResultFilter;
#Autowired
private KerberosAuthenticationProvider kerberosAuthenticationProvider;
#Autowired
private KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider;
#Autowired
private RestAuthenticationProcessingFilter restAuthenticationProcessingFilter;
#Autowired
#Qualifier("restEntryPoint")
private RestAuthenticationEntryPoint restEntryPoint;
#Override
protected void configure(final AuthenticationManagerBuilder authManagerBuilder) throws Exception
{
authManagerBuilder.authenticationProvider(this.kerberosServiceAuthenticationProvider);
authManagerBuilder.authenticationProvider(this.kerberosAuthenticationProvider);
}
#Override
protected void configure(final HttpSecurity http) throws Exception
{
http.csrf().disable();
http.antMatcher("/rest/**").antMatcher("/hooks/**").antMatcher("/get/**").antMatcher("/hook/**").antMatcher("/hookhistories/**")
.antMatcher("/hookcalls/**").antMatcher("/hookversions/**");
http.authorizeRequests().anyRequest().permitAll();
http.exceptionHandling().authenticationEntryPoint(this.restEntryPoint);
http.addFilterAt(this.restAuthenticationProcessingFilter, BasicAuthenticationFilter.class);
http.addFilterAfter(this.authenticationResultFilter, BasicAuthenticationFilter.class);
}
}
#Autowired
#Qualifier("authenticationResultFilter")
private ManagerAuthenticationResultFilter authenticationResultFilter;
#Autowired
#Qualifier("restEntryPoint")
private RestAuthenticationEntryPoint restEntryPoint;
#Autowired
#Qualifier("spnegoEntryPoint")
private ManagerAuthenticationEntryPoint spnegoEntryPoint;
#Bean
public AccessDeniedHandlerImpl accessDeniedHandler()
{
AccessDeniedHandlerImpl accessDeniedHandlerImpl = new AccessDeniedHandlerImpl();
accessDeniedHandlerImpl.setErrorPage("/login");
return accessDeniedHandlerImpl;
}
#Override
public void configure(final WebSecurity web) throws Exception
{
// though StrictHttpFirewall is advised
super.configure(web);
web.httpFirewall(this.defaultHttpFirewall());
}
#Bean
public HttpFirewall defaultHttpFirewall()
{
DefaultHttpFirewall firewall = new DefaultHttpFirewall();
firewall.setAllowUrlEncodedSlash(true);
return firewall;
}
#Bean
public GlobalSunJaasKerberosConfig globalSunJaasKerberosConfig()
{
GlobalSunJaasKerberosConfig globalSunJaasKerberosConfig = new GlobalSunJaasKerberosConfig();
globalSunJaasKerberosConfig.setDebug(false);
globalSunJaasKerberosConfig.setKrbConfLocation("/etc/krb5.conf");
return globalSunJaasKerberosConfig;
}
#Bean("kerberosAuthenticationProvider")
public KerberosAuthenticationProvider kerberosAuthenticationProvider(#Qualifier("kerberosClient") final SunJaasKerberosClient kerberosClient,
final KerberosUserDetailsService kerberosUserDetailsService)
{
KerberosAuthenticationProvider kerberosAuthenticationProvider = new KerberosAuthenticationProvider();
kerberosAuthenticationProvider.setKerberosClient(kerberosClient);
kerberosAuthenticationProvider.setUserDetailsService(kerberosUserDetailsService);
return kerberosAuthenticationProvider;
}
#Bean("kerberosServiceAuthenticationProvider")
public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider(final KerberosUserDetailsService kerberosUserDetailsService,
#Qualifier("ticketValidator") final SunJaasKerberosTicketValidator ticketValidator)
{
KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider = new KerberosServiceAuthenticationProvider();
kerberosServiceAuthenticationProvider.setUserDetailsService(kerberosUserDetailsService);
kerberosServiceAuthenticationProvider.setTicketValidator(ticketValidator);
return kerberosServiceAuthenticationProvider;
}
#Bean
public KerberosUserDetailsService kerberosUserDetailsService()
{
return new KerberosUserDetailsService();
}
#Bean("spnegoEntryPoint")
public ManagerAuthenticationEntryPoint managerAuthenticationEntryPoint()
{
return new ManagerAuthenticationEntryPoint();
}
#Bean("authenticationResultFilter")
public ManagerAuthenticationResultFilter managerAuthenticationResultFilter()
{
return new ManagerAuthenticationResultFilter();
}
#Bean("authenticationSuccessHandler")
public ManagerAuthenticationSuccessHandler managerAuthenticationSuccessHandler()
{
return new ManagerAuthenticationSuccessHandler();
}
#Bean
public ManagerRequestRedirectFilter managerRequestRedirectFilter()
{
return new ManagerRequestRedirectFilter();
}
#Bean("spnegoAuthenticationProcessingFilter")
public ManagerSpnegoAuthenticationProcessingFilter managerSpnegoAuthenticationProcessingFilter(final AuthenticationManager authenticationManager,
final SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler,
#Qualifier("authenticationSuccessHandler") final AuthenticationSuccessHandler authenticationSuccessHandler)
{
ManagerSpnegoAuthenticationProcessingFilter managerSpnegoAuthenticationProcessingFilter = new ManagerSpnegoAuthenticationProcessingFilter();
managerSpnegoAuthenticationProcessingFilter.setAuthenticationManager(authenticationManager);
managerSpnegoAuthenticationProcessingFilter.setFailureHandler(simpleUrlAuthenticationFailureHandler);
managerSpnegoAuthenticationProcessingFilter.setSuccessHandler(authenticationSuccessHandler);
return managerSpnegoAuthenticationProcessingFilter;
}
#Bean("restEntryPoint")
public RestAuthenticationEntryPoint restAuthenticationEntryPoint()
{
return new RestAuthenticationEntryPoint();
}
#Bean
public RestAuthenticationProcessingFilter restAuthenticationProcessingFilter()
{
return new RestAuthenticationProcessingFilter();
}
#Bean("simpleUrlAuthenticationFailureHandler")
public SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler()
{
SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler();
simpleUrlAuthenticationFailureHandler.setUseForward(true);
simpleUrlAuthenticationFailureHandler.setDefaultFailureUrl("/login");
return simpleUrlAuthenticationFailureHandler;
}
#Bean
public SunJaasKerberosClient sunJaasKerberosClient()
{
SunJaasKerberosClient sunJaasKerberosClient = new SunJaasKerberosClient();
sunJaasKerberosClient.setDebug(false);
return sunJaasKerberosClient;
}
#Bean("ticketValidator")
public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() throws MalformedURLException
{
SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator = new SunJaasKerberosTicketValidator();
sunJaasKerberosTicketValidator.setServicePrincipal("HTTP/an.URL");
Resource keyTabFile = new UrlResource("file:/etc/krb5.keytab");
sunJaasKerberosTicketValidator.setKeyTabLocation(keyTabFile);
sunJaasKerberosTicketValidator.setDebug(false);
return sunJaasKerberosTicketValidator;
}
}
Login via /login works fine, permissions working inside the applications webinterface.
The problem I encountered is the part for the server-to-server communication via REST.
Sending the proper credentials like used to now just returns the login page instead of the requested resource - this is the point where I am stuck.
I feel like, the config is too complex and confusing at some points because of several entrypoints. but that was what I read in the offical documentation. Or is there an easier way and I am just thinking too complex? In short Java-Config behaves not like the Java-Config, and I can't see why so far.
I am working on a Spring-MVC application in which we are using Spring-Security for authentication and authorization. In our application we send out emails with URL's. Many times the user is not logged in, but after login, we would want to redirect to the original link after login. Thank you. Tried XML configuration, but it is not working.
Xml config :
<!-- Global Security settings -->
<security:http pattern="/resources/**" security="none"/>
<security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true">
<security:form-login login-page="/login" username-parameter="j_username" password-parameter="j_password"
login-processing-url="/j_spring_security_check" default-target-url="/canvaslisting"
always-use-default-target="true" authentication-failure-url="/denied"/>
<security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService"
token-validity-seconds="1209600" data-source-ref="dataSource"/>
<security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/>
<security:intercept-url pattern="/**" requires-channel="https"/>
<security:port-mappings>
<security:port-mapping http="8080" https="8443"/>
</security:port-mappings>
<security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/>
<security:session-management session-fixation-protection="newSession">
<security:concurrency-control session-registry-ref="sessionReg" max-sessions="5" expired-url="/login"/>
</security:session-management>
</security:http>
<beans:bean id="sessionReg" class="org.springframework.security.core.session.SessionRegistryImpl"/>
<beans:bean id="rememberMeAuthenticationProvider"
class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<beans:constructor-arg index="0" value="_spring_security_remember_me"/>
<beans:constructor-arg index="1" ref="userDetailsService"/>
<beans:constructor-arg index="2" ref="jdbcTokenRepository"/>
<property name="alwaysRemember" value="true"/>
</beans:bean>
<beans:bean id="jdbcTokenRepository"
class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
<beans:property name="createTableOnStartup" value="false"/>
<beans:property name="dataSource" ref="dataSource"/>
</beans:bean>
<!-- Remember me ends here -->
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="LoginServiceImpl">
<security:password-encoder ref="encoder"/>
</security:authentication-provider>
</security:authentication-manager>
<beans:bean id="encoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg name="strength" value="11"/>
</beans:bean>
<beans:bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="LoginServiceImpl"/>
<beans:property name="passwordEncoder" ref="encoder"/>
</beans:bean>
<beans:bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="filterProcessesUrl" value="/login" />
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="authenticationSuccessHandler">
<beans:bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="useReferer" value="true"/>
</beans:bean>
</beans:property>
<beans:property name="authenticationFailureHandler">
<beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login?login_error=t" />
</beans:bean>
</beans:property>
</beans:bean>
</beans>
Thank you.
Although you have not shown how you have configured your tag, so I am assuming that, you already have, that see bellow code.
<security:http auto-config="true" use-expressions="false">
<security:form-login login-page="/login" login-processing-url="/login"
username-parameter="custom_username"
password-parameter="custom_password"
default-target-url="/appointments/"
always-use-default-target="true"
authentication-failure-url="/login?error=true"
/>
<security:intercept-url pattern="/appointments/*" access="ROLE_USER"/>
<security:intercept-url pattern="/schedule/*" access="ROLE_FOO"/>
<security:intercept-url pattern="/**" access="ROLE_ANONYMOUS, ROLE_USER"/>
</security:http>
so, if you are not mentioning these two lines
default-target-url="/appointments/"
always-use-default-target="true"
, then by default spring security will redirect you user to the same page (which he requested), and got authentication prompt.
If this still does not full fills your requirement then you may need to implement your own filter or take a look at FilterSecurityInterceptor or MethodSecurityInterceptor .
Bellow is an Example, which will help you to achieve your goal:
To understand this problem better, take a look on below example:
- user receives a newsletter mail where he's invited to vote for more beautiful holidays picture. The URL contains a hash parameter used to authenticate user in the page.
- when user clicks on given URL, it will arrive to voting page as already authenticated user.
So My Custom Filter Will be like bellow:
package com.osigu.ehr.config;
public class OneShotActionFilter extends GenericFilterBean {
private static final Logger LOGGER =
LoggerFactory.getLogger(OneShotActionFilter.class);
private static Map<String, String> users = new HashMap<String, String>();
static {
users.put("0000000000001", "bartosz");
users.put("0000000000002", "admin");
users.put("0000000000003", "mod");
}
private static final String PARAM_NAME = "uio";
private AuthenticationManager authenticationManager;
private UserDetailsService userDetailsService;
private final RedirectStrategy redirectStrategy = new
DefaultRedirectStrategy();
private enum AuthenticationStates {
REDIRECT, CONTINUE;
}
public void setAuthenticationManager(AuthenticationManager
authenticationManager) {
this.authenticationManager = authenticationManager;
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException,
ServletException {
LOGGER.debug("One shot filter invoked");
if (attemptAuthentication(request) == AuthenticationStates.REDIRECT) {
// Note that we should handle that dynamically but for learning purposes
//we'll consider that one-shot
// authentication works only for this URL
this.redirectStrategy.sendRedirect((HttpServletRequest) request,
(HttpServletResponse) response,
"/secret/one-shot-action");
} else {
LOGGER.debug("User was not correctly authenticated, continue filter chain");
// continue execution of all other filters
// You can test the code without this fragment in the pages without ?uio parameter. You should see blank page because of
// security filter chain interruption.
filterChain.doFilter(request, response);
}
}
private AuthenticationStates attemptAuthentication(ServletRequest request) {
AuthenticationStates state = AuthenticationStates.CONTINUE;
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
String code = request.getParameter(PARAM_NAME);
if ((authentication == null || !authentication.isAuthenticated()) && code !=
null &&
users.containsKey(code)) {
LOGGER.debug("Checking user for code " + code);
UserDetails user = userDetailsService.loadUserByUsername(users.get(code));
LOGGER.debug("Found user from code (" + users.get(code) + "). User found is " + user);
if (user != null) {
users.remove(code);
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(user.getUsername(),
user.getPassword());
authentication = this.authenticationManager.authenticate(authRequest);
if (authentication != null && authentication.isAuthenticated()) {
SecurityContextHolder.getContext().setAuthentication(authentication);
state = AuthenticationStates.REDIRECT;
}
}
}
return state;
}
}
And Finally Configure it in your xml, like bellow
<security:http authentication-manager-ref="frontend" auto-config="true" use-
expressions="true" access-denied-page="/access-denied">
<-- other filters are defined here -->
<security:custom-filter ref="oneShootAuthFilter"
after="CONCURRENT_SESSION_FILTER"/>
</security:http>
<bean id="oneShootAuthFilter"
class="com.waitingforcode.security.filter.OneShotActionFilter">
<property name="authenticationManager" ref="frontend" />
<property name="userDetailsService" ref="inMemoryUserService" />
</bean>
To test the filter, we can try to access to http://localhost:8080/?uio=0000000000001. You should be redirected (but only once) to http://localhost:8080/secret/one-shot-action page
I wrote this example for better clarity and as reference for future questions.
Do up vote if you think it helped you to clear your doubt.
you can also visit this link
#Component("MyAuthFilter")
public class MyAuthFilter extends UsernamePasswordAuthenticationFilter {
#Override
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
...
}}
my spring-security:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.2.xsd">
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/courses*" access="hasRole('ROLE_USER')" />
<custom-filter before="FORM_LOGIN_FILTER" ref="MyAuthFilter" />
<form-login
login-page="/login"
default-target-url="/courses"
authentication-failure-url="/login?error"
username-parameter="loginField"
password-parameter="passwordField" />
<csrf disabled="true" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="ars" password="1234" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
i'm trying to add my custom filter in spring security, but on startup i get an error that authenticationManager must be specified. Can someone have a look?
Try adding an #Autowired to setter of AuthenticationManager
#Autowired
#Qualifier("authenticationManager")
#Override
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
UPDATE
Add alias="authenticationManager" for your Authentication Manager
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="ars" password="1234" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
I have Java Restful web service with Spring Security, JAX-RS Jersey. I use #PreAuthorize annotations for method security, but it doesn't work.
I have method, which use annotation #PreAuthorize("hasRole('ROLE_ADMIN')"), but users with ROLE_USER, also have access to this method.
Can anybody help me?
Spring version
<spring.version>3.2.8.RELEASE</spring.version>
<spring.security.version>3.2.3.RELEASE</spring.security.version>
My spring-security-context.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<http use-expressions="true" auto-config="true">
<intercept-url pattern="/rest/users/list" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')"/>
<intercept-url pattern="/rest/users/add" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/rest/users/update" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')"/>
<intercept-url pattern="/rest/users/**" method="DELETE" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/rest/users/get/**" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')"/>
<intercept-url pattern="/rest/orders/**" access="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')"/>
<logout logout-url="/logout"/>
</http>
<security:global-method-security secured-annotations="enabled"
pre-post-annotations="enabled"/>
<beans:bean id="customUserService" class="com.bankproject.services.CustomUserDetailService"/>
<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user" password="user" authorities="ROLE_USER"/>
<user name="admin" password="admin" authorities="ROLE_ADMIN"/>
</user-service>
</authentication-provider>
</authentication-manager>
<beans:bean id="orderDAO" class="com.bankproject.DAO.Impl.OrderOutputDAOImpl"/>
<beans:bean id="orderManager" class="com.bankproject.services.OrderService"/>
My OutputOrderDAOImpl.java
public class OrderOutputDAOImpl implements OrderOutputDAO {
#Override
#PreAuthorize("hasRole('ROLE_ADMIN')")
public List<OrderOutputObject> getOrdersByUsername(String username) throws SQLException {
List<OrderObject> orders = orderDAO.getOrdersByUsername(username);
return getOutputOrders(orders);
}
}
My OrderService.java
#Path("/orders")
public class OrderService {
#GET
#Path("/{username}")
#Produces(MediaType.APPLICATION_JSON)
public List<OrderOutputObject> getOrdersForUser(#PathParam("username") String username){
List<OrderOutputObject> orders = new ArrayList<OrderOutputObject>();
try{
orders = orderOutputDAO.getOrdersByUsername(username);
}catch (Exception e){
e.printStackTrace();
}
return orders;
}
}
I am working on a Spring-MVC application which uses Spring-Security for authentication and related security purpose. Currently I am having problem querying the sessionRegistry to get a list of currently online users as the getAllPrincipals() method always contains NULL. I tried solutions mentioned in the documentation and many suggestions mentioned on other SO threads. I would really appreciate some help as I am trying various combinations which will work to get list of all Online users.
Here is my security-application-context.xml:
<import resource="servlet-context.xml" />
<!-- Global Security settings -->
<security:global-method-security pre-post-annotations="enabled" />
<security:http pattern="/resources/**" security="none"/>
<security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true">
<security:form-login login-page="/login" login-processing-url="/j_spring_security_check" default-target-url="/canvas/list" always-use-default-target="false" authentication-failure-url="/denied.jsp" />
<security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService" token-validity-seconds="1209600" data-source-ref="dataSource"/>
<security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/>
<security:port-mappings>
<security:port-mapping http="80" https="443"/>
</security:port-mappings>
<security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/>
</security:http>
<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="maximumSessions" value="-1" />
</beans:bean>
<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<beans:property name="key" value="_spring_security_remember_me" />
<property name="alwaysRemember" value="true"/>
<beans:property name="tokenRepository" ref="jdbcTokenRepository"/>
<beans:property name="userDetailsService" ref="LoginServiceImpl"/>
</beans:bean>
<beans:bean id="myAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="sessionAuthenticationStrategy" ref="sas"/>
<property name="rememberMeServices" ref="rememberMeAuthenticationProvider"/>
<property name="allowSessionCreation" value="true"/>
<property name="authenticationManager" ref="authenticationManager"/>
</beans:bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="LoginServiceImpl">
<security:password-encoder ref="encoder"/>
</security:authentication-provider>
</security:authentication-manager>
<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg name="strength" value="11" />
</beans:bean>
<beans:bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="LoginServiceImpl"/>
<beans:property name="passwordEncoder" ref="encoder"/>
</beans:bean>
here is where I am trying to get back the list of OnlineUsers :
#Service
#Transactional
public class OnlineUsersServiceImpl implements OnlineUsersService {
#Autowired
#Qualifier("sessionRegistry")
private SessionRegistry sessionRegistry;
#Override
public boolean checkIfUserhasSession(int id) {
Person person = this.personService.getPersonById(id);
String email = person.getUsername();
List<Object> principals = sessionRegistry.getAllPrincipals();
for (Object principal : principals) {
// It never reaches here
System.out.println("We reached here");
if (principal instanceof User) {
String username = ((User) principal).getUsername();
System.out.println("Username is "+username);
if(email.equals(username)){
return true;
}
}
}
return false;
}
Any help would be nice. As I am on this hopeless thing since 3-4 days.
Before injecting session registry you need to define session management part in your security-application-context.xml
In concurrency-control section you should set alias for session registry object
<security:http access-denied-page="/error403.jsp" use-expressions="true" auto-config="false">
<security:session-management session-fixation-protection="migrateSession" session-authentication-error-url="/login.jsp?authFailed=true">
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login.html" session-registry-alias="sessionRegistry"/>
</security:session-management>
...
</security:http>
For java based configuration alternative to xml configuration
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
// ...
http.sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry());
}
#Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
#Bean
public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}
}
You need additional configuration in web.xml - listener for login/logout events
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>