<bean class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"/>
<security:http use-expressions="false" entry-point-ref="loginEntryPoint">
<security:custom-filter ref="customFormLoginFilter" position="FORM_LOGIN_FILTER"/>
<security:logout logout-url="/logout" logout-success-url="/login?logout=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>
<bean id="customFormLoginFilter" class="com.fetn.security.CustomAuthenticationFilter">
<property name="filterProcessesUrl" value="/login"/>
<property name="authenticationManager" ref="authenticationManager"/>
<property name="usernameParameter" value="custom_username"/>
<property name="passwordParameter" value="custom_password"/>
<property name="authenticationSuccessHandler">
<bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/"/>
</bean>
</property>
<property name="authenticationFailureHandler">
<bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login/failure?error=true"/>
</bean>
</property>
</bean>
<bean id="loginEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg value="/login"/>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>
I wrote belowJava Config Code but for logout and .antMatchers("/appointments/").access("hasRole('USER')") and antMatchers("/schedule/").access("hasRole('ADMIN')")
URL always go to /login/failure?error=true
what will be the appropriate java cofig code .Please Help.....
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Autowired
private AutoUserRepository autoUserRepository;
#Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/appointments/*").access("hasRole('USER')").
antMatchers("/schedule/*").access("hasRole('ADMIN')").and().exceptionHandling().authenticationEntryPoint(loginEntryPoint()).and().addFilterBefore(customFormLoginFilter(), UsernamePasswordAuthenticationFilter.class);
http.logout().logoutUrl("/logout")
.logoutSuccessUrl("/login?logout=true");
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Bean
public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler(){
return new DefaultWebSecurityExpressionHandler();
}
#Bean
public LoginUrlAuthenticationEntryPoint loginEntryPoint(){
LoginUrlAuthenticationEntryPoint ent=new LoginUrlAuthenticationEntryPoint("/login");
return ent;
}
#Bean
public CustomAuthenticationFilter customFormLoginFilter() throws Exception{
CustomAuthenticationFilter filter=new CustomAuthenticationFilter();
//setting up super class property AbstractAuthenticationProcessingFilter
filter.setFilterProcessesUrl("/login");//login url
filter.setAuthenticationManager(authenticationManagerBean());
filter.setUsernameParameter("custom_username");
filter.setPasswordParameter("custom_username");
filter.setAuthenticationSuccessHandler(savedRequestAwareAuthenticationSuccessHandler());
filter.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler());
return filter;
}
#Bean
public SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler(){
SavedRequestAwareAuthenticationSuccessHandler surl=new SavedRequestAwareAuthenticationSuccessHandler();
surl.setDefaultTargetUrl("/");//url after seuuces login
return surl;
}
#Bean
SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler(){
SimpleUrlAuthenticationFailureHandler faillure=new SimpleUrlAuthenticationFailureHandler();
faillure.setDefaultFailureUrl("/login/failure?error=true");
return faillure;
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Could it be that you have to add .and() between the various antMatchers? Also you are using two http.* calls i think it can be done with one. See code below from this page.
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
Related
I'm using Spring Boot MVC last version (5.3) e Spring security (5.5) with LDAP users
I'm trying to change from this xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-5.4.xsd">
<security:http auto-config="true" disable-url-rewriting="true"
use-expressions="true">
<security:form-login login-page="/signin"
authentication-failure-url="/signinAjax?error=1" authentication-details-source-ref="customWebAuthenticationDetailsSource" authentication-success-forward-url="/logged"/>
<security:intercept-url pattern="/" access="permitAll" />
<security:intercept-url pattern="/isAutenticated" access="permitAll" />
<security:intercept-url pattern="/resources/images/favicon.png"
access="permitAll" />
<security:intercept-url pattern="/resources/webfonts/**"
access="permitAll" />
<security:intercept-url pattern="/resources/**"
access="permitAll" />
<security:intercept-url pattern="/signin"
access="permitAll" />
<security:intercept-url pattern="/signinAjax"
access="permitAll" />
<security:intercept-url pattern="/userList"
access="isAuthenticated()" />
<security:intercept-url pattern="/imgages/**"
access="permitAll" />
<security:intercept-url pattern="/**"
access="isAuthenticated()" />
</security:http>
<security:global-method-security
secured-annotations="enabled" />
<security:authentication-manager
erase-credentials="true">
<security:authentication-provider
ref="ldapActiveDirectoryAuthProvider" />
</security:authentication-manager>
<bean id="ldapActiveDirectoryAuthProvider"
class="org.springframework.security.ldap.authentication.ad.CustomActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="XXXX" />
<constructor-arg value="ldap://XXX:389" />
<property name="convertSubErrorCodesToExceptions" value="true" />
<property name="searchFilter"
value="(&(objectClass=user)(sAMAccountName={0}))" />
<property name="useAuthenticationRequestCredentials" value="true" />
<property name="userDetailsContextMapper" ref="tdrUserDetailsContextMapper" />
</bean>
<bean id="tdrUserDetailsContextMapper"
class="it.xxx.account.CustomUserDetailsContextMapper" />
<bean id="customWebAuthenticationDetailsSource"
class="it.xxx.config.security.CustomWebAuthenticationDetailsSource"/>
</beans>
That function correctly to this Java Based Configuration
#Configuration
#EnableWebSecurity
//#EnableGlobalMethodSecurity(securedEnabled=true)
//#ImportResource(value = "classpath:spring-security-context.xml")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public CustomWebAuthenticationDetailsSource customWebAuthenticationDetailsSource() {
return new CustomWebAuthenticationDetailsSource();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/isAutenticated").permitAll()
.antMatchers("/resources/**").permitAll()
.antMatchers("/signin").permitAll()
.antMatchers("/signinAjax").permitAll()
.antMatchers("/userList").permitAll()
.antMatchers("/images/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/signin")
.authenticationDetailsSource(customWebAuthenticationDetailsSource())
.successForwardUrl("/logged")
.failureForwardUrl("/signinAjax?error=1");
}
#Bean
public CustomActiveDirectoryLdapAuthenticationProvider ldapActiveDirectoryAuthProvider() {
CustomActiveDirectoryLdapAuthenticationProvider provider = new CustomActiveDirectoryLdapAuthenticationProvider("xxx.local","ldap://xxx:389");
provider.setConvertSubErrorCodesToExceptions(true);
provider.setSearchFilter("(&(objectClass=user)(sAMAccountName={0}))");
provider.setUseAuthenticationRequestCredentials(true);
provider.setUserDetailsContextMapper(tdrUserDetailsContextMapper());
return provider;
}
#Bean
public LoggerListener loggerListener() {
return new LoggerListener();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.eraseCredentials(true);
auth.authenticationProvider(ldapActiveDirectoryAuthProvider());
}
#Bean
public CustomUserDetailsContextMapper tdrUserDetailsContextMapper() {
return new CustomUserDetailsContextMapper();
}
}
on compile and runnung of tomcat no error but is impossible to make the loggin and having this error
org.springframework.security.access.event.LoggerListener.onAuthorizationFailureEvent Security authorization failed due to: org.springframework.security.access.AccessDeniedException: Access is denied; authenticated principal: AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=19C02E6245BF011635B6ADC374ED4EA4], Granted Authorities=[ROLE_ANONYMOUS]]; secure object: filter invocation [POST /login]; configuration attributes: [authenticated]
I don't know what is missing.
http.csrf().disable()
.authorizeRequests()
.antMatchers("/index","/images/**","/showSignUpForm","/login","/userSignUp",
"/page/**","/sort/**","/sortWithPage/**","/search/**").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login").defaultSuccessUrl("/index").permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout").permitAll();
Try in this way
I found the problems:
Error from xml to java (&)
provider.setSearchFilter("(&(objectClass=user)(sAMAccountName={0}))");
Changed loginPage
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/isAutenticated").permitAll()
.antMatchers("/resources/**").permitAll()
.antMatchers("/signin").permitAll()
.antMatchers("/signinAjax").permitAll()
.antMatchers("/userList").permitAll()
.antMatchers("/images/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.authenticationDetailsSource(customWebAuthenticationDetailsSource())
.successForwardUrl("/logged")
.failureForwardUrl("/signinAjax?error=1");
}
I don't know how function with xml....
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 making a Spring MVC web application. I have a login page and a dashboard page. Anyone attempting to access the dashboard JSP must be logged in:
Here's my Spring Security config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity
#Import({SpringConfiguration.class})
public class SecurityContext extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
// authorizeRequests() -> use-expresions = "true"
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/createaccount","/error", "/register", "/login", "/newaccount", "/resources/**").permitAll()
.antMatchers("/**", "/*", "/").authenticated()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.loginProcessingUrl("/j_spring_security_check")
.usernameParameter("username")
.passwordParameter("password")
.failureUrl("/login?error=true")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login")
.invalidateHttpSession(true)
.and()
.csrf();
// Upon starting the application, it prints the asdfasdf so I know the SecurityContext is loaded
System.out.println("asdfasdf");
}
// Equivalent of jdbc-user-service in XML
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("SELECT username, password, enabled FROM Users WHERE username=?")
.authoritiesByUsernameQuery("SELECT username, authority FROM authorities where username=?");
}
}
As you can see, I have some endpoints which I permit anyone to access such as /login, /register, but all other URLs require that they be authenticated. When I start the application, if I try go to the dashboard page, I can access it just fine without needing to login which is not what I want.
My issue is that I want people attempting to reach the dashboard to be sent to the login page if they are not logged in/authenticated.
I'm trying to avoid using XML entirely and only use Java to configure my application, would anyone know what I'm doing wrong? I am almost certain it's something wrong with with my SecurityContext.
I might as well include the context XML too of which I'm trying to convert to Java config style
<security:authentication-manager>
<security:jdbc-user-service
data-source-ref="dataSource"
users-by-username-query="select username, password, enabled from Users where username=?"
authorities-by-username-query="select username, authority from Authority where username =? " />
</security:authentication-provider>
</security:authentication-manager>
<security:http use-expressions="true">
<security:intercept-url pattern="/newaccount"
access="permitAll" />
<security:intercept-url pattern="/accountcreated"
access="permitAll" />
<security:intercept-url pattern="/createaccount"
access="permitAll" />
<security:intercept-url pattern="/error"
access="permitAll" />
<security:intercept-url pattern="/resources/**"
access="permitAll" />
<security:intercept-url pattern="/login"
access="permitAll" />
<security:intercept-url pattern="/setemote"
access="isAuthenticated()" />
<security:intercept-url pattern="/**"
access="isAuthenticated()" />
<security:intercept-url pattern="/*"
access="isAuthenticated()" />
<security:form-login login-page="/login"
default-target-url="/" login-processing-url="/j_spring_security_check"
username-parameter="username" password-parameter="password"
authentication-failure-url="/login?error=true" />
<security:csrf />
</security:http>
Good day.
You have to be sure that you have SecurityWebApplicationInitializer, looking like that:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(SecurityContext.class);
}
}
Where SecurityContext - is your class extending WebSecurityConfigurerAdapter.
If you already have it then the problem might be in the lack of roles.
To have roles you might want to implement the config a bit differently, something like that:
.antMatchers("/restricted_area/*")
.access("hasRole('ADMIN')")
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.successHandler(authenticationSuccessHandler)
.permitAll()
.and()
.logout()
.permitAll();
For working with roles and authentication you can extend org.springframework.security.core.userdetails.UserDetailsService having a separate class that would work along with the Spring' authorization/authentication machinery checking the credentials.
As you see I also have authenticationSuccessHandler here. This is actually extended
org.springframework.security.web.authentication.AuthenticationSuccessHandler
What it does is redirecting to specific pages depending on the role: e.g. regular user to user' dashboard, admin to admin' dashboard.
Not sure if this is relevant to your question though, but the implementation is something like that:
#Component("customHandler")
public class CustomAuthenticationHandler implements AuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationHandler.class);
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
#Autowired
private UserService userService;
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
Object principal = authentication.getPrincipal();
String username = ((UserDetails) principal).getUsername();
userService.updateLastLoginTimeByName(username);
handle(request, response, authentication);
clearAuthenticationAttributes(request);
}
protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException {
String targetUrl = determineTargetUrl(authentication);
if (response.isCommitted()) {
logger.debug("Response has already been committed. Unable to redirect to " + targetUrl);
return;
}
redirectStrategy.sendRedirect(request, response, targetUrl);
}
/**
* Builds the target URL according to the logic defined in the main class
* Javadoc.
*/
protected String determineTargetUrl(Authentication authentication) {
boolean isAdmin = false;
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
isAdmin = true;
break;
}
}
if (isAdmin) {
return "/restricted_area/";
} else {
throw new IllegalStateException();
}
}
protected void clearAuthenticationAttributes(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
protected RedirectStrategy getRedirectStrategy() {
return redirectStrategy;
}
}
I have working XML-based security configuration in my Spring MVC project:
<security:http use-expressions="true"
authentication-manager-ref="authenticationManager">
<security:intercept-url pattern="/" access="permitAll"/>
<security:intercept-url pattern="/dashboard/home/**" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')"/>
<security:intercept-url pattern="/dashboard/users/**" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/rest/users/**" access="hasRole('ROLE_ADMIN')"/>
<security:form-login login-page="/"/>
</security:http>
And I have question: is it possible to fully replace it by Java configuration? What annotations and where should I use for "use-expressions", "intercept-url", etc.?
Yes, if you are using Spring security 3.2 and above, it will be something like this :
#Configuration
#EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/dashboard/home/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/dashboard/users/**").hasRole("ADMIN")
.antMatchers("/rest/users/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/")
.permitAll();
}
// Possibly more overridden methods ...
}
How can I add my own logout handler to LogoutFilter in spring-security ?
Thanks!
The following solution works for me and may be helpful:
Extend the SimpleUrlLogoutSuccessHandler or implement the LogoutHandler:
public class LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
// Just for setting the default target URL
public LogoutSuccessHandler(String defaultTargetURL) {
this.setDefaultTargetUrl(defaultTargetURL);
}
#Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
// do whatever you want
super.onLogoutSuccess(request, response, authentication);
}
}
Add to your Spring Security Configuration:
<security:logout logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<bean id="logoutSuccessHandler" class="your.package.name.LogoutSuccessHandler" >
<constructor-arg value="/putInYourDefaultTargetURLhere" />
</bean>
See the answer in this post in the Spring Security Forum:
XML Definition:
<beans:bean id="logoutFilter" class="org.springframework.security.ui.logout.LogoutFilter">
<custom-filter position="LOGOUT_FILTER"/>
<beans:constructor-arg index="0" value="/logout.jsp"/>
<beans:constructor-arg index="1">
<beans:list>
<beans:ref bean="securityContextLogoutHandler"/>
<beans:ref bean="myLogoutHandler"/>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="securityContextLogoutHandler" class="org.springframework.security.ui.logout.SecurityContextLogoutHandler"/>
<beans:bean id="myLogoutHandler" class="com.whatever.CustomLogoutHandler">
<beans:property name="userCache" ref="userCache"/>
</beans:bean>
LogoutHandler class:
public class CustomLogoutHandler implements LogoutHandler {
private UserCache userCache;
public void logout(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) {
// ....
}
#Required
public void setUserCache(final UserCache userCache) {
this.userCache = userCache;
}
}
You can use java-config solutions like this.
#Configuration
#EnableWebSecurity
public class SpringSecurity2Config extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
//you can set other security config by call http.XXX()
http
.logout()
.addLogoutHandler(new CustomLogoutHandler())
.logoutUrl("/logout")
.logoutSuccessHandler(...)
.permitAll();
}
static class CustomLogoutHandler implements LogoutHandler {
#Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
//...
}
}
}
You should use success-handler-ref attribute of <logout> element:
<security:logout invalidate-session="true"
success-handler-ref="myLogoutHandler"
logout-url="/logout" />
As alternative solution you can configure your own filter on the logout URL.