[tlinh2110-BAEL1382] Add Security in SI (#3593)

* [tlinh2110-BAEL1382] Add Security in SI

* [tlinh2110-BAEL1382] Upgrade to Spring 5 & add Logger
This commit is contained in:
linhvovn
2018-02-07 03:43:44 +08:00
committed by maibin
parent 372cba10bb
commit 56316fd029
8 changed files with 452 additions and 6 deletions
@@ -0,0 +1,45 @@
package com.baeldung.si.security;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Service;
@Service
public class MessageConsumer {
private String messageContent;
private Map<String, String> messagePSContent = new ConcurrentHashMap<>();
public String getMessageContent() {
return messageContent;
}
public void setMessageContent(String messageContent) {
this.messageContent = messageContent;
}
public Map<String, String> getMessagePSContent() {
return messagePSContent;
}
public void setMessagePSContent(Map<String, String> messagePSContent) {
this.messagePSContent = messagePSContent;
}
@ServiceActivator(inputChannel = "endDirectChannel")
public void endDirectFlow(Message<?> message) {
setMessageContent(message.getPayload().toString());
}
@ServiceActivator(inputChannel = "finalPSResult")
public void endPSFlow(Message<?> message) {
Logger.getAnonymousLogger().info(Thread.currentThread().getName() + " has completed ---------------------------");
messagePSContent.put(Thread.currentThread().getName(), (String) message.getPayload());
}
}
@@ -0,0 +1,50 @@
package com.baeldung.si.security;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.security.channel.ChannelSecurityInterceptor;
import org.springframework.integration.security.channel.SecuredChannel;
import org.springframework.messaging.Message;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
@Configuration
@EnableIntegration
public class SecuredDirectChannel {
@Bean(name = "startDirectChannel")
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = { "ROLE_VIEWER", "jane" })
public DirectChannel startDirectChannel() {
return new DirectChannel();
}
@ServiceActivator(inputChannel = "startDirectChannel", outputChannel = "endDirectChannel")
@PreAuthorize("hasRole('ROLE_LOGGER')")
public Message<?> logMessage(Message<?> message) {
Logger.getAnonymousLogger().info(message.toString());
return message;
}
@Bean(name = "endDirectChannel")
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = { "ROLE_EDITOR" })
public DirectChannel endDirectChannel() {
return new DirectChannel();
}
@Autowired
@Bean
public ChannelSecurityInterceptor channelSecurityInterceptor(AuthenticationManager authenticationManager, AccessDecisionManager customAccessDecisionManager) {
ChannelSecurityInterceptor channelSecurityInterceptor = new ChannelSecurityInterceptor();
channelSecurityInterceptor.setAuthenticationManager(authenticationManager);
channelSecurityInterceptor.setAccessDecisionManager(customAccessDecisionManager);
return channelSecurityInterceptor;
}
}
@@ -0,0 +1,46 @@
package com.baeldung.si.security;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.security.channel.ChannelSecurityInterceptor;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Bean
public AccessDecisionManager customAccessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
decisionVoters.add(new RoleVoter());
decisionVoters.add(new UsernameAccessDecisionVoter());
AccessDecisionManager accessDecisionManager = new AffirmativeBased(decisionVoters);
return accessDecisionManager;
}
@Autowired
@Bean
public ChannelSecurityInterceptor channelSecurityInterceptor(AuthenticationManager authenticationManager, AccessDecisionManager customAccessDecisionManager) {
ChannelSecurityInterceptor channelSecurityInterceptor = new ChannelSecurityInterceptor();
channelSecurityInterceptor.setAuthenticationManager(authenticationManager);
channelSecurityInterceptor.setAccessDecisionManager(customAccessDecisionManager);
return channelSecurityInterceptor;
}
}
@@ -0,0 +1,82 @@
package com.baeldung.si.security;
import java.util.stream.Collectors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.config.GlobalChannelInterceptor;
import org.springframework.integration.security.channel.SecuredChannel;
import org.springframework.integration.security.channel.SecurityContextPropagationChannelInterceptor;
import org.springframework.integration.support.DefaultMessageBuilderFactory;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
@Configuration
@EnableIntegration
public class SecurityPubSubChannel {
@Bean(name = "startPSChannel")
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = "ROLE_VIEWER")
public PublishSubscribeChannel startChannel() {
return new PublishSubscribeChannel(executor());
}
@ServiceActivator(inputChannel = "startPSChannel", outputChannel = "finalPSResult")
@PreAuthorize("hasRole('ROLE_LOGGER')")
public Message<?> changeMessageToRole(Message<?> message) {
return buildNewMessage(getRoles(), message);
}
@ServiceActivator(inputChannel = "startPSChannel", outputChannel = "finalPSResult")
@PreAuthorize("hasRole('ROLE_VIEWER')")
public Message<?> changeMessageToUserName(Message<?> message) {
return buildNewMessage(getUsername(), message);
}
@Bean(name = "finalPSResult")
public DirectChannel finalPSResult() {
return new DirectChannel();
}
@Bean
@GlobalChannelInterceptor(patterns = { "startPSChannel", "endDirectChannel" })
public ChannelInterceptor securityContextPropagationInterceptor() {
return new SecurityContextPropagationChannelInterceptor();
}
@Bean
public ThreadPoolTaskExecutor executor() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setCorePoolSize(10);
pool.setMaxPoolSize(10);
pool.setWaitForTasksToCompleteOnShutdown(true);
return pool;
}
public String getRoles() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return securityContext.getAuthentication().getAuthorities().stream().map(auth -> auth.getAuthority()).collect(Collectors.joining(","));
}
public String getUsername() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return securityContext.getAuthentication().getName();
}
public Message<String> buildNewMessage(String content, Message<?> message) {
DefaultMessageBuilderFactory builderFactory = new DefaultMessageBuilderFactory();
MessageBuilder<String> messageBuilder = builderFactory.withPayload(content);
messageBuilder.copyHeaders(message.getHeaders());
return messageBuilder.build();
}
}
@@ -0,0 +1,45 @@
package com.baeldung.si.security;
import java.util.Collection;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
public class UsernameAccessDecisionVoter implements AccessDecisionVoter<Object> {
private String rolePrefix = "ROLE_";
@Override
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& !attribute.getAttribute().startsWith(rolePrefix)) {
return true;
}else {
return false;
}
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
@Override
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
if (authentication == null) {
return ACCESS_DENIED;
}
String name = authentication.getName();
int result = ACCESS_ABSTAIN;
for (ConfigAttribute attribute : attributes) {
if (this.supports(attribute)) {
result = ACCESS_DENIED;
if (attribute.getAttribute().equals(name)) {
return ACCESS_GRANTED;
}
}
}
return result;
}
}