Log4j write spring-security username - spring-security

I am using log4j and spring-security in application, and the logger should write logs with username in every message. I am very new to all of this, can somebody help with advice or links? Maybe there is some standart ways of solving this?
Thank you.
EDIT
Using spring framework 3.1
My spring-security.xml is:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http pattern="/favicon.ico" security="none" />
<http auto-config="true">
<intercept-url pattern="/**" access="ROLE_ADMIN"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="detect_me" password="1111" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
And log4j.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %p [%c] - %m%n" />
</layout>
</appender>
<appender name="R" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="/logs/urlbuilderweb.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %p %t %c - %m%n" />
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<param name="BufferSize" value="10000"/>
<appender-ref ref="R"/>
</appender>
<logger name="org.springframework">
<level value="WARN"/>
</logger>
<logger name="org.directwebremoting">
<level value="WARN"/>
</logger>
<logger name="org.apache.http">
<level value="WARN"/>
</logger>
<logger name="org.hibernate">
<level value="WARN"/>
</logger>
<root>
<level value="INFO" />
<appender-ref ref="ASYNC"/>
</root>
</log4j:configuration>

You can use NDC feature.
Set up some filter / interceptor (depends on what presentation technology you use). Add nested diagnostic context (filter example):
public class LogDiagnosticContextFilter implements javax.servlet.Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// do nothing
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
SecurityContext context = SecurityContextHolder.getContext();
if (context != null) {
Authentication authentication = context.getAuthentication();
if (authentication != null) {
NDC.push("Username=" + authentication.getName());
}
}
chain.doFilter(request, response);
NDC.pop();
}
#Override
public void destroy() {
// do nothing
}
}
Ensure that filter executed after Spring Security filter chain (web.xml):
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>logDiagnosticContextFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
Add x to each interested log4j pattern:
%x %d %p %t %c - %m%n
Later when you call
LOGGER.info("some text");
anywhere in you code you will see
Username=corresponding_login some text
in your log

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 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.

Struts2 parameters is coming null in action class when using Interceptors

When I am using Interceptors, the values on Action class coming as null. I have removed the Interceptors, the values coming perfect from the JSP page.
Login.jsp
<s:form id="loginFrm" name="loginFrm" action="LoginAction">
<s:textfield key="username"/>
<s:password key="password"/>
<s:submit/>
</s:form>
LoginAction.java
public class LoginAction {
private static Logger LOGGER = Logger.getLogger(LoginAction.class);
private String username;
private String password;
public String execute() throws Exception {
LOGGER.info("LoginAction : authenticate()");
LOGGER.info("LoginAction : {[" + username + "],["+password+ "]}");
return "success";
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Bulk Fund Switching</display-name>
<context-param>
<param-name> org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG </param-name>
<param-value>/WEB-INF/tiles.xml</param-value>
</context-param>
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener </listener-class>
</listener>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>jsp/Login.jsp</welcome-file>
</welcome-file-list>
</web-app>
struts.xml (working version)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<constant name="struts.custom.i18n.resources" value="BFSView,BFSMessages" />
<package name="home-default" extends="struts-default" namespace="/">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<interceptors>
<interceptor name="AuthenticationInterceptor" class="com.lv.bfs.controller.interceptor.AuthenticationInterceptor"></interceptor>
<interceptor-stack name="SecureStack">
<interceptor-ref name="AuthenticationInterceptor" />
</interceptor-stack>
</interceptors>
<action name="LoginAction" class="com.lv.bfs.controller.action.LoginAction">
<result name="success">jsp/Welcome.jsp</result>
<result name="error">/jsp/Login.jsp</result>
</action>
</package>
</struts>
struts.xml (Not working version )
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<constant name="struts.custom.i18n.resources" value="BFSView,BFSMessages" />
<package name="home-default" extends="struts-default" namespace="/">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<interceptors>
<interceptor name="AuthenticationInterceptor" class="com.lv.bfs.controller.interceptor.AuthenticationInterceptor"></interceptor>
<interceptor-stack name="SecureStack">
<interceptor-ref name="AuthenticationInterceptor" />
</interceptor-stack>
</interceptors>
<action name="LoginAction" class="com.lv.bfs.controller.action.LoginAction">
<interceptor-ref name="SecureStack"></interceptor-ref>
<result name="success">jsp/Welcome.jsp</result>
<result name="error">/jsp/Login.jsp</result>
</action>
</package>
</struts>
AuthenticationInterceptor.java
public class AuthenticationInterceptor extends AbstractInterceptor {
private static Logger LOGGER = Logger.getLogger(AuthenticationInterceptor.class);
private static final long serialVersionUID = 1844249996954274967L;
public String intercept(ActionInvocation invocation) throws Exception {
LOGGER.info("intercept : START");
return invocation.invoke();
}
}
Logs statements (both cases)
12:39:05,533 INFO [AuthenticationInterceptor] intercept : START
12:39:05,533 INFO [LoginAction] LoginAction : authenticate()
12:39:05,533 INFO [LoginAction] LoginAction : {[null],[null]}
12:09:05,533 INFO [LoginAction] LoginAction : authenticate()
12:09:05,533 INFO [LoginAction] LoginAction : {[admin],[admin]}
Any suggestions?
When you define an interceptor stack for a specific action you must define all the interceptors for that action. In this case, you are only defining your custom interceptor, meaning the "params" interceptor doesn't run, so the action properties won't be set.
Either define a new stack that includes the normal S2 interceptors, or include those interceptors (or stack) in your action configuration.

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