How to set up Spring Security SecurityContextHolder strategy? - spring

I'm using asynchronous methods in my service (Spring 3 #Async annotation). And I've got a problem - spawned thread doesn't have security context. Cause of it is Spring Security by default uses SecurityContextHolder.MODE_THREADLOCAL strategy for its context holder. But I need to use SecurityContextHolder.MODE_INHERITABLETHREADLOCAL strategy.
For the moment I set up strategy in my AuthenticationSuccessHandler. But in my point of view it's not a good practice.
So how can I set it up in context configuration file?
Version of spring security is 3.0.0.

You can set the environment variable spring.security.strategy to MODE_INHERITABLETHREADLOCAL. You could also have a simple bean that during your web applications startup calls SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL) and initialize that value in your context configuration file.
SecurityContextHolder API

The java config for #viator 's answer if it helps you.
#Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
methodInvokingFactoryBean.setTargetMethod("setStrategyName");
methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
return methodInvokingFactoryBean;
}

A little bit another solution, like #viator write:
<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" value="MODE_INHERITABLETHREADLOCAL" />
</bean>
Working like a charm.

Via Java configuration without reflection.
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.context.SecurityContextHolder;
#Configuration
public class SecurityConfig {
#PostConstruct
public void enableAuthCtxOnSpawnedThreads() {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
}

Related

javanica #HystrixCommand and spring #Cacheable execution order

In a Spring Application (not spring-boot), I'm using javanica #HystrixCommand annotation and spring cache #Cacheable annotation on the same bean method, Spring execute the cache advice before the Hystrix advice.
It's what I'm waiting, but for me the cache advice and hystrix advice without any configuration have the same order in spring : LOWEST_PRECEDENCE.
I wan't to know what make this order : is it defined somewhere or this an undefined order and I'm lucky to have the good order ?
What must be done to ensure that cache advice will be executed before Hystrix advice (set order on cache:annotation-driven before LOWEST_PRECEDENCE ?)
This is an example of my code :
...
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
...
#Service
#Slf4j
#CacheConfig(cacheManager="myCacheManager")
public class MyRessourcesImpl implements MyRessources {
...
#Override
#HystrixCommand(commandProperties = {
#HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE"),
#HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "10000") })
#Cacheable("cacheName") //from spring cache
public Map<String, String> getTheMap() {
...
}
...
}
With this spring config :
<bean id="myCache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
<property name="configLocation" value="classpath:/META-INF/...." />
</bean>
<bean id="myCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="myCache" />
</bean>
<cache:annotation-driven cache-manager="myCacheManager" />
<aop:aspectj-autoproxy/>
<bean id="hystrixAspect" class="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect" />
Thanks for help
According to the docs, if you don't specify the order, it is undefined:
When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined. You can control the order of execution by specifying precedence. This is done in the normal Spring way by either implementing the org.springframework.core.Ordered interface in the aspect class or annotating it with the Order annotation. Given two aspects, the aspect returning the lower value from Ordered.getValue() (or the annotation value) has the higher precedence.
Credit: spring annotation advice order

Spring 4 (no boot) with custom jackson ObjectMapper

Secton 65.3 of the spring boot manual indicates that I can replace the default ObjectMapper by providing my own. I am not using boot, just a spring WebMVC application that builds to a .war and runs in tomcat.
It instantiates my ObjectMapper but doesn't use it. I used the debugger to trace through why timestamps still come out as numeric and found that it was using a different instance of ObjectMapper. It's not clear to me where it came from, or why this doesn't cause it to only use mine:
#Primary
#Bean
public ObjectMapper localObjectMapper() {
JodaMapper mapper = new JodaMapper();
mapper.setWriteDatesAsTimestamps(false);
mapper.getSerializationConfig().with(SerializationFeature.INDENT_OUTPUT)
.without(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
.without(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)
.without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
The above is in a #Configure bean that's definitely getting loaded.
The approach I took above worked fine in Spring 3, just not when I ugpraded to 4.2.2. I have read Jackson Integration Improvements as well, and tried approaches listed there, to the same effect.
--Chris
The way I always did it was:
#Configuration
#EnableWebMvc
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {
#Bean
public ObjectMapper localObjectMapper() {
JodaMapper mapper = new JodaMapper();
// ...
return mapper;
}
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter (localObjectMapper())); // use your own ObjectMapper
}
}
One warning, to quote the JavaDoc of WebMvcConfigurer.html#configureMessageConverters:
Note that adding converters to the list, turns off default converter registration. To simply add a converter without impacting default registration, consider using the method extendMessageConverters(java.util.List) instead.
In Spring 4 I've solved with the following xml-configuration
<bean name="jacksonObjectMapper"
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="featuresToDisable">
<array>
<util:constant
static-field="com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS" />
</array>
</property>
</bean>
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
putting it in the Servlet configuration file, usually under
/WEB-INF/spring/appServlet/*.xml

Grails initialization

In my Grails app, I need access to configuration exposed by a Java class similar to the below
public class Config {
private Properties properties = new Properties();
static load(String path) {
File configFile = new File(path);
FileReader fileReader = new FileReader(configFile);
properties.load(fileReader);
}
String getProperty(String name) {
properties.getProperty(name);
}
}
I trigger the initialisation of this class in the first line of Bootstrap.groovy by calling Config.load("/conf.properties"). However, the initialization of various Spring beans needs properties that are exposed by Config, but by the time Bootstrap.groovy is executed, Spring initialization has already completed.
So I need to find a way to call Config.load() before construction of the Spring beans, is this possible? I guess there might be an event handler available in /script/_Events.groovy that I could invoke it from, but I'm not sure which handlers are available.
Unfortunately, changing the source code of Config.java isn't an option, and neither is eliminating my usage of this class.
You could try declaring a suitable bean in web-app/WEB-INF/applicationContext.xml, which is the definition of the root web application context as opposed to the GrailsApplication's internal context.
<bean id="initConfig" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="com.example.Config" />
<property name="targetMethod" value="load" />
<property name="arguments">
<list><value>/conf.properties</value></list>
</property>
</bean>
and modify the grailsApplication bean to depend on that:
<bean id="grailsApplication" depends-on="initConfig" class="...">

Spring AOP and apache shiro configuration.Annotations not been scanned

I've been struggling with a configuration which requires a knowledge in AOP.
i must admit that AOP is that part i'm trying to get for a while without success.
It seems that my shiro annotations are not scanned and thus are ignored.
i've tried using shiro 1.1.0+ maven3+spring 3.0.5.RELEASE, hibernate 3.6.1.Final with ZK 5.0.6.
i got my hibernaterealm working , talking to database, i got the authentication working, i successfully(i believe) get the roles and permission loaded.
so to test the authorization side i have somewhere in my code this :
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isPermitted("businessaccount:list")) {
throw new AuthorizationException("User not authorized");
}
and it works fine.
So i know my permissions were loaded.i'll be convenient for me using annotations to i've put it in implementation class, because i didn't plan on using interface at first place with my controller classes which are extending ZK GenericForwardController.
i've seen this bug and i've decided to do a try with one interface with the #RequiresPersmissions on methods.
apparently it's still not working as in it's giving access to unauthorized subject.there is no error in my log.Maybe i'm doing something wrong here are snippet of the codes:
#Component("layouteventhandler")
public class LayoutEventHandlerImpl extends GenericForwardComposer implements LayoutEventHandler {
Logger logger = Logger.getLogger(LayoutEventHandlerImpl.class);
Menuitem logout;
//...
#Override
public void onClick$pAccounts() {
try {
execution.sendRedirect("/accounts/personal/list");
} catch (Exception ex) {
logger.info("Error redirecting to personal accounts", ex);
}
}
#Override
public void onClick$bAccounts() {
try {
execution.sendRedirect("/accounts/business/list");
} catch (Exception ex) {
logger.info("Error redirecting to business accounts", ex);
}
}
//.....
}
its interface it :
public interface LayoutEventHandler {
#RequiresPermissions(value="personalaccount:list")
public void onClick$pAccounts();
#RequiresPermissions(value="businessaccount:list")
public void onClick$bAccounts();
//.....
}
here is my shiro applicationcontext
<bean id="hibernateRealm" class="com.personal.project.admin.webapp.security.DatabaseRealm" />
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="hibernateRealm" />
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<!-- <property name="proxyTargetClass" value="true" />-->
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- Secure Spring remoting: Ensure any Spring Remoting method invocations can be associated
with a Subject for security checks. -->
<bean id="secureRemoteInvocationExecutor" class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- ... -->
is it in there something that i should do? thanks for reading and helping out
I don't know Shiro, but I'm guessing that you've put annotations on your bean classes which implement interfaces and then you're proxying them for security, transactions, and/or something else. When that happens, the object that's returned is a JDK dynamic proxy, which isn't an instance of your bean's concrete class, only of the interface it implements. Therefore any annotation scanning that depends on annotations in the concrete class won't find them.
To expand on Ryan Stewart's answer, you need to add
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
to the implementing class (not the interface) and move the Shiro annotations to it.
I encountered a similar problem when I was running two spring contexts. There is a parent root context that defined Database, Service, Security and non-SpringMVC web beans and a child web context for a Spring MVC REST api which contained the Controllers I want to proxy. The Configuration for each context was class path scanning separate packages.
In this case make sure that the DefaultAdvisorAutoProxyCreator and the AuthorizationAttributeSourceAdvisor beans that are requied are defined in the child web context (i.e. where the Rest Controllers are class path scanned) as defining them in the parent context does not work (the documentation on the DefaultAdvisorAutoProxyCreate is quite clear about this in hindsight!).
Posting this in case someone else encounters the same issue.

Testing JNDI Spring Websphere Outside the Container

I have successfully tested some DAO outside a weblogic server by looking up the datasource information through jndi. I have search for a similar option with websphere and have to yet come accross a solution that does not involve hardcoding the username and password in some location within the application or something similar. Right now my jndi settings look like this inside spring:
<bean id="applicationServerEnviromentProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties"><props>
<prop key="java.naming.factory.initial">com.ibm.websphere.naming.WsnInitialContextFactory</prop>
<prop key="java.naming.provider.url">iiop://localhost:2809</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>PeopleAppDS</value></property>
<property name="jndiEnvironment"><ref local="applicationServerEnviromentProperties"/></property>
</bean>
I have Tested the jndi connection and it is working when the application is loaded on to websphere. I would like to be able to test the daos inside eclipse for instance before the app is loaded. Any help would be much appreciated.
Here are the details for the test case.
-------BaseTestCase.java--------------------
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations= {"file:data-access-config.xml"})
public class BaseTestCase {
}
-----PersonDaoTest.java----------------
import static org.junit.Assert.assertNotNull;
import java.util.List;<br>
import org.junit.Test;<br>
import org.springframework.beans.factory.annotation.Autowired;
import ....dao.PersonDao;<br>
import ....domain.Person;<br>
public class PersonDaoTest extends BaseTestCase {
#Autowired
private PersonDao personDao;
#Test
public void findByName() {
List<Person> people = personDao.listByName("j%", false, "userId");
assertNotNull(people);
}
}
The right way to do it is to have a JNDI data source with a DriverManagerDataSource default. If you run in the container, Spring will use the named data source; if the lookup fails, it'll use the non-JNDI data source.

Resources