Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Thursday, 18 September 2014

Spring Security + @Async problem: (SecurityContextHolder is empty)


Problem: I annotated a method with @Async and @PreAuthorize so that is executed asynchronously and be secured.
But it seems the security context (SecurityContextHolder) is not populated (althouth user has authenticated).
This happens only if the method is annotated with @Async.

Solution: From SecurityContextHolder we can get e.g. the logged in username (e.g. check this). SecurityContextHolder is saved in
current thread [1]. When we spawn a new thread the current thread's SecurityContextHolder  (which is a ThreadLocals)
is not copied/inherited.

In order to inherit it do the following:

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetClass" value="org.springframework.security.core.context.SecurityContextHolder" />
        <property name="targetMethod" value="setStrategyName" />
        <property name="arguments">
            <list>
                <value>MODE_INHERITABLETHREADLOCAL</value>
            </list>
        </property>
    </bean>


All possible modes:
  • MODE_THREADLOCAL (default strategy)
  • MODE_INHERITABLETHREADLOCAL: spawned threads inherit SecurityContext of the parent thread
  • MODE_THREADLOCAL
  • SYSTEM_PROPERTY

[1] From the Spring Reference: "By default the SecurityContextHolder uses a ThreadLocal to store these details, which means that the security context is always available to methods in the same thread of execution ..."

Apache CXF+Spring: How to add authentication (dynamic credentials: from db, AD, etc)

 Server exposing Web Service


@WebService
public interface MyWebService {

...

}

@WebService(endpointInterface = "com.micharg.MyWebService")
public class MyWebServiceImpl implements MyWebService {

...
}


public interface WebServiceAuthenticationService {

}



@Service("webServiceAuthenticationService")
public class WebServiceAuthenticationServiceImpl implements Validator, WebServiceAuthenticationService {

    @Autowired
    private AuthenticationService authenticationService;
  
   
    @Override
    public Credential validate(Credential credential, RequestData data) throws WSSecurityException {

         String candidateUsername = credential.getUsernametoken().getName();
         String candidatePassword = credential.getUsernametoken().getPassword();
       
        boolean isUserAuthenticated = authenticationService.authenticate(candidateUsername, candidatePassword);
  
        if(!isUserAuthenticated ) {
             throw new WSSecurityException("Wrong credentials (" + candidateUsername + ", " + candidatePassword + "); can not execute web service");
         }
         
        return credential;
    }

}

<bean id="inbound-security" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
        <constructor-arg>
            <map>
                <entry key="action" value="UsernameToken" />
                <entry key="passwordType" value="PasswordText" />
            </map>
        </constructor-arg>
 </bean>
   
<!-- Add authentication to the web service that listens to endpoint http://mydomain/myendpoint; -->
<jaxws:endpoint id="myWebService" implementor="#myWebServiceImpl" address="/myendpoint">
   
        <jaxws:properties>
            <entry key="ws-security.ut.validator" value-ref="webServiceAuthenticationService" />
        </jaxws:properties>
       
        <jaxws:inInterceptors>
            <ref bean="inbound-security" />
        </jaxws:inInterceptors>
</jaxws:endpoint>




Client consuming Web Service


<!-- consume web service located on http://foo.com/myendpoint

<jaxws:client id="myWebServicesClient"
            serviceClass="com.micharg.MyWebService"
            address="http://foo.com/myendpoint">
           
            <jaxws:outInterceptors>
                <ref bean="outbound-security" />
            </jaxws:outInterceptors>
    </jaxws:client>





<bean class="eu.europa.europarl.apapeople.people.web.ws.WebServicesCallbackHandler" id="webServicesCallbackHandler" />


<bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor" id="outbound-security">
        <constructor-arg>
            <map>
                <entry key="action" value="UsernameToken"/> 
                <entry key="user" value="dummy password - passwordCallbackClass overrides it"/> 
                <entry key="passwordType" value="PasswordText"/>
                <entry key="passwordCallbackRef" value-ref="webServicesCallbackHandler"/>          
            </map>
        </constructor-arg>
    </bean>   




public class WebServicesCallbackHandler implements CallbackHandler {

    private String username = "...";
    private String password = "...";
   
    @Override
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        WSPasswordCallback c = (WSPasswordCallback) callbacks[0];
        c.setIdentifier(username);
        c.setPassword(password);
    }

}
   

Spring+Apache CXF: How to disable XML payload limits

Error: "org.apache.cxf.staxutils.DepthExceededStaxException: reach the innerElementCountThreshold:50000"
Solution: Disable XML payload limits

   <!-- disable XML payload limits -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetClass" value="java.lang.System" />
        <property name="targetMethod" value="setProperty" />
        <property name="arguments">
            <list>
                <value>org.apache.cxf.stax.maxChildElements</value>
                <value>1000000</value>
            </list>
        </property>
    </bean>

PS: org.apache.cxf.interceptor.security.DepthRestrictingStreamInterceptor seem not to work

Thursday, 12 January 2012

Tomcat+Spring: how to load a resource (file) from the application path

Method #1

The following code shows how to read a file called src/a/b/file.txt from src/a/b/Foo.java:
package a.b;

public class Foo {
 ...

  // reads src/a/b/file.txt
  InputStream is = getClass().getResourceAsStream("file.txt");
 
 ...

}

Method #2

InputStream is = Foo.class
                .getClassLoader()
                .getResourceAsStream("a/b/file.txt");

Wednesday, 4 January 2012

Log4j+Spring warning: No appenders could be found for logger (org.springframework.web.context.ContextLoader)

Warning:
INFO: Initializing Spring root WebApplicationContext
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Jan 4, 2012 3:00:45 PM org.apache.catalina.core.ApplicationContext log
Solution: Log4jConfigListener MUST be the 1st listener in web.xml

  log4jConfigLocation
  /WEB-INF/classes/log4j-my.properties



  org.springframework.web.util.Log4jConfigListener


...other listeners here...

Wednesday, 30 November 2011

Spring+JUnit: the db results of a method are persisted during methods calls

Problem description

I want the db to become empty on each method call of a JUnit Test. My persistence.xml contains
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
The service layer is transactional (@Transactional) and my test is transactional ("defaultRollback = true"). But db changes are persisted among method calls so my tests fail!
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class MyTest {

 @Test
 public void test1() { 
          /*db is empty*/ 
          write sth to db;
          /*db is empty*/ 
        }

 @Test
 public void test2() {
          /*db is NOT empty*/
        }

Solution

Test should extend AbstractTransactionalJUnit4SpringContextTests

Thursday, 24 November 2011

What if I want to expose a bean in foo.jar that I have in WEB-INF/lib/foo.jar

What if I want to expose a bean in foo.jar that I have in WEB-INF/lib/foo.jar

If you have a bean (@ManagedBean or @Controller if using Spring) in jar then place faces-config.xml in foo.jar/META-INF/faces-config.xml

StackOverflow

Monday, 14 November 2011

How to inject a service into a converter in Spring

Wrong (throw NullException):


@Autowired
private FooService fooService;

Right:


public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue) {
FooService fooService = (FooService) FacesContextUtils.getWebApplicationContext(facesContext).getBean("fooService");
}

Monday, 7 November 2011

Spring: how to locate a file in WEB-INF/classes/resources

The project if built with Spring and has the standard filesystem of Maven.


Assume we want to read foo.txt in WEB-INF/classes/resources/foo.txt


ClassPathResource r = new ClassPathResource("foo.xml");
try {
System.out.println("full path"+r.getFile().getAbsolutePath());
} catch (IOException e1) {
e1.printStackTrace();
}

The output is the full path to foo.xml.

References
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/resources.html#resources-implementations-classpathresource

Friday, 4 November 2011

java.lang.ClassNotFoundException: org.springframework.web.*

error:
SEVERE: Error configuring application listener of class org.springframework.web.context.ContextLoaderListener
java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
java.lang.ClassNotFoundException: org.springframework.web.context.request.RequestContextListener
java.lang.ClassNotFoundException: org.springframework.web.util.Log4jConfigListener

Solution 1:
delete server (tested with Tomcat) and recreate it+deploy the project
Solution 2:
Make sure that in Eclipse the Maven Dependencies are included in the output war (right clich the project and go to Deployment Assembly/Add/Maven Dependencies )
Note:
The classes org.springframework.web.* are included in spring-web-#.#.#.jar (for me spring-web-3.0.5.RELASE.jar) but I already had this jar

Spring configuration error: Could not load JDBC driver class [com.mysql.jdbc.Driver]

Configuration error for Spring: Could not load JDBC driver class [com.mysql.jdbc.Driver]
Solution: add to pom.xml
<!-- 
- MySQL database driver
- GlassFish contains it / Tomcat needs it
- handles error "Could not load JDBC driver class [com.mysql.jdbc.Driver]"
-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
</dependency>

Tuesday, 14 June 2011

SSO

Shibboleth
http://shibboleth.internet2.edu/

OpenAM
http://forgerock.com/openam.html

Looks promising..supports integration with Spring but is very complex

Friday, 22 April 2011

Access from Servlet Spring @Autowired/@Resource


access @Autowired

public class RSSServlet extends HttpServlet {

 private static NewsService newsService;
 private static ApplicationContext ctx;
 private static String[] configs = {"classpath:applicationContext.xml"};

 static {
  ctx = new ClassPathXmlApplicationContext(configs);
  newsService = (NewsService)ctx.getBean("newsService");
 }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  //...
 }

}


==========================================

access @Resource

public class RSSServlet extends HttpServlet {

 private static Properties config;
 private static ApplicationContext ctx;
 private static String[] configs = {"classpath:applicationContext.xml"};
 private static String domain;

 static {
  ctx = new ClassPathXmlApplicationContext(configs);
  config = (Properties)ctx.getBean("runtimeConfig");
  domain = (String) config.get("domain");
  System.out.println("*** domain="+domain);
 }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  //...
 }

}


Monday, 11 April 2011

jBPM + Maven + JSF + GlassFish

If you use jBPM + Maven + JSF + GlassFish then this won't work (exception thrown Undefined Method - or sth like this)