How to get Rabbit Password using ConnectionFactory? - rabbitmq

I want to get the bound Rabbit user and password in Cloud Foundry.
Configuration:
#Profile("cloud")
#Configuration
public class RabbitMQCloudConfig extends AbstractCloudConfig {
public ConnectionFactory rabbitFactory() {
return connectionFactory().rabbitConnectionFactory();
}
}
And in my controller I can get the rabbit user but how can I get the password?
#Autowired(required = false)
RabbitMQCloudConfig rabbitMQCloudConfig;
private void setRabbitCredentialsForCF() {
this.user = rabbitMQCloudConfig.rabbitFactory().getUsername();
//this.password = ????
}

It seems that you are using Spring's RabbitMQ integration as your client.
So the question is which ConnectionFactory implementation did you register as your ConnectionFactory Bean. If you are using any subclass of AbstractConnectionFactory, there is a public getRabbitConnectionFactory which returns a reference to the underlying Rabbit Connection factory. Once you get the RabbitConnectionFactory, getting password is pretty easy by calling the getPassword method.
org.springframework.amqp.rabbit.connection.AbstractConnectionFactory
/**
* Return a reference to the underlying Rabbit Connection factory.
* #return the connection factory.
* #since 1.5.6
*/
public com.rabbitmq.client.ConnectionFactory getRabbitConnectionFactory() {
return this.rabbitConnectionFactory;
}

Related

Logging user info and update operations from REST / EJB service

I need to log all update operations from my rest resources and store to a Database log table.
The idea is to store info like:
logged user
operation description about updated / saved entity
updated fields and reference key
My application is Java EE8 compatible, it uses REST / EJB and CDI stuff.
At first I thought of dealing all this stuff on EJB side, however the exposed services don't need to have logged user on the method signature, so adding it would result on a forcing..
Is there any way to send user information, that is normally retrieved by webrequest (we use a session token model authentication) and inject through EJB ?
If your session management is setup correctly, you can just inject the session context via:
#Resource
SessionContext sessionContext;
Then:
sessionContext.getCallerPrincipal().getName()
is your logged in user.
As mentioned before, SessionContext.getCallerPrincipal().getName() doesn't work as authentication mechanism does not provide it.
After some tries I found this:
On EJB side
#RequestScoped
public class UserInfo {
private String userId;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
if (this.userId != null) throw new UncheckedException("cannot infer userid twice");
this.userId = userId;
}
}
On REST side
#Inject
UserInfo userInfo;
void userAuthenticated(...) {
String userId = ... // get userid from access token through **WebRequest** object
userInfo.setUserId(userId);
}
Side note
I honestly would have preferred to inject userid on UserInfo constructor but I was not allowed doing this as WebRequest object does not belong to EJB context
Alternative way
Move all the logging process to REST side by using a Response filter.
Example code:
#Provider
public class LoggingFilter implements ContainerResponseFilter {
#Context
HttpServletRequest webRequest;
#Context
ResourceInfo resinfo;
#Inject
LoggingService loggingService;
#Override
public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) {
final Method resourceMethod = resinfo.getResourceMethod();
if (resourceMethod.isAnnotationPresent(Loggable.class) && containerResponseContext.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) {
// get all method's info and log to database ...
}
}

authentication in spring boot using graphql

I’m working on a spring boot project with GraphQL. I'm using graphql-java-tools and graphql-spring-boot-starter. I managed to configure security and session management with spring security as you can see in the java config files below.
Now the “/graphql” path is secured (it can be accessed only sending the “basic http authentication” or a session token (x-auth-token) in a http header of the request). Authenticating with “basic http authentication” on any GraphQL operation will start a new session and send back the new session token in a header, and that token can be used further to continue that session.
How to give access to anonymous users to some GraphQL queries/mutations keeping the above behavior?
If I change antMatchers("/graphql").authenticated() to antMatchers("/graphql").permitAll() in order to allow anonymous access, then my custom AuthenticationProvider is not called anymore even when I try to authenticate with “basic http authentication”.
Thanks!
Here are my configs:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationProvider authenticationProvider;
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) {
authenticationManagerBuilder.authenticationProvider(authenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/graphql").authenticated()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.httpBasic()
.and()
.headers()
.frameOptions().sameOrigin() // needed for H2 web console
.and()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry());
}
#Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
#Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
}
#EnableRedisHttpSession(maxInactiveIntervalInSeconds = 180)
public class HttpSessionConfig {
#Bean
public HttpSessionStrategy httpSessionStrategy() {
return new HeaderHttpSessionStrategy();
}
}
Instead of .antMatchers("/graphql").authenticated() we used .antMatchers("/graphql").permitAll(), then we removed .httpBasic() and also removed the custom AuthenticationProvider. Now the security configs look like this:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/graphql").permitAll()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.headers()
.frameOptions().sameOrigin() // needed for H2 web console
.and()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry());
}
#Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
#Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
}
Then we created a mutation for login that accepts the user's credentials and returns the session token. Here is the graphql schema:
login(credentials: CredentialsInputDto!): String
input CredentialsInputDto {
username: String!
password: String!
}
Basically the code we had in our custom AuthenticationProvider went into the service that is called by the login operation:
public String login(CredentialsInputDto credentials) {
String username = credentials.getUsername();
String password = credentials.getPassword();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
... credential checks and third party authentication ...
Authentication authentication = new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
httpSession.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());
return httpSession.getId();
}
The key is that we prepared the session context with the authenticated user's authentication and then we save it (in redis) as a session attribute called "SPRING_SECURITY_CONTEXT". This is all what spring needs to be able to automatically restore the context when you make a request having the "x-auth-token" header set with the value of the session token obtained from the login operation.
Now also anonymous calls are allowed because of .antMatchers("/graphql").permitAll() and in the service layer, on public methods we can use annotations like this: #Preauthorize("isAnonymous() OR hasRole("USER")").
Even though you need to use permitAll() you can still create reasonable default for your resolver methods using AOP.
You can create your custom security aspect that will require authentication by default.
Unsecured methods may be marked for example using annotation.
See my blog post for details: https://michalgebauer.github.io/spring-graphql-security

Closing WCF Connections from service

I have recently started a new job where WCF services are being used. I have used them in the past and am comfortable with them but from what I can recall if the client does not close the connection it has the ability to bring your service down entirely. I am aware of the proper procedure for closing the connections but if the responsibility is on the client, they may not follow the same practices and potentially have the ability to bring the service down. Is there any other way of handling the closing of the connections so that it is not reliant on the client doing the right thing? It seems odd that anyone who has access to your service has the ability to bring it down with such ease...
Thank you very much for any insights!
One option is to use session time out in the server. This actually faults the client channel.
There are only really three ways in which a session can terminated:
1) The client closes the proxy
2) The service's receiveTimeout is exceeded before the client sends another request
3) The service throws a non-fault exception which will fault the channel and so terminate the session
If you don't want the client involved then you only have 2 and 3 neither of which end well for the client - they will get an exception in both situation on the next attempt to talk to the service.
You could use Duplex messaging and get the service to notify the client that its requires session termination - the client then gets an opportunity to close down the proxy gracefully but this is a cooperative strategy
Or you need to use duplex (but still the client will have to call the service).
Here is some important points of the service implementation:
a: Use a static dictionary to keep the Client’s IP and callback channel. Before writing on the share object, lock the object.
b: Gets the IP address of the client using the GetAddressAsString method. You can get the IP of the client from the incoming message. The following statement shows how can we get the IP adddress of the Client in WCF:
RemoteEndpointMessageProperty clientEndpoint = OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
String ipAddress = clientEndpoint.Address;
If you are using the namepipe binding, you will not get the RemoteEndpointMessageProperty.
c: When the client creates the proxy of the service, it will call StartingService method immediately. Inside the StartingService method, I am keeping the callback channel of the client and current instance into the dictionary.
d: When the user of WCF service wants to disconnect a client, he/she will call the Disconnect method with the IP Address of the client.
e: The Disconnect method uses the IP Address to get the callback channel of the client and associate service instance of the client from the dictionary. Eventually, it notifies the client by using callback channel and close the incoming channel.
Here is the implementation through code:
[ServiceContract(CallbackContract=typeof(INotifyClientCallback),SessionMode=SessionMode.Required)]
public interface IService1
{
[OperationContract]
bool StartingService();
}
public interface INotifyClientCallback
{
[OperationContract(IsOneWay = true)]
void Disconnecting();
}
INotifyClientCallback interface for Callback.
Step 2: Implementation of the Contact:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service1 : IService1
{
private static readonly Dictionary subscribers = new Dictionary();
public static event EventHandler onClientAdded;
///
/// Returns the IP Address of the Client
///
///
public string GetAddressAsString()
{
if (!OperationContext.Current.IncomingMessageProperties.ContainsKey(RemoteEndpointMessageProperty.Name))
{
return "127.0.0.1";
}
RemoteEndpointMessageProperty clientEndpoint =
OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
return clientEndpoint.Address;
}
public bool StartingService()
{
//Get the callback reference
INotifyClientCallback callback = OperationContext.Current.GetCallbackChannel();
string IPAddress = GetAddressAsString();
lock (subscribers)
{
if (!subscribers.ContainsKey(IPAddress))
{
subscribers[IPAddress] = new CommunicationStore()
{ NotifyCallback = callback,
IService = OperationContext.Current.InstanceContext
};
if (onClientAdded != null)
{
onClientAdded(IPAddress, null);
}
}
}
return true;
}
public static void Disconnect(string ipAddress)
{
if (subscribers.ContainsKey(ipAddress))
{
CommunicationStore com = subscribers[ipAddress];
if (((ICommunicationObject)com.NotifyCallback).State == CommunicationState.Opened)
{
try
{
//fires the callback method
com.NotifyCallback.Disconnecting();
com.IService.IncomingChannels.FirstOrDefault().Close();
}
catch (Exception)
{
throw;
}
}
}
}
}
public class CommunicationStore
{
public InstanceContext IService { get; set; }
public INotifyClientCallback NotifyCallback { get; set; }
}

ConnectionPoolManager for RedisNativeClient

Is there a Connection Pool Manager available for RedisNativeClient? We are doing byte level operations and use RedisNativeClient instead of the RedisClient.
Here is the solution I implemented. RedisClient inherits RedisNativeClient so using PooledRedisClientManager and then casting the connection to RedisNativeClient works fine. It holds the same TCP socket.
P.S. I am using Dependency Injection so I keep the lifestyle of this helper class singleton.
//Lifestyle is singleton
public class RedisHelper:IRedisHelper
{
private readonly PooledRedisClientManager _poolManager;
public RedisHelper()
{
_poolManager = new PooledRedisClientManager("localhost:6379");
}
public void RedisSingleSet(string redisKey, byte[] redisValues)
{
using (var client = (RedisNativeClient)_poolManager.GetClient())
{
client.Set(redisKey, redisValues);
}
}
}

Spring security: adding "On successful login event listener"

I'm new to Spring Security. How do I add an event listener which will be called as a user logs in successfully? Also I need to get some kind of unique session ID in this listener which should be available further on. I need this ID to synchronize with another server.
You need to define a Spring Bean which implements ApplicationListener.
Then, in your code, do something like this:
public void onApplicationEvent(ApplicationEvent appEvent)
{
if (appEvent instanceof AuthenticationSuccessEvent)
{
AuthenticationSuccessEvent event = (AuthenticationSuccessEvent) appEvent;
UserDetails userDetails = (UserDetails) event.getAuthentication().getPrincipal();
// ....
}
}
Then, in your applicationContext.xml file, just define that bean and it will automatically start receiving events :)
The problem with AuthenticationSuccessEvent is it doesn't get published on remember-me login. If you're using remember-me authentication use InteractiveAuthenticationSuccessEvent instead, it works for normal login as well as for remember-me login.
#Component
public class LoginListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {
#Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event)
{
UserDetails userDetails = (UserDetails) event.getAuthentication().getPrincipal();
// ...
}
}
Similar to Phill's answer, but modified to take Generics into consideration:
public class AuthenticationListener implements ApplicationListener<AuthenticationSuccessEvent> {
#Override
public void onApplicationEvent(final AuthenticationSuccessEvent event) {
// ...
}
}
Another way using #EventListener
#EventListener
public void doSomething(InteractiveAuthenticationSuccessEvent event) { // any spring event
// your code
}
In Grails, with Spring Security Plugin, you can do this in Config.groovy:
grails.plugins.springsecurity.useSecurityEventListener = true
grails.plugins.springsecurity.onAuthenticationSuccessEvent = { e, appCtx ->
def session = SecurityRequestHolder.request.getSession(false)
session.myVar = true
}