AuthenticationProvider function authenticate not call after migration to spring security 4 - spring-security

AuthenticationProvider function authenticate not call after migration spring security 2 to spring security 4.
I am use custom provider and ldap authentication, all of my config its ok , but when I try to connect , I have an anonymousUser in my AccessDecisionVoter.vote
please see the description code here:
public class RoleVoter implements AccessDecisionVoter<Object> {
#SuppressWarnings("unchecked")
public boolean supports(Class clazz) {
return true;
}
/**
 * #see AccessDecisionVoter#supports(ConfigAttribute)
 */
public boolean supports(ConfigAttribute configAttribute) {
if (getAttributeValue(configAttribute) != null) {
try {
//Integer.parseInt(configAttribute.getAttribute());
return true;
} catch (Exception e) {
return false;
}
}
return false;
}
public String getAttributeValue(ConfigAttribute attribute){
if (attribute instanceof ConfigAttribute) { 
return attribute.toString();
} 
return attribute.getAttribute(); 
}
public int vote(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributeDefinition) {
return result;
}
}
#Component
public class MyAuthenticationProvider implements AuthenticationProvider  {
private static final Logger LOG = Logger
.getLogger(MyAuthenticationProvider.class);
protected MessageSourceAccessor messages = SpringSecurityMessageSource
.getAccessor();
private LdapAuthenticator authenticator;
private UserDetailsService userDetailsService;
private boolean useAuthenticationRequestCredentials = true;
public MyAuthenticationProvider(LdapAuthenticator authenticator,
UserDetailsService userDetailsService) {
setAuthenticator(authenticator);
setUserDetailsService(userDetailsService);
}
public MyAuthenticationProvider() {
}
//—> not called????
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class,authentication,messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.onlySupports",
"Only UsernamePasswordAuthenticationToken is supported"));
UsernamePasswordAuthenticationToken userToken = (UsernamePasswordAuthenticationToken) authentication;
//my authentication
return return new UsernamePasswordAuthenticationToken(user, password, user
.getAuthorities());
}
private LdapAuthenticator getAuthenticator() {
return authenticator;
}
protected UserDetailsService getUserDetailsService() {
return userDetailsService;
}
private void setAuthenticator(LdapAuthenticator authenticator) {
Assert.notNull(authenticator, "An LdapAuthenticator must be supplied");
this.authenticator = authenticator;
}
private void setUserDetailsService(UserDetailsService userDetailsService) {
Assert.notNull(userDetailsService,
"An UserDetailsService must be supplied");
this.userDetailsService = userDetailsService;
}
#SuppressWarnings("unchecked")
#Override
public boolean supports(Class authentication) {
return UsernamePasswordAuthenticationToken.class
.isAssignableFrom(authentication);
}
}
<?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:aop="http://www.springframework.org/schema/aop"
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-4.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">
    
<!-- Security configuration -->
    <security:http pattern="/struts/**" security="none" />
<security:http pattern="/resources/**" security="none" />
<security:http pattern="/dojo/**" security="none" />
<security:http pattern="/index.jsp" security="none" />
<security:http pattern="/pages/authentication/auth.jsp*"
security="none" />
<security:http pattern="/authentication/authErr.action*"
security="none" />
<security:http pattern="/authentication/auth.action*"
security="none" />
<security:http pattern="/authentication/logout.action*"
security="none" />
<security:http pattern="/resources/firefox/*" security="none" />
<!-- ************************************************************************** -->
<security:http disable-url-rewriting="false"  auto-config="true" use-expressions="false" access-decision-manager-ref="myAccessDecisionManager">
<security:access-denied-handler error-page="/pages/authentication/denied.jsp"/>
<security:csrf disabled="true"/>
    <security:headers disabled="true"/>
    
<security:intercept-url pattern="/struts/**" />
<security:intercept-url pattern="/resources/**" />
<security:intercept-url pattern="/dojo/**" />
<security:intercept-url pattern="/index.jsp" />
<security:intercept-url
pattern="/pages/authentication/auth.jsp*" />
<security:intercept-url
pattern="/authentication/authErr.action*" />
<security:intercept-url
pattern="/authentication/auth.action*" />
<security:intercept-url pattern="/authentication/logout.action*" />
<security:intercept-url pattern="/resources/firefox/*" />
<security:intercept-url pattern="/**" access="hasRole('1')" /><!-- OR access=1 -->
<security:form-login
login-page="/authentication/auth.action"
always-use-default-target="false"
default-target-url="/home/home.action"
authentication-failure-url="/authentication/authErr.action" />
<security:anonymous granted-authority="99" />
 
<security:session-management>
 <security:concurrency-control error-if-maximum-exceeded="true" max-sessions="1"/>
 </security:session-management>
</security:http>
<!-- LDAP configuration -->
<bean id="dbLdapManager"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="local.framework.ldap-java5.DBLdapManager" />
<property name="targetMethod" value="setDbLdapParameters" />
<property name="arguments">
<list>
<bean id="dbLdapParameters"
class="local.framework.ldap-java5.DBLdapParameters">
<property name="application" value="refpat" />
<property name="dbLdapDriver"
value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="dbLdapURL"
value="${ldap-host}" />
</bean>
</list>
</property>
</bean>
<bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="${ldap-host}" />
<property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
<property name="pooled" value="true" />
</bean>
<bean id="ldapAuthProvider"
class="mypackage.security.provider.MyAuthenticationProvider">
<!-- <security:custom-authentication-provider /> -->
<constructor-arg>
<bean
class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="contextSource" />
<property name="userDnPatterns">
<list>
<value>${ldap-dn-pattern}</value>
</list>
</property>
</bean>
</constructor-arg>
<constructor-arg ref="userService" />
</bean>
  <security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="ldapAuthProvider"/>
</security:authentication-manager>  
 
<bean id="userService"
class="mypackage.security.MyUserDetails">
<property name="serviceLookups" ref="serviceLookups" />
</bean>
<bean id="myAccessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"><!-- old:org.springframework.security.vote.UnanimousBased -->
<constructor-arg>
<list>
<bean class="mypackage.security.vote.RoleVoter"/>
<!-- other voter …—>
</list>
</constructor-arg>
</bean>
<bean id="loggerListener"
class="org.springframework.security.access.event.LoggerListener" />
</beans>
any solution/idea to solve my probleme ? thank a lot

Related

How to set exception handler in spring security oauth2

I have implemented spring security oauth2 in my server for authentication.Now i have to implement a exception handler which will be called when a REST request with wrong credentials,expired token,etc. comes and which will respond with json string as error message instead of throwing exception.How can i set a exception handler in spring security oauth2.Does it have a default error handler,if how to set that in configuration file?
Below is my code.
spring-security.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:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd ">
<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="authenticationManager"
xmlns="http://www.springframework.org/schema/security" >
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" method="POST" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/protected/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/protected/**" method="GET" access="ROLE_APP" />
<!-- <intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_FULLY" /> -->
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/logout" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/logout" method="GET" />
<sec:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="logoutSuccessHandler" class="com.example.myproject.security.LogoutImpl" >
<property name="tokenstore" ref="tokenStore"></property>
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="exceptionTranslator" ref="myExceptionTranslator"></property>
</bean>
<bean id="myExceptionTranslator"
class="org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator">
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="com.example.myproject.service.ClientService"/>
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="userService">
</authentication-provider>
</authentication-manager>
<bean id="userService"
class="com.example.myproject.service.UserService">
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials />
<oauth:password authentication-manager-ref="userAuthenticationManager"/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<!-- <bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" /> -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" >
<property name="authenticationKeyGenerator">
<bean class="com.example.myproject.service.UniqueAuthenticationKeyGenerator" />
</property>
</bean>
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="300000"></property>
<property name="clientDetailsService" ref="clientDetails" />
<property name="tokenEnhancer"><bean class="com.example.myproject.service.CustomTokenEnhancer" /></property>
</bean>
<sec:global-method-security
pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the
http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
</beans>
ClientService.java :
#Component
public class ClientService implements ClientDetailsService {
#Autowired
private OauthRepository oauthRepository;
#Override
public ClientDetails loadClientByClientId(String s) throws ClientRegistrationException{
BaseClientDetails clientDetails = oauthRepository.getByClientId(s);
return clientDetails;
}
}
UserService.java :
#Component
public class UserService implements UserDetailsService {
#Autowired
private OauthRepository oauthRepository;
#Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
UserDetails user = oauthRepository.getByUsername(s);
return user;
}
}
OauthRepository.java :
#Repository
#Transactional
public class OauthRepository {
#Autowired
private SessionFactory sessionFactory;
#Autowired
private InMemoryTokenStore tokenStore;
private org.hibernate.Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
public UserDetails getByUsername(String username) {
MyUser user=new MyUser();
user.setUserName(username);
Query query=getCurrentSession().createQuery("FROM User WHERE userName=:usrName");
query.setParameter("usrName", username);
List<SiUser> getUser=query.list();
User act=getUser.get(0);
user.setPassword(act.getPassword());
user.setUserId(act.getUserId());
user.setAuthorities(getAuthorities(act.getUserId()));
return user;
}
public BaseClientDetails getByClientId(String clientId) {
System.out.println(" *** OauthRepository.getByClientId "+clientId);
Query query=getCurrentSession().createQuery("FROM OauthClientDetails WHERE clientId=:clientId");
query.setParameter("clientId", clientId);
List<OauthClientDetails> getClient=query.list();
OauthClientDetails oauthClient=getClient.get(0);
BaseClientDetails details = new BaseClientDetails();
details.setClientId(oauthClient.getClientId());
List<String> grantTypesList = Arrays.asList(oauthClient.getAuthorizedGrantTypes().split(","));
details.setAuthorizedGrantTypes(grantTypesList);
details.setClientSecret(oauthClient.getClientSecret());
return details;
}
/**
* Retrieves a collection of {#link GrantedAuthority} based on a numerical role
* #param role the numerical role
* #return a collection of {#link GrantedAuthority
*/
public Collection<GrantedAuthority> getAuthorities(Integer role) {
List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
return authList;
}
/**
* Converts a numerical role to an equivalent list of roles
* #param role the numerical role
* #return list of roles as as a list of {#link String}
*/
public List<String> getRoles(Integer role) {
List<String> roles = new ArrayList<String>();
Query query=getCurrentSession().createQuery("FROM UserRole WHERE userID=:userId");
query.setParameter("userId", role);
List<SiUserRole> getUser=query.list();
UserRole actRole=getUser.get(0);
roles.add(actRole.getRole());
return roles;
}
/**
* Wraps {#link String} roles to {#link SimpleGrantedAuthority} objects
* #param roles {#link String} of roles
* #return list of granted authorities
*/
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new GrantedAuthorityImpl(role));
}
return authorities;
}
}
servlet-context.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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<!-- #author Nagesh.Chauhan(neel4soft#gmail.com) -->
<context:annotation-config />
<context:component-scan base-package="com.example.myproject" />
<mvc:annotation-driven />
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="1000000000" />
</bean>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/MyDatabase"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<!-- Hibernate Session Factory -->
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan">
<array>
<value>com.example.myproject</value>
</array>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<!-- Activates annotation based transaction management -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

confirm-ack and confirm-nack channel not getting invoked

I am trying to configure the ack & nack channel and am getting the error like
"Only one confirm call back channel can be configured at a time"
Below are the things which I tried:
1. confirm-correlation-expression="#root" //no result found
2. Changed the amqp template like below
<rabbit:connection-factory id="connectionFactory" host="localhost" publisher-confirms="true" publisher-returns="true" />
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" mandatory="true" /> <!-- for nacks -->
<rabbit:admin connection-factory="connectionFactory" />
/>
The error was not there but the ack channel is not getting invoked.
Can anyone help me on this?
Here the MQ config
<rabbit:template id="nonTransactionalRabbitTemplate"
connection-factory="nonTransactionalConnectionFactory"
mandatory="true"
channel-transacted="false"
confirm-callback="confirmCallback"
return-call`enter code here`back="returnCallback" />
<rabbit:connection-factory id="nonTransactionalConnectionFactory"
connection-factory="rabbitClientConnectionFactory"
publisher-confirms="true"
publisher-returns="true"/>
<rabbit:connection-factory id="nonTransactionalConnectionFactory"
connection-factory="rabbitClientConnectionFactory"
publisher-confirms="true"
publisher-returns="true"/>
<bean id="rabbitClientConnectionFactory" class="com.rabbitmq.client.ConnectionFactory" >
<property name="uri" value="${mq.uri}" />
<property name="requestedHeartbeat" value="30" />
</bean>
Here is my outbound adapter
<int-amqp:outbound-channel-adapter channel="abc"
routing-key="xyz"
amqp-template="amqpTemplate"
confirm-correlation-expression="payload"
confirm-ack-channel="successRespTransformChannel"
confirm-nack-channel="failureRespTransformChannel"
return-channel="failureRespTransformChannel"
mapped-request-headers="*"
Here is my service activator
<chain input-channel="successRespTransformChannel">
<int:header-enricher>
<error-channel ref="failed-publishing" />
</int:header-enricher>
<service-activator id="successResp" expression="#abc.addRequestTracking(payload.id,'success')"/>
</chain>
When using the template in the adapter, you must NOT set your own callbacks
confirm-callback="confirmCallback"
return-callback="returnCallback" />
The adapter sets itself as the callback for both confirms and returns. This fails since you have already set the callbacks.
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" mandatory="true" /> <!-- for nacks -->
mandatory enables returns, not nacks.
EDIT
I have no idea what you are doing wrong. I just wrote a quick test case...
#SpringBootApplication
#ImportResource("context.xml")
public class So36546646Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = SpringApplication.run(So36546646Application.class, args);
ctx.getBean("out", MessageChannel.class).send(new GenericMessage<>("foo"));
boolean received = ctx.getBean(MyService.class).latch.await(10, TimeUnit.SECONDS);
if (!received) {
System.err.println("Did not receive ack");
}
ctx.getBean(RabbitAdmin.class).deleteQueue(ctx.getBean(Queue.class).getName());
ctx.close();
}
public static class MyService {
private final CountDownLatch latch = new CountDownLatch(1);
public void handle(Message<?> ack) {
System.out.println("ack:" + ack);
latch.countDown();
}
}
}
and
<?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:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:int-amqp="http://www.springframework.org/schema/integration/amqp"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
<rabbit:connection-factory id="cf" publisher-confirms="true" publisher-returns="true" host="localhost" />
<rabbit:template id="t" connection-factory="cf" mandatory="true" />
<rabbit:admin connection-factory="cf" />
<rabbit:queue id="anon" />
<int:channel id="out" />
<int-amqp:outbound-channel-adapter
channel="out"
amqp-template="t"
routing-key="#{anon.name}"
confirm-correlation-expression="payload"
confirm-ack-channel="acks"
confirm-nack-channel="acks"
return-channel="returns" />
<int:service-activator input-channel="acks" ref="service" />
<bean id="service" class="com.example.So36546646Application$MyService" />
<int:channel id="returns">
<int:queue />
</int:channel>
</beans>
and it worked fine:
ack:GenericMessage [payload=foo, headers={amqp_publishConfirm=true, id=5eed89bf-11b6-76a5-34ed-0091c6bac2c8, timestamp=1460464254229}]

Spring Security + LDAP Authentication- org.springframework.ldap.UncategorizedLdapException

I am using Spring Security where I have to authenticate the User from AD. Currently I have a login Form, Where when i provide correct login credentials it validates properly and after login it redirects to landing page. However if I provide wrong credential I am getting Following exception-
org.springframework.ldap.UncategorizedLdapException: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: JBAS011843: Failed instantiate InitialContextFactory com.sun.jndi.ldap.LdapCtxFactory from classloader ModuleClassLoader for Module "deployment.GPPortal.war:main" from Service Module Loader [Root exception is javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, vece]]
Please Help me resolving this exception as I am stuck with this from a long time.
This is my Spring-security.xml file-
<?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: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-3.0.xsd">
<context:component-scan base-package="com.svc.gp" />
<bean id="customAuthenticationFailureHandler"
class="com.svc.gp.customExceptionHandler.CustomAuthenticationFailureHandler">
<constructor-arg value="/GP/login"></constructor-arg>
</bean>
<!-- redirect url for failure of authentication -->
<!-- <bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<constructor-arg value="/login.jsp?error=1"></constructor-arg> </bean> -->
<!-- This is where we configure Spring-Security -->
<security:http auto-config="true" use-expressions="true"
access-denied-page="/GP/denied">
<security:intercept-url pattern="/GP/welcome"
access="permitAll" />
<security:intercept-url pattern="/GP/login"
access="permitAll" />
<security:intercept-url pattern="/GP/landing"
access="hasRole('ROLE_USER')" />
<security:intercept-url pattern="/GP/test"
access="permitAll" />
<security:form-login login-page="/GP/login"
default-target-url="/GP/test" authentication-failure-url="/GP/login?authfailed=true" />
<security:logout invalidate-session="true"
logout-success-url="/GP/login" logout-url="/GP/logout" />
</security:http>
<!-- For authentication: user-search-filter: the attribute name that contains
the user name user-search-base: the base path where to find user information
For authorization: group-search-filter: the attribute name that contains
the full dn of a user group-search-base: the base path where to find role
information group-role-attribute: the attribute name that contains the role
type role-prefix: the prefix to be added when retrieving role values For
server access: manager-dn: the full dn of the person that has access to an
LDAP server manager-password: the password of the person that has access
to an LDAP server -->
<security:authentication-manager>
<!-- <security:ldap-authentication-provider user-search-filter="(uid={0})"
user-search-base="ou=users" group-search-filter="(uniqueMember={0})" group-search-base="ou=groups"
group-role-attribute="cn" role-prefix="ROLE_"> </security:ldap-authentication-provider> -->
<security:authentication-provider
ref="ldapActiveDirectoryAuthProvider" />
<!-- For Roles against database -->
<security:authentication-provider>
<security:jdbc-user-service
data-source-ref="dataSource"
authorities-by-username-query="select username, role from user_roles where username =? " />
</security:authentication-provider>
</security:authentication-manager>
<!-- <security:ldap-server url="ldap://172.28.26.135:10389/o=fulcrum,dc=fulcrum,dc=com"
manager-dn="uid=admin,ou=system" manager-password="secret" /> -->
<bean id="ldapActiveDirectoryAuthProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="abc.com" />
<constructor-arg value="ldap://************" />
<property name="useAuthenticationRequestCredentials" value="true" />
<property name="convertSubErrorCodesToExceptions" value="true" />
</bean>
my CustomAuthenticationFailureHandler.java
package com.svc.gp.customExceptionHandler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
public class CustomAuthenticationFailureHandler extends
SimpleUrlAuthenticationFailureHandler {
private boolean forwardToDestination;
private RedirectStrategy redirectStrategy;
public CustomAuthenticationFailureHandler() {
super();
}
public CustomAuthenticationFailureHandler(String defaultFailureUrl) {
super(defaultFailureUrl);
System.out.println("defaultFailureUrl::" +defaultFailureUrl);
}
/* public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
super.onAuthenticationFailure(request, response, exception);
if (this.defaultFailureUrl == null) {
this.logger
.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(401,
"Authentication Failed: " + exception.getMessage());
} else {
saveException(request, exception);
if (this.forwardToDestination) {
this.logger.debug("Forwarding to " + this.defaultFailureUrl);
request.getRequestDispatcher(this.defaultFailureUrl).forward(
request, response);
} else {
this.logger.debug("Redirecting to " + this.defaultFailureUrl);
this.redirectStrategy.sendRedirect(request, response,
this.defaultFailureUrl);
}
}
}*/
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
if(exception.getClass().isAssignableFrom(BadCredentialsException.class)) {
setDefaultFailureUrl("/url1");
}
else if (exception.getClass().isAssignableFrom(DisabledException.class)) {
setDefaultFailureUrl("/url2");
}
else if (exception.getClass().isAssignableFrom(SessionAuthenticationException.class)) {
setDefaultFailureUrl("/url3");
}
super.onAuthenticationFailure(request, response, exception);
}
}
Here is my login.jsp
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Genius Plus Portal Login Page</title>
</head>
<body>
<%
Exception error = (Exception) request.getSession().getAttribute(
"SPRING_SECURITY_LAST_EXCEPTION");
if (error != null)
out.write(error.getMessage());
%>
<form action="../j_spring_security_check" method="POST">
<p>
<label for="j_username">Username</label> <input id="j_username"
name="j_username" type="text" />
</p>
<p>
<label for="j_password">Password</label> <input id="j_password"
name="j_password" type="password" />
</p>
<input type="submit" value="Login" />
</form>
</body>
</html>
Thanks in Advance.

Spring xml to resource.groovy

I am doing configuration in resource.groovy. I am stuck on 'bean-method' xml, how it will be set in resource.groovy and how to pass arguments to the method.
XML config is:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/neo4j
http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">
<context:component-scan base-package="neo4j"></context:component-scan>
j
<util:map id="config">
<entry key="ha.server_id" value="1" />
<entry key="ha.initial_hosts" value="127.0.0.1:5001,127.0.0.1:5002" />
<!-- put in more config parameters here, http://docs.neo4j.org/chunked/stable/ha-configuration.html -->
</util:map>
<bean id="graphDbFactory"
class="org.neo4j.graphdb.factory.HighlyAvailableGraphDatabaseFactory" />
<bean id="graphDbBuilder" factory-bean="graphDbFactory" factory-method="newHighlyAvailableDatabaseBuilder">
<constructor-arg value="/home/alok/Desktop/data1" />
</bean>
<bean id="graphDbBuilderFinal" factory-bean="graphDbBuilder"
factory-method="setConfig">
<constructor-arg ref="config" />
</bean>
<bean id="graphDatabaseService" factory-bean="graphDbBuilderFinal"
factory-method="newGraphDatabase" destroy-method="shutdown" />
<neo4j:config graphDatabaseService="graphDatabaseService" base-package="neo4j"/>
<neo4j:repositories base-package="neo4j" />
</beans>
My resource.groovy is
beans = {
xmlns neo4j:"http://www.springframework.org/schema/data/neo4j"
xmlns context:"http://www.springframework.org/schema/context"
context.'component-scan'('base-package': 'neo4j')
neo4j.'repositories'('base-package':'neo4j')
// neo4j.'config'('storeDirectory':'target/db5', 'base-package':'neo4j')
graphDbFactory(HighlyAvailableGraphDatabaseFactory)
graphDbBuilder=ref('graphDbFactory'){
bean -> bean.factoryMethod='newHighlyAvailableDatabaseBuilder'
bean.constructorArgs=['/home/alok/Desktop/data1']
}
println "after"
graphDbBuilderFinal=ref('graphDbBuilder'){
bean -> bean.factoryMethod='setConfig'
server_id= ["1"]
initial_hosts= ["127.0.0.1:5001,127.0.0.1:5002"]
}
graphDatabaseService=ref('graphDbBuilderFinal'){
bean -> bean.factoryMethod='newGraphDatabase'
}
neo4j.'config'('base-package':'neo4j')
}
I am getting error bean name must not be empty.
This should work:
import org.neo4j.graphdb.factory.HighlyAvailableGraphDatabaseFactory
beans = {
xmlns neo4j:"http://www.springframework.org/schema/data/neo4j"
xmlns context:"http://www.springframework.org/schema/context"
context.'component-scan'('base-package': 'neo4j')
neo4j.'repositories'('base-package':'neo4j')
// neo4j.'config'('storeDirectory':'target/db5', 'base-package':'neo4j')
def config = ['ha.server_id': 1, 'ha.initial_hosts': '127.0.0.1:5001,127.0.0.1:5002']
graphDbFactory(HighlyAvailableGraphDatabaseFactory)
graphDbBuilder(graphDbFactory: 'newHighlyAvailableDatabaseBuilder') { bean ->
bean.constructorArgs = ['/home/alok/Desktop/data1']
}
graphDbBuilderFinal(graphDbBuilder: 'setConfig') { bean ->
bean.constructorArgs = [config]
}
graphDatabaseService(graphDbBuilderFinal: 'newGraphDatabase') { bean ->
bean.destroyMethod = 'shutdown'
}
}
The syntax for beans with a factory instead of a class is:
graphDbBuilder(graphDbFactory:"newHighlyAvailableDatabaseBuilder") { bean ->
bean.constructorArgs = ...
}
Bean definitions must be method calls, your version has an assignment expression outside a bean definition block, which is not allowed.

Spring Security 3 not work with JDK 1.7

I'm using Spring Security 3 with LDAP authenticated in my Spring MVC project.
It works fine until I need to deploy my project to other environment and change JDK's version from 1.6 to 1.7.
below is my spring security config file and sample code:
1) security-application-Context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns:s="http://www.springframework.org/schema/security"
xmlns="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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<s:http use-expressions="true">
<s:intercept-url pattern="/auth/**" access="permitAll" />
<s:intercept-url pattern="/css/**" access="permitAll" />
<s:intercept-url pattern="/image/**" access="permitAll" />
<s:intercept-url pattern="/scripts/**" access="permitAll" />
<s:intercept-url pattern="/**" access="hasRole('GENERAL_USER')" />
<s:form-login login-page="/auth/login.html"
default-target-url="/welcome.html"
authentication-failure-url="/auth/login.html?error=1" />
<s:access-denied-handler error-page="/auth/denied.html"/>
<s:logout invalidate-session="true" logout-success-url="/auth/logoutSuccess.html"/>
</s:http>
<s:authentication-manager>
<s:authentication-provider ref="ldapAuthProvider" />
</s:authentication-manager>
<bean
id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"
scope="singleton">
<constructor-arg
value="ldap://ldapurl:389/dc=o,dc=a" />
<property name="userDn" value="cn=xxx,cn=users,dc=o,dc=a" />
<property name="password" value="password" />
<property name="baseEnvironmentProperties">
<map>
<entry key="java.naming.referral">
<value>follow</value>
</entry>
</map>
</property>
</bean>
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<!-- searchBase, searchFilter, contextSource -->
<constructor-arg index="0" value="" />
<constructor-arg index="1" value="(sAMAccountName={0})" />
<constructor-arg index="2" ref="contextSource" />
</bean>
<bean id="ldapAuthProvider"
class="com.foo.auth.MyLdapAuthenticationProvider">
<constructor-arg>
<bean
class="com.foo.auth.MyLdapAuthenticator">
<constructor-arg ref="contextSource" />
<property name="userSearch">
<ref bean="userSearch" />
</property>
</bean>
</constructor-arg>
<property name="authoritiesPopulator" ref="authoritiesPopulator" />
<property name="userDetailsContextMapper" ref="userDetailsMapper" />
</bean>
<bean id="authoritiesPopulator" class="com.foo.auth.MyLdapAuthoritiesPopulator">
<constructor-arg ref="userService" />
</bean>
<bean id="userService" class="com.foo.auth.MyLdapUserDetailsService">
<constructor-arg ref="userSearch" />
<property name="userDetailsMapper" ref="userDetailsMapper" />
</bean>
<bean id="userDetailsMapper" class="com.foo.auth.MyUserDetailsContextMapper">
</bean>
</beans>
2) after success logon will redirect the url to welcome.jsp, in welcome.jsp, I use spring security taglib to get logon user's full name. (for test, I use principal to show whole context info):
<security:authentication property="principal"></security:authentication>
when use JDK 1.6, principal shows:
com.foo.auth.MyUserDetails#3e2d20ec:.........
and I can use my custom UserDetail's attribute such like principal.fullName.
when use JDK 1.7, principal shows:
org.springframework.security.ldap.userdetails.LdapUserDetailsImpl#86dae957:...
it doesn't get my custom UserDetail object. so if I use JDKk1.7, I can't get Spring context correctly.
this issue takes me almost 1 week to found out the root cause is JDK version's problem ;-(
does anyone know why spring security with LDAP doesn't work in JDK1.7? or I miss something to config?
thank you in advance!
Problem fixed.
It is because my MyLdapAuthenticationProvider extends wrong provider.
I change MyLdapAuthenticationProvider extended class to LdapAuthenticationProvider,
and the spring security is work fine both in JDK 1.6 and 1.7 now.
Here is my custom LdapAuthenticationProvider:
public class MyLdapAuthenticationProvider extends LdapAuthenticationProvider {
private static Logger logger = Logger.getLogger(MyLdapAuthenticationProvider.class);
private MyLdapAuthenticator authenticator;
#Autowired
private MyLdapAuthoritiesPopulator authoritiesPopulator;
#Autowired
private MyUserDetailsContextMapper userDetailsContextMapper;
public MyLdapAuthenticationProvider(LdapAuthenticator authenticator) {
super(authenticator);
this.authenticator = (MyLdapAuthenticator) authenticator;
}
#Override
protected DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken userToken) {
try {
DirContextOperations dirCtx = getAuthenticator().authenticate(userToken);
return dirCtx;
} catch (PasswordPolicyException ppe) {
throw new LockedException(this.messages.getMessage(ppe.getStatus().getErrorCode(), ppe.getStatus()
.getDefaultMessage()));
} catch (UsernameNotFoundException notFound) {
throw new BadCredentialsException("User Name Error!");
} catch (NamingException ldapAccessFailure) {
throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure);
}
}
private void setAuthenticator(MyLdapAuthenticator authenticator) {
Assert.notNull(authenticator, "An LdapAuthenticator must be supplied");
this.authenticator = authenticator;
}
private MyLdapAuthenticator getAuthenticator() {
return authenticator;
}
public MyUserDetailsContextMapper getUserDetailsContextMapper() {
return userDetailsContextMapper;
}
public void setUserDetailsContextMapper(MyUserDetailsContextMapper userDetailsContextMapper) {
this.userDetailsContextMapper = userDetailsContextMapper;
}
public void setAuthoritiesPopulator(MyLdapAuthoritiesPopulator authoritiesPopulator) {
this.authoritiesPopulator = authoritiesPopulator;
}
public MyLdapAuthoritiesPopulator getAuthoritiesPopulator() {
return authoritiesPopulator;
}
}

Resources