Can multiple Spring sessions be backed by same redis instance? - spring-session

We have a couple of web applications written on Java Spring, we are using spring-data-redis and #EnableRedisHttpSession. I was wondering what are the spring session internals. Would it check redis database for duplicate session keys before creating a new session?
I looked at spring documentation and also did a google search but couldn't get a definitive answer.

Found the solution after going through spring session project's github issues. Answer provided by #Avnish doesn't work because in cluster configuration redis does not provide databases, there is just a single database 0 and SELECT commands are not supported.
spring-session#1.1.0.RELEASE solves this issue by providing session namespaces. If you are using #EnableRedisHttpSession annotation, you can add redisNamespace property to it. Or you can add the key in spring.session.redis.namespace property in your .properties or .yml file.

As far as as spring-session is concerned, it'll assume that another application is part of the cluster and will try to reuse existing session if found for given id, although very unlikely that two different applications will generate same session ids considering it's generated via random UUID. Following are the options that you can go with to safe guard yourself anyway.
If you are using spring boot, use different value of spring.redis.database property for each of your application (details here, search for "# REDIS")
If you are using spring-data-redis directly then you should be setting this value directly in the JedisConnectionFactory bean that you are using in your application. For XML configuration, following would do:
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="database" value="1" />
</beans>
Hope it helps!!

Related

JWT Authentication graphql-spqr with spring security

I am using graphql-spqr-spring-boot-starter, version 0.0.5 in my spring boot application.
#GraphQLApi & #GraphQLQuery working fine and I am fetching data on /gui as well.
But as many have faced I am trying to apply the authentication part on graphql server calls. I am using JWT token in my application for REST API authorization/authentication.
So I have token which I suppose can be used for validation here as well.
I have tried using:
#PreAuthorize("hasRole('ROLE_RECRUITER_HR')")
but it gives compile time error:
io.leangen.graphql.metadata.exceptions.TypeMappingException: The
registered object of type com.sun.proxy.$Proxy90 appears to be a
dynamically generated proxy
For these and other possible issues, is it better to use wrapper graphql library like spring-boot-starter or it is safer to use graphql-spqr which more steps in my hand.
EDIT: GraphQL SPQR Spring Boot starter v0.0.6 fixed the issue and should work out of the box.
This is a bug in the starter. It doesn't properly detect the types when JDK proxies (and not CGLib) are used. I will make sure to fix this for the next release.
There's a couple of ways to temporarily work around this, but none of them are nice unfortunately.
You could e.g. force Spring to use CGLIB by e.g.
#EnableAspectJAutoProxy(proxyTargetClass = true)
but this has potentially wide implications so I would recommend you simply wait a bit. I'll release a new version with a fix in a couple of days, as this is a very important bug.

log4j2 runtime configuration - in clustered/docker environment

I have various loggers with different log levels.
Initially loaded from a log4j2.xml
<Logger name="a.b.c" level="INFO">
I want to provide an option to modify or update the log levels at runtime using an API. The following lines of code work fine. I am just mentioning the relevant lines.
LoggerContext cxt = (LoggerContext) LogManager.getContext(false);
for (Logger l : cxt.getLoggers()) {
....
// I am getting logger config of the logger (I am doing this update only once per unique logger config)
LoggerConfig lc = l.get();
// This won't be hardcoded but will be obtained from request
lc.setLevel(Level.ERROR);
}
cxt.updateLoggers();
As mentioned this works fine when I test the application locally. It is updating all the loggers.
I was going through log4j2 configuration update documentation
https://logging.apache.org/log4j/2.x/manual/cloud.html
Managing Logging Configuration
Also, in a micro-services, clustered environment it is quite likely that these changes will need to be propagated to multiple servers at the same time. Trying to achieve this via REST calls could be difficult.
I am just wondering how can this propagation be achieved in a clustered environment or with multiple docker containers of the application running. I know I can call the update on individual containers but my question is about any possibility to update log levels in all containers programmatically in one go?
Thanks for your help.
I would suggest reviewing Logging in the Cloud and taking a look at the Log4j Spring Cloud Sample Application. If you are using a Spring Boot application it can automatically be notified when changes are made to the logging configuration hosted in Spring Cloud Config. Multiple applications can share a single configuration file.
You can accomplish the same thing without Spring Boot but it will be more difficult as you would have to implement your own RabbitMQ event listener and trigger Log4j's Watcher.

Can Spring Rabbitmq XML configuration of ssl properties "passPhrase" be compromised?

I have used Spring Rabbitmq XML configuration in my project. To create the RabbitConnectionFactoryBean, we provide the ssl.properties file resource with below properties
keyStore=file:/secret/keycert.p12
trustStore=file:/secret/trustStore
keyStore.passPhrase=secret
trustStore.passPhrase=secret
The passPhrases are hardcoded values. We are worried that any one who gains access to the system can read this file and misuse it. It is true that the system admin and OS should protect these files, but this can be considered a security threat when untrusted user logs in.
In this link Gary suggests to use Java configuration and we can use that to create the RabbitConnectionFactoryBean and maybe read the encrypted passwords from system and use the setter to set them in the bean.
But since we are already using XML configuration, is there any other ways to secure the passPhrases in the properties file?
Will this same configuration cause similar security issue in the PRODUCTION environment.?
Kindly help me on how to achieve security on the above.
Not sure if that is legal to say in the public, but I'll try.
There is some security token approach, when you start your project it requests such a token. An admin (or security representative) comes, inserts some special flesh drive, enter passwords. Your project reads properties from that device, populates all the properties and starts properly. That admin pulls flesh drive from USB and goes away. No one see password for your application!
The other solution you could consider is something like Config Server. So, your properties are stored somewhere outside of the current machine.
You also can really follow encryption way as well: http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/multi/multi__spring_cloud_context_application_context_services.html#_encryption_and_decryption

Swagger produces an uncomplete document when Spring Security is enabled

When I have Spring Security disabled, Swagger2 (springfox 2.5) seems to work fine, but when I enable it again, the JSON it produces when calling http://localhost:8082/v2/api-docs seems to have some kind of problem. Taking a look at the browser console I find:
TypeError: e.schema is undefined
Comparing both api-docs, the one produced with Spring Security on is much longer. I have done all that says here. It was really helpful for being able to reach Swagger with Spring Security on, but it seems not to be enough. Why are these JSON so different? Why the one with Spring Security on seems to lack some info?
We have also used below paths in our spring security config and it was enough:
"/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**"
Could you show some code?
What kind of JSON converter do you use? Gson, Jackson?
Do you have some spring/spring security configuration in xml files?

Spring SessionRegistry provides empty session lists when #EnableJdbcHttpSession is used

Since I persisted the session information of resilient and load balanced spring-boot based microservices to PostgreSQL DB by adding #EnableJdbcHttpSession to our config, the SessionRegistry provides no information at all anymore (e.g. SessionRegistry::getAllPrincipals() empty list).
Also HttpSessionListener is not getting fired anymore.
Grateful for any hint
Frank

Resources