All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.healthy.security.server.AppSecurityBeanConfig Maven / Gradle / Ivy

package com.healthy.security.server;

import cn.hutool.core.collection.ListUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.healthy.common.security.properties.SecurityProperties;
import com.healthy.security.server.handler.HealthyAccessDeniedHandler;
import com.healthy.security.server.handler.HealthyAuthenticationEntryPoint;
import com.healthy.security.server.kickout.KickOutPostProcessor;
import com.healthy.security.server.kickout.impl.RedisKickOutPostProcessor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Collections;

/**
 * Default policy configuration in browser environment. You can override the default
 * configuration by declaring beans of the same type or the same name.
 *
 * @author xiaomingzhang
 */
@Configuration
public class AppSecurityBeanConfig {

	@Resource
	private SecurityProperties securityProperties;

	@Resource
	private DataSource dataSource;

	@Resource
	private UserDetailsService userDetailsService;

	@Resource
	private AuthenticationEventPublisher authenticationEventPublisher;

	@Resource
	private ObjectMapper objectMapper;

	@Resource
	private RedisTemplate redisTemplate;

	@Resource
	private RedisConnectionFactory redisConnectionFactory;

	@Bean
	public ClientDetailsService clientDetails() {
		return new JdbcClientDetailsService(dataSource);
	}

	@Bean
	@ConditionalOnMissingBean(AccessDeniedHandler.class)
	public AccessDeniedHandler accessDeniedHandler() {
		HealthyAccessDeniedHandler accessDeniedHandler = new HealthyAccessDeniedHandler();
		accessDeniedHandler.setObjectMapper(objectMapper);
		return accessDeniedHandler;
	}

	@Bean
	@ConditionalOnMissingBean(AuthenticationEntryPoint.class)
	public AuthenticationEntryPoint authenticationEntryPoint(KickOutPostProcessor kickOutPostProcessor) {
		HealthyAuthenticationEntryPoint authenticationEntryPoint = new HealthyAuthenticationEntryPoint();
		authenticationEntryPoint.setKickOutPostProcessor(kickOutPostProcessor);
		return authenticationEntryPoint;
	}

	@Bean
	@ConditionalOnMissingBean(KickOutPostProcessor.class)
	public KickOutPostProcessor kickOutPostProcessor() {
		RedisKickOutPostProcessor kickOutPostProcessor = new RedisKickOutPostProcessor();
		kickOutPostProcessor.setKickOutCachePrefix(securityProperties.getOauth2().getKickOutCachePrefix());
		kickOutPostProcessor.setRedisTemplate(redisTemplate);
		return kickOutPostProcessor;
	}

	@Bean
	@Primary
	public HealthyTokenServices healthyTokenServices(ClientDetailsService clientDetailsService, TokenStore tokenStore,
			TokenEnhancerChain tokenEnhancerChain, KickOutPostProcessor kickOutPostProcessor) {
		HealthyTokenServices tokenServices = new HealthyTokenServices();
		tokenServices.setKickOut(securityProperties.getOauth2().isKickOut());
		tokenServices.setReuseRefreshToken(securityProperties.getOauth2().isReuseRefreshToken());
		tokenServices.setTokenStore(tokenStore);
		tokenServices.setSupportRefreshToken(true);
		tokenServices.setClientDetailsService(clientDetailsService);
		tokenServices.setKickOutPostProcessor(kickOutPostProcessor);
		tokenServices.setTokenEnhancer(tokenEnhancerChain);

		PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
		provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(userDetailsService));
		ProviderManager providerManager = new ProviderManager(Collections.singletonList(provider));
		providerManager.setAuthenticationEventPublisher(authenticationEventPublisher);
		tokenServices.setAuthenticationManager(providerManager);

		return tokenServices;
	}

	@Bean
	@ConditionalOnMissingBean(AuthenticationKeyGenerator.class)
	public AuthenticationKeyGenerator authenticationKeyGenerator() {
		return new DefaultAuthenticationKeyGenerator();
	}

	@Bean
	@ConditionalOnMissingBean(TokenStore.class)
	public TokenStore tokenStore(AuthenticationKeyGenerator authenticationKeyGenerator) {
		RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
		redisTokenStore.setPrefix(securityProperties.getOauth2().getRedisTokenStorePrefix());
		redisTokenStore.setAuthenticationKeyGenerator(authenticationKeyGenerator);
		return redisTokenStore;
	}

	@Bean
	@ConditionalOnMissingBean(name = "healthyTokenEnhancer")
	public TokenEnhancer healthyTokenEnhancer() {
		return new HealthyTokenEnhancer();
	}

	@Bean
	public TokenEnhancerChain tokenEnhancerChain(
			@Qualifier(value = "healthyTokenEnhancer") TokenEnhancer tokenEnhancer) {
		TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
		enhancerChain.setTokenEnhancers(ListUtil.toList(tokenEnhancer));
		return enhancerChain;
	}

	@Bean
	@ConditionalOnProperty(prefix = "healthy.security.oauth2", name = "jwt-token", havingValue = "true")
	public JwtAccessTokenConverter jwtAccessTokenConverter(
			@Qualifier("healthyTokenEnhancer") TokenEnhancer tokenEnhancer, TokenEnhancerChain tokenEnhancerChain) {
		JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
		converter.setSigningKey(securityProperties.getOauth2().getJwtSigningKey());
		tokenEnhancerChain.setTokenEnhancers(ListUtil.toList(tokenEnhancer, converter));
		return converter;
	}

	@Bean
	public TokenStoreUtil tokenStoreUtil() {
		return new TokenStoreUtil();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy