I have the following configuration in my spring security xml file. When I try to authenticate I get the following message but cannot proceed.
INFO: Ignoring PartialResultException
I am aware that spring's documentation states that you can set ignorePartialResultException to true but this property seems to be in the LdapTemplate class which may require additional coding. I would like to accomplish all of this through bean configuration as I am not interested in role mapping.
<authentication-manager>
<authentication-provider ref="activeDirectoryAuthProvider" />
</authentication-manager>
<beans:bean id="activeDirectoryAuthProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<beans:constructor-arg value="mydomain.com" />
<beans:constructor-arg value=" ldap://mydomain.com:389" />
</beans:bean>
After digging around we found out that our role mapping was blocking the authentication. We were in fact hitting AD but Spring was trying to map a group name to a role that didn't exist within our system. Once we did that we were good to go.
Related
I am implementing Spring SAML in my web app which already has spring security implemented, due to which I have 2 authentication managers now. As spring always refer to the last declared authenticationManager, I found the solution to define one authenticationManager as a bean.
Following was my AuthenticationManager before conversion to bean:
<authentication-manager alias="samlAuthenticationManager">
<!-- Register authentication manager for SAML provider -->
<authentication-provider ref="samlAuthenticationProvider"/>
<!-- Register authentication manager for administration UI -->
<authentication-provider>
<user-service id="adminInterfaceService">
<user name="admin" password="admin" authorities="ROLE_ADMIN"/>
</user-service>
</authentication-provider>
</authentication-manager>
Following is my code after converting to bean:
<beans:bean id="samlAuthenticationManager" class="org.springframework.security.authentication.ProviderManager">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.saml.SAMLAuthenticationProvider">
<beans:property name="userDetails" value="adminInterfaceService"/>
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<user-service id="adminInterfaceService">
<user name="admin" password="admin" authorities="ROLE_ADMIN"/>
</user-service>
Authentication provider is defines as follows:
<beans:bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider">
<!-- OPTIONAL property: can be used to store/load user data after login -->
<!--
<beans:property name="userDetails" ref="bean" />
-->
</beans:bean>
I am getting following exception:
Cannot convert value of type 'java.lang.String' to required type
'org.springframework.security.saml.userdetails.SAMLUserDetailsService'
for property 'userDetails'
Please help regarding the same. I will be highly obliged.
Thanks in advance
Found the solution here
https://github.com/spring-projects/spring-security/issues/2163
Just had to use id instead of alias in both the authentication-manager
You shouldn't need to use Spring beans. If you don't specify an ID,
you will override the "default" instance. That's pretty much the way
standard Spring beans work. In the referenced thread, the user is
specifying an alias, rather than an ID, so that doesn't create a
separate instance. Again that's the way normal bean instances work, so
I'm not sure we should deviate from that.
I'm using spring security to manage user log in/signup in my project. I need to implement user lockout functionality after three failed log in attempts.What I did is to add another field 'account_non_locked' in 'Users' table in database.
The problem I'm facing is that spring security does not update that newly added column. I digged into the source code and found in the default UserDetailsManager the sql statement is written as:
"insert into users (username, password, enabled) values (?,?,?)"
which explains why it does not recognized my new column.
So I copy that file and change it to fit my own need, which is CustomUserDetailsManager.java
Now I can't configure spring security to use my own customized UserDetailsManager. The configuration file right now is:
<authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder ref="passwordEncoder" />
<jdbc-user-service id="userDetailsService" data-source-ref="dataSource" />
</authentication-provider>
</authentication-manager>
<beans:bean id="passwordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder" />
I can't find any examples online that will configure this properly. Please help and thanks in advance!
The section 3.2.4 Using other Authentication Providers covers how to do this using authentication-provider#user-service-ref.
Your example would look something like the following:
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="customUserDetailsManager">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
<beans:bean id="passwordEncoder"
class="org.springframework.security.crypto.password.StandardPasswordEncoder" />
<beans:bean id="customUserDetailsManager"
class="com.example.CustomUserDetailsManager">
<!-- additional properties -->
</beans:bean>
I was referring to this thread, and in the second last post by Rob Winch (Spring Security Lead), he mentions that we can have access to the sessionRegisty :
<session-management>
<concurrency-control session-registry-alias="sessionRegistry"/>
</session-management>
Therefore, I register the HttpSessionEventPublisher filter in web.xml and specify the above setting in my <http> section. I DON'T add this :
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
and in my class, I inject an instance of sessionRegistry like this :
#Autowired
private SessionRegistry sessionRegistry
This is how I am trying to find out the sessions for a user:
List<SessionInformation> userSessions = sessionRegistry.getAllSessions(username,false);
for (SessionInformation userSession : userSessions){
userSession.expireNow();
}
The principal is the username of the user. Upon debugging, the sessionRegistry variable's principals and sessionids variables are empty.
Am I doing anything wrong here, or are the steps mentioned by krams's blog, the only way to do this ?
Well you can autowire sessionRegistry. Nothing is wrong. I used it to track SessionInformation and registered sessions for UserPrincipal
It only worked for me if I changed session-registry-alias to session-registry-ref,and then defined the default impl:
<security:session-management>
<security:concurrency-control max-sessions="10" session-registry-ref="sessionRegistry"/>
</security:session-management>
<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
Well it depends which version of spring security you use.
In Spring Security 3.0 it is enough to have the configuration as follows:
<security:session-management>
<security:concurrency-control max-sessions="1"/>
</security:session-management>
Because internally there is used class ConcurrentSessionControlStrategy which invokes registerNewSession on sessionRegistry object.
In Spring Security 3.2 it is different and you have to use more verbose configuration. There is an example in the Spring Security reference doc
The most important part to have sessionRegistry filled with data is the following:
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry"/>
<beans:property name="maximumSessions" value="1" />
</beans:bean>
<beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry"/>
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
The registration of a new session in sessionRegistry is performed in RegisterSessionAuthenticationStrategy class.
Hopefully it will help you.
Too long for comment, so I answer.
Turn Spring Security debugging on (add to log4j.properties line log4j.logger.org.springframework.security=DEBUG). This should be standard procedure in such problems, as debugging prints many handy information that can show were the problem is.
Can you debug if public void registerNewSession(String sessionId, Object principal) method inside SessionRegistryImpl is called after logging? If not that means HttpSessionEventPublisher is not set up correctly.
You use #Autowired private SessionRegistry sessionRegistry; in your class, dont't you?
EDIT: Can you check if there are any principals in registry?
List<Object> userSessions = sessionRegistry.getAllPrincipals();
where Objects are principals instances you use.
this is my spring security file
<!-- Declare an authentication-manager to use a custom userDetailsService -->
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
</security:authentication-provider>
</security:authentication-manager>
<!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database -->
<bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>
<!-- A custom service where Spring will retrieve users and their corresponding access levels -->
<bean id="customUserDetailsService" class="com.vaannila.service.CustomUserDetailsService" />
This is running fine , i want to ask that if i use #Service on CustomUserDetailsService then can i delete the bean line form xml file and spring security will read the bean from annotation or not
Yes, assuming you don't move the bean to a different ApplicationContext (this is directly related to the location of your <context:component-scan.../> declaration).
Conversely, you can #Autowired many/most of the Spr Sec beans which are identified by a specific id.
<bean id="ntlmFilter" class="org.springframework.security.ui.ntlm.NtlmProcessingFilter">
<security:custom-filter position="NTLM_FILTER" />
<property name="stripDomain" value="true" />
<property name="defaultDomain" value="company" />
<property name="domainController" value="192.168.1.1" />
<property name="authenticationManager" ref="_authenticationManager" />
</bean>
may i know how to set failover second controller?
Unfortunately, NTLM isn't supported by Spring 3.
If using a secondary domain controller is a critical requirement for your application, I think you'll need to look into the jcifs source. Even jcifs doesn't want to support NTLM anymore either. But the old libraries are out there. I've hacked around so that my app will invisibly authenticate users whether they're from domainA or domainB. So it's possible, although possibly a bit daunting.
If I understood your question properly, you are looking for a fallback authentication provider, You can setup a list of authentication managers, so that if first one fails, it will automatically check with second one.
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="ntlmServiceAuthenticationProvider"/>
<security:authentication-provider ref="ldapAuthProvider"/>
</security:authentication-manager>