Use spring security acl in spring boot - spring

I use spring boot 1.5.1 config the spring security acl without xml,but have some problem. My config java is:
The web security config class:
#Configuration
public class ACLConfig extends GlobalMethodSecurityConfiguration
{
#Autowired
DataSource dataSource;
#Bean(name = "aclCache")
public EhCacheBasedAclCache aclCache()
{
PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(
new ConsoleAuditLogger());
return new EhCacheBasedAclCache(aclEhCache().getObject(),
permissionGrantingStrategy, aclAuthorizationStrategy());
}
#Bean(name = "aclEhCache")
public EhCacheFactoryBean aclEhCache()
{
EhCacheFactoryBean factoryBean = new EhCacheFactoryBean();
EhCacheManagerFactoryBean cacheManager = new EhCacheManagerFactoryBean();
cacheManager
.setConfigLocation(new ClassPathResource("cache/ehcache.xml"));
factoryBean.setCacheName("aclCache");
factoryBean.setCacheManager(cacheManager.getObject());
return factoryBean;
}
#Bean
public LookupStrategy lookupStrategy()
{
return new BasicLookupStrategy(dataSource, aclCache(),
aclAuthorizationStrategy(), new ConsoleAuditLogger());
}
#Bean(name = "adminRole")
public SimpleGrantedAuthority adminRole()
{
return new SimpleGrantedAuthority(Const.ADMIN_ROLE);
}
#Bean
public AclAuthorizationStrategy aclAuthorizationStrategy()
{
return new AclAuthorizationStrategyImpl(adminRole(), adminRole(),
adminRole());
}
#Bean(name = "aclService")
public MutableAclService aclService()
{
EhCacheBasedAclCache aclCache = aclCache();
JdbcMutableAclService service = new JdbcMutableAclService(dataSource,
lookupStrategy(), aclCache);
service.setClassIdentityQuery("select ##IDENTITY");
service.setSidIdentityQuery("select ##IDENTITY");
return service;
}
#Bean(name = "aclDeleteVoter")
public AclEntryVoter aclDeleteVoter()
{
String processConfigAttribute = Const.ACL_DELETE;
Permission[] requirePermission = new Permission[2];
requirePermission[0] = org.springframework.security.acls.domain.BasePermission.ADMINISTRATION;
requirePermission[1] = org.springframework.security.acls.domain.BasePermission.DELETE;
AclEntryVoter aclEntryVoter = new AclEntryVoter(aclService(),
processConfigAttribute, requirePermission);
// 设置要管理的class
aclEntryVoter.setProcessDomainObjectClass(AclDomainClass.class);
return aclEntryVoter;
}
#Override
protected AffirmativeBased accessDecisionManager()
{
return aclAccessDecisionManager();
}
#Bean(name = "aclAccessDecisionManager")
public AffirmativeBased aclAccessDecisionManager()
{
List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<AccessDecisionVoter<? extends Object>>();
decisionVoters.add(new RoleVoter());
decisionVoters.add(aclDeleteVoter());
decisionVoters.add(afterAclRead());
decisionVoters.add(aclWriteVoter());
AffirmativeBased affirmativeBased = new AffirmativeBased(
decisionVoters);
return affirmativeBased;
}
#Bean(name = "afterAclRead")
public AclEntryVoter afterAclRead()
{
String processConfigAttribute = Const.ACL_READ;
Permission[] requirePermission = new Permission[2];
requirePermission[0] = org.springframework.security.acls.domain.BasePermission.ADMINISTRATION;
requirePermission[1] = org.springframework.security.acls.domain.BasePermission.READ;
AclEntryVoter aclEntryVoter = new AclEntryVoter(aclService(),
processConfigAttribute, requirePermission);
// 设置要管理的class
aclEntryVoter.setProcessDomainObjectClass(AclDomainClass.class);
return aclEntryVoter;
}
#Bean(name = "aclWriteVoter")
public AclEntryVoter aclWriteVoter()
{
String processConfigAttribute = Const.ACL_WRITE;
Permission[] requirePermission = new Permission[2];
requirePermission[0] = org.springframework.security.acls.domain.BasePermission.ADMINISTRATION;
requirePermission[1] = org.springframework.security.acls.domain.BasePermission.WRITE;
AclEntryVoter aclEntryVoter = new AclEntryVoter(aclService(),
processConfigAttribute, requirePermission);
// 设置要管理的class
aclEntryVoter.setProcessDomainObjectClass(AclDomainClass.class);
return aclEntryVoter;
}
#Override
protected MethodSecurityExpressionHandler createExpressionHandler()
{
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(
new AclPermissionEvaluator(aclService()));
return expressionHandler;
}
}
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true ,securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
}
#Secured(Const.ACL_DELETE)
public void delete(User user)
{
// TODO Auto-generated method stub
userMapper.delete(user);
ObjectIdentity oid = new ObjectIdentityImpl(User.class,
user.getId());
aclService.deleteAcl(oid, false);
}
but I visit this method throw a exception (org.springframework.security.access.AccessDeniedException);

Related

JwtAuthenticationToken is not in the allowlist, Jackson issue

I have created my authorization server using org.springframework.security:spring-security-oauth2-authorization-server:0.2.2 and my client using org.springframework.boot:spring-boot-starter-oauth2-client. The users are able to sign in and out successfully, however, while testing I noticed that if I log in successfully then restart the client (but not the server) without signing out and try to login in again the server throws the following error in an endless loop of redirects
java.lang.IllegalArgumentException: The class with org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken and name of org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
I tried to follow this link https://github.com/spring-projects/spring-security/issues/4370 but the solution on it did not work for me. I also tried a different solution described in this link https://github.com/spring-projects/spring-authorization-server/issues/397#issuecomment-900148920 and modified my authorization server code as follows:-
Here is my Jackson Configs
#Configuration
public class JacksonConfiguration {
/**
* Support for Java date and time API.
*
* #return the corresponding Jackson module.
*/
#Bean
public JavaTimeModule javaTimeModule() {
return new JavaTimeModule();
}
#Bean
public Jdk8Module jdk8TimeModule() {
return new Jdk8Module();
}
/*
* Support for Hibernate types in Jackson.
*/
#Bean
public Hibernate5Module hibernate5Module() {
return new Hibernate5Module();
}
/*
* Module for serialization/deserialization of RFC7807 Problem.
*/
#Bean
public ProblemModule problemModule() {
return new ProblemModule();
}
/*
* Module for serialization/deserialization of ConstraintViolationProblem.
*/
#Bean
public ConstraintViolationProblemModule constraintViolationProblemModule() {
return new ConstraintViolationProblemModule();
}
/**
* To (de)serialize a BadCredentialsException, use CoreJackson2Module:
*/
#Bean
public CoreJackson2Module coreJackson2Module() {
return new CoreJackson2Module();
}
#Bean
#Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(coreJackson2Module());
mapper.registerModule(javaTimeModule());
mapper.registerModule(jdk8TimeModule());
mapper.registerModule(hibernate5Module());
mapper.registerModule(problemModule());
mapper.registerModule(constraintViolationProblemModule());
return mapper;
}
}
and here is my Authorization server config
#Configuration(proxyBeanMethods = false)
public class AuthServerConfig {
private final DataSource dataSource;
private final AuthProperties authProps;
private final PasswordEncoder encoder;
public AuthServerConfig(DataSource dataSource, AuthProperties authProps, PasswordEncoder encoder) {
this.dataSource = dataSource;
this.authProps = authProps;
this.encoder = encoder;
}
#Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource);
}
#Bean
#Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer<>();
authorizationServerConfigurer.tokenRevocationEndpoint(tokenRevocationEndpoint -> tokenRevocationEndpoint
.revocationResponseHandler((request, response, authentication) -> {
Assert.notNull(request, "HttpServletRequest required");
HttpSession session = request.getSession(false);
if (!Objects.isNull(session)) {
session.removeAttribute("SPRING_SECURITY_CONTEXT");
session.invalidate();
}
SecurityContextHolder.getContext().setAuthentication(null);
SecurityContextHolder.clearContext();
response.setStatus(HttpStatus.OK.value());
})
);
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
http
.requestMatcher(endpointsMatcher)
.authorizeRequests(authorizeRequests -> authorizeRequests.anyRequest().authenticated())
.csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))
.apply(authorizationServerConfigurer);
return http.formLogin(Customizer.withDefaults()).build();
}
#Bean
public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate, TokenSettings tokenSettings) {
JdbcRegisteredClientRepository clientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
RegisteredClient webClient = RegisteredClient.withId("98a9104c-a9c7-4d7c-ad03-ec61bcfeab36")
.clientId(authProps.getClientId())
.clientName(authProps.getClientName())
.clientSecret(encoder.encode(authProps.getClientSecret()))
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.redirectUri("http://127.0.0.1:8000/login/oauth2/code/web-client")
.scope(OidcScopes.OPENID)
.scope(OidcScopes.PROFILE)
.tokenSettings(tokenSettings)
.build();
clientRepository.save(webClient);
return clientRepository;
}
#Bean
public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate,
RegisteredClientRepository registeredClientRepository,
ObjectMapper objectMapper) {
JdbcOAuth2AuthorizationService authorizationService =
new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper rowMapper = new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(registeredClientRepository);
ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
objectMapper.registerModules(SecurityJackson2Modules.getModules(classLoader));
objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
// You will need to write the Mixin for your class so Jackson can marshall it.
// objectMapper.addMixIn(UserPrincipal .class, UserPrincipalMixin.class);
rowMapper.setObjectMapper(objectMapper);
authorizationService.setAuthorizationRowMapper(rowMapper);
return authorizationService;
}
#Bean
public OAuth2AuthorizationConsentService authorizationConsentService(JdbcTemplate jdbcTemplate,
RegisteredClientRepository registeredClientRepository) {
return new JdbcOAuth2AuthorizationConsentService(jdbcTemplate, registeredClientRepository);
}
#Bean
public JWKSource<SecurityContext> jwkSource() {
RSAKey rsaKey = generateRsa();
JWKSet jwkSet = new JWKSet(rsaKey);
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
}
private static RSAKey generateRsa() {
KeyPair keyPair = generateRsaKey();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
return new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
}
private static KeyPair generateRsaKey() {
KeyPair keyPair;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
keyPair = keyPairGenerator.generateKeyPair();
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
return keyPair;
}
#Bean
public ProviderSettings providerSettings() {
return ProviderSettings.builder()
.issuer(authProps.getIssuerUri())
.build();
}
#Bean
public TokenSettings tokenSettings() {
return TokenSettings.builder()
.accessTokenTimeToLive(Duration.ofDays(1))
.refreshTokenTimeToLive(Duration.ofDays(1))
.build();
}
}
But am still facing the same issue.
How do I solve this? Any assistance is highly appreciated.
After trying out different solutions this was how I was able to solve it.
I changed my OAuth2AuthorizationService bean to look like this.
#Bean
public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate,
RegisteredClientRepository registeredClientRepository) {
JdbcOAuth2AuthorizationService authorizationService =
new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper rowMapper =
new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(registeredClientRepository);
JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper oAuth2AuthorizationParametersMapper =
new JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper();
ObjectMapper objectMapper = new ObjectMapper();
ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
List<Module> securityModules = SecurityJackson2Modules.getModules(classLoader);
objectMapper.registerModules(securityModules);
objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
objectMapper.addMixIn(JwtAuthenticationToken.class, JwtAuthenticationTokenMixin.class);
rowMapper.setObjectMapper(objectMapper);
oAuth2AuthorizationParametersMapper.setObjectMapper(objectMapper);
authorizationService.setAuthorizationRowMapper(rowMapper);
authorizationService.setAuthorizationParametersMapper(oAuth2AuthorizationParametersMapper);
return authorizationService;
}
and here is my JwtAuthenticationTokenMixin configurations
#JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
#JsonDeserialize(using = JwtAuthenticationTokenDeserializer.class)
#JsonAutoDetect(
fieldVisibility = JsonAutoDetect.Visibility.ANY,
getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
#JsonIgnoreProperties(ignoreUnknown = true)
public abstract class JwtAuthenticationTokenMixin {}
class JwtAuthenticationTokenDeserializer extends JsonDeserializer<JwtAuthenticationToken> {
#Override
public JwtAuthenticationToken deserialize(JsonParser parser, DeserializationContext context) throws IOException {
ObjectMapper mapper = (ObjectMapper) parser.getCodec();
JsonNode root = mapper.readTree(parser);
return deserialize(parser, mapper, root);
}
private JwtAuthenticationToken deserialize(JsonParser parser, ObjectMapper mapper, JsonNode root)
throws JsonParseException {
JsonNode principal = JsonNodeUtils.findObjectNode(root, "principal");
if (!Objects.isNull(principal)) {
String tokenValue = principal.get("tokenValue").textValue();
long issuedAt = principal.get("issuedAt").longValue();
long expiresAt = principal.get("expiresAt").longValue();
Map<String, Object> headers = JsonNodeUtils.findValue(
principal, "headers", JsonNodeUtils.STRING_OBJECT_MAP, mapper);
Map<String, Object> claims = new HashMap<>();
claims.put("claims", principal.get("claims"));
Jwt jwt = new Jwt(tokenValue, Instant.ofEpochMilli(issuedAt), Instant.ofEpochMilli(expiresAt), headers, claims);
return new JwtAuthenticationToken(jwt);
}
return null;
}
}
abstract class JsonNodeUtils {
static final TypeReference<Set<String>> STRING_SET = new TypeReference<Set<String>>() {
};
static final TypeReference<Map<String, Object>> STRING_OBJECT_MAP = new TypeReference<Map<String, Object>>() {
};
static String findStringValue(JsonNode jsonNode, String fieldName) {
if (jsonNode == null) {
return null;
}
JsonNode value = jsonNode.findValue(fieldName);
return (value != null && value.isTextual()) ? value.asText() : null;
}
static <T> T findValue(JsonNode jsonNode, String fieldName, TypeReference<T> valueTypeReference,
ObjectMapper mapper) {
if (jsonNode == null) {
return null;
}
JsonNode value = jsonNode.findValue(fieldName);
return (value != null && value.isContainerNode()) ? mapper.convertValue(value, valueTypeReference) : null;
}
static JsonNode findObjectNode(JsonNode jsonNode, String fieldName) {
if (jsonNode == null) {
return null;
}
JsonNode value = jsonNode.findValue(fieldName);
return (value != null && value.isObject()) ? value : null;
}
}
you don't need to create a Mixin, because it's all ready created by authorization springboot module. juste
#Bean
public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {
JdbcOAuth2AuthorizationService authorizationService = new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper rowMapper = new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(registeredClientRepository);
ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModules(new CoreJackson2Module());
objectMapper.registerModules(SecurityJackson2Modules.getModules(classLoader));
objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
rowMapper.setObjectMapper(objectMapper);
authorizationService.setAuthorizationRowMapper(rowMapper);
return authorizationService;
}
i think you miss this line and is where the token mixin is registered
objectMapper.registerModules(new CoreJackson2Module());

Multiple DataBase Configuration for Spring Data JPA 2.0.9 Release

I have two JPA Configurations Classes. I need to configure two databases (Oracle Connections). While I connect with the JDBC template it works perfectly by using #PersistenceContext. while using JPA Repo it took the default initially but before execution, it took second and execute the query. I am very much confused about this. Will anyone clear my doubt?
Spring Boot- 2.0.9
Spring-data-jpa - 2.0.9
Hibernate - 5.2.18
My First Class(Default) - JPAConfig.java ,
#ConditionalOnProperty(name = "embedded", havingValue = "true", matchIfMissing = true)
#Configuration
#RefreshScope
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager", basePackages = {
"kgfsl" })
public class JPAConfig {
#Bean
public Validator getValidator() {
return new LocalValidatorFactoryBean();
}
#Value("${db.url}")
String dbUrl = "jdbc:oracle:thin:#10.100.1.95:1539:HFSL12C";
#Value("${db.driverClassName}")
String dbDriverClassName = "oracle.jdbc.driver.OracleDriver";
#Value("${db.userName}")
String dbUserName = "TENYV2";
#Value("${db.password}")
String dbPassword = "TENYV2";
#Value("${db.databaseType}")
String dbDatabaseType = "Oracle";
#Value("${encryptionOn:false}")
private boolean encryptionOn;
#Bean
#Primary
#RefreshScope
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dbDriverClassName);
dataSource.setSchema(dbUserName);
dataSource.setUrl(dbUrl);
dataSource.setUsername(dbUserName);
if (encryptionOn)
dataSource.setPassword(CryptoUtil.decrypt(dbPassword));
else
dataSource.setPassword(dbPassword);
return dataSource;
}
#Bean
#Primary
#RefreshScope
public Map<String, Object> jpaProperties() {
Map<String, Object> props = new HashMap<>();
props.put("hibernate.dialect", ApplicationStartUpFactory.getDialect(dbDatabaseType));
props.put("javax.persistence.validation.mode", "none");
props.put("hibernate.id.new_generator_mappings", "false");
props.put("hibernate.default_schema", dbUserName);
return props;
}
public static int batchSize() {
return Integer.valueOf(Dialect.DEFAULT_BATCH_SIZE);
}
#Primary
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(true);
hibernateJpaVendorAdapter.setGenerateDdl(false);
hibernateJpaVendorAdapter.setDatabase(ApplicationStartUpFactory.getJPAVendor(dbDatabaseType));
hibernateJpaVendorAdapter.setDatabasePlatform(dbUserName);
return hibernateJpaVendorAdapter;
}
#Primary
#Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory().getObject());
}
#Bean()
#Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(this.dataSource());
lef.setJpaPropertyMap(this.jpaProperties());
lef.setJpaVendorAdapter(this.jpaVendorAdapter());
String entityPackages = "kgfsl.*.*";
lef.setPackagesToScan(entityPackages.split(","));
lef.setPersistenceUnitName("default"); // <- giving 'default' as name
return lef;
}
#Bean()
#Qualifier("jdbcTemplate")
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(this.dataSource());
}
#Bean(name = "namedParameterJdbcTemplate")
public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
return new NamedParameterJdbcTemplate(this.dataSource());
}
#SuppressWarnings("unused")
private DatabasePopulator createDatabasePopulator() {
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.setContinueOnError(false);
/*
* if (new ClassPathResource("basic_table.sql").exists())
* databasePopulator.addScript(new ClassPathResource("basic_table.sql"));
*/
return databasePopulator;
}
#Bean
#Primary
public PhysicalNamingStrategy physical() {
return new PhysicalNamingStrategyStandardImpl();
}
#Bean
#Primary
public ImplicitNamingStrategy implicit() {
return new ImplicitNamingStrategyJpaCompliantImpl();
}
MY Second Class(Not Default) - JPADataSyncConfig.java,
#ConditionalOnProperty(name = "embedded", havingValue = "true", matchIfMissing = true)
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "dataSyncEntityManagerFactory", transactionManagerRef = "dataSyncTransactionManager", basePackages = {
"kgfsl" })
public class JPADataSyncConfig {
#Value("${db.syncurl}")
String dbUrl = "jdbc:oracle:thin:#10.100.1.94:1522:TENYY";
#Value("${db.syncurldriverClassName}")
String dbDriverClassName = "oracle.jdbc.driver.OracleDriver";
#Value("${db.syncuserName}")
String dbUserName = "MYNEWDB";
#Value("${db.syncpassword}")
String dbPassword = "MYNEWDB";
#Value("${db.syncurldatabaseType}")
String dbDatabaseType = "Oracle";
#Value("${encryptionOn:false}")
private boolean encryptionOn;
#Bean(name = "dataSyncDataSource")
public DataSource dataSyncDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dbDriverClassName);
dataSource.setUrl(dbUrl);
dataSource.setUsername(dbUserName);
if (encryptionOn)
dataSource.setPassword(CryptoUtil.decrypt(dbPassword));
else
dataSource.setPassword(dbPassword);
return dataSource;
}
#Bean(name = "dataSyncJpaProperties")
public Map<String, Object> dataSyncJpaProperties() {
Map<String, Object> props = new HashMap<>();
props.put("hibernate.dialect", ApplicationStartUpFactory.getDialect(dbDatabaseType));
props.put("javax.persistence.validation.mode", "none");
props.put("hibernate.id.new_generator_mappings", "false");
return props;
}
public static int batchSize() {
return Integer.valueOf(Dialect.DEFAULT_BATCH_SIZE);
}
#Bean(name = "dataSyncJpaVendorAdapter")
public JpaVendorAdapter dataSyncJpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(false);
hibernateJpaVendorAdapter.setDatabase(ApplicationStartUpFactory.getJPAVendor(dbDatabaseType));
return hibernateJpaVendorAdapter;
}
#Bean(name = "dataSyncTransactionManager")
public PlatformTransactionManager dataSyncTransactionManager() {
return new JpaTransactionManager(dataSyncEntityManagerFactory().getObject());
}
#Bean(name = "dataSyncEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean dataSyncEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(this.dataSyncDataSource());
lef.setJpaPropertyMap(this.dataSyncJpaProperties());
lef.setJpaVendorAdapter(this.dataSyncJpaVendorAdapter());
String entityPackages = "kgfsl.*.*";
lef.setPackagesToScan(entityPackages.split(","));
return lef;
}
#Bean(name = "dataSyncJdbcTemplate")
public JdbcTemplate dataSyncJdbcTemplate() {
return new JdbcTemplate(this.dataSyncDataSource());
}
}
My Method Call,
#Transactional(rollbackFor = Exception.class)
public List<Customer> listPending(Long formId) throws Exception, JsonParseException, JsonMappingException,
ClassNotFoundException, JSONException, IOException, ParseException, CustomException {
List<Customer> auditData = customerRepo.findByFormIdAndStatus(formId, 'P');
return auditData;
}
I solved my Problem by Changing the base path. It's Working Fine.
My Second Class,
#ConditionalOnProperty(name = "embedded", havingValue = "true", matchIfMissing = true)
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "dataSyncEntityManagerFactory", transactionManagerRef = "dataSyncTransactionManager", basePackages = {
"kgfsl.rms.datasync" })
public class JPADataSyncConfig {

Why the "/index" redirect to the UnauthorizedUrl in shiro?

I test the shiro with springboot,but no matter what urls like 127.0.0.1:8080/index are redirected to the the UnauthorizedUrl("/error");
Here is my ShiroConfig:
#Configuration
public class ShiroConfig {
#Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
#Bean
#DependsOn("lifecycleBeanPostProcessor")
public MyShiroRealm myShiroRealm(){
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
}
#Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
#Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
//securityManager.setCacheManager(ehCacheManager());
return securityManager;
}
#Bean
public ShiroFilterFactoryBean shiroFilter() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
filterChainDefinitionMap.put("/index", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSuccessUrl("/welcome");
//Unauthorized;
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
#Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
#Bean
#ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
#Bean
public PassThruAuthenticationFilter passThruAuthenticationFilter(){
return new PassThruAuthenticationFilter();
}
}
And the Realm
public class MyShiroRealm extends AuthorizingRealm {
private static final Logger LOGGER = Logger.getLogger(MyShiroRealm.class);
#Resource
UserService userService;
#Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
LOGGER.info("AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) : "+principalCollection);
String principal=(String) principalCollection.getPrimaryPrincipal();
LOGGER.info(principal);
User user=(User) userService.findUserByName(principal);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
for(Role role:user.getRoles()){
info.addRole(role.getName());
for(Permission permission:role.getPermissions()){
info.addStringPermission(permission.getName());
}
}
return info;
}
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
LOGGER.info("AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) : "+authenticationToken);
String name=((UsernamePasswordToken)authenticationToken).getUsername();
User user=userService.findUserByName(name);
if (user != null) {
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("user", user);
return new SimpleAuthenticationInfo(name,user.getPassword(),getName());
} else {
return null;
}
}
}
Properties in application.properties
#thymeleaf
spring.thymeleaf.cache=false
#hibernate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true
#html
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
DB properties are not given. Tomcat's server port is 8080.
The recources dir:
dir of resource
When I access the "127.0.0.1:8080/index" ,it redirects to the "error" page setted by
shiroFilterFactoryBean.setUnauthorizedUrl("/error");.
when the "/login" Controller method is given it redirects to login page.
I am so confused and cannot find a way to solve it.
UPDATE
After moving the index.html to templates dir and make a #RequestMapping("/index") method,I get the index in browser.(If the index.html is in the static dir, A #RequestMapping("/index") method don't work.)
How could I get the static html ?
As I test, for the resources in static folder like "/css/**","/index.html" ,
If we want to access them without being intercepted by shiro,
full name like
"127.0.0.1:8080/css/a.css" or "127.0.0.1:8080/index.html",
should be used,
which the filterChainDefinitionMap should be setted as
filterChainDefinitionMap.put("/index.html", "anon");
filterChainDefinitionMap.put("/css/**", "anon");

Spring boot redirect loop

This project can be run in two ways to start: first,use the run debug Main.java: debug start, and then redirect loop;Second, debug by spring boot run commandrun (use the spring-boot-maven-plugin startup),but no redirection loop. The environment is those:spring-boot-starter-parent :1.2.3.RELEASE. How the whole?
/*--------- FreeMarker Configuration -------**/
#Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer fmc = new FreeMarkerConfigurer();
fmc.setPreferFileSystemAccess(false);
fmc.setTemplateLoaderPath("/WEB-INF/templates");
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("base", contextPath);
fmc.setFreemarkerVariables(variables);
Properties settings = new Properties();
settings.put("defaultEncoding","UTF-8");
fmc.setFreemarkerSettings(settings);
return fmc;
}
#Bean
public FreeMarkerViewResolver freeMarkerViewResolver() {
FreeMarkerViewResolver fvr = new FreeMarkerViewResolver();
fvr.setCache(false);
fvr.setPrefix("");
fvr.setSuffix(".ftl");
fvr.setContentType("text/html;charset=UTF-8");
return fvr;
}
/*--------- Shiro Configuration -------**/
private static Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
#Bean(name = "ShiroRealmImpl")
public ShiroDatabaseRealm getShiroRealm() {
return new ShiroDatabaseRealm();
}
#Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager() {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(getShiroRealm());
dwsm.setCacheManager(getEhCacheManager());
return dwsm;
}
#Bean(name = "shiroEhcacheManager")
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
return em;
}
#Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
*
* #return
*/
#Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(getDefaultWebSecurityManager());
return new AuthorizationAttributeSourceAdvisor();
}
#Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
shiroFilterFactoryBean.setLoginUrl("/initlogin");
shiroFilterFactoryBean.setUnauthorizedUrl("/login.jhtml");
shiroFilterFactoryBean.setSuccessUrl("/admin/common/main");
filterChainDefinitionMap.put("/admin/**", "authc");
filterChainDefinitionMap.put("/api/**", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/*--------- Mapping Handler -------**/
#RequestMapping(value={"/"})
private String home(){
return "redirect:/admin/common/main";
}
#RequestMapping(value={"/admin/common/main"}, method={RequestMethod.GET,RequestMethod.POST})
private String main(){
return "/admin/common/main";//main.ftl
}
#RequestMapping("/initlogin")
public String login(ModelMap model,HttpServletRequest request) {
boolean isAuth = SecurityUtils.getSubject().isAuthenticated();
if(isAuth){
return "redirect:/admin/common/main.jhtml";
}
return "login";
}
#RequestMapping(value={"/login"}, method={RequestMethod.GET,RequestMethod.POST})
public String login(String username,String password,ModelMap model){
boolean isAuth = SecurityUtils.getSubject().isAuthenticated();
if(!isAuth){//
String errorMsg = null;
try{
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
errorMsg = "admin.login.incorrectCredentials";
model.addAttribute("msg", ApplicationSupport.getMessageByEnv(errorMsg));
}else{
UsernamePasswordToken token = new UsernamePasswordToken(username,DigestUtils.md5Hex(password));
if (token!=null)
SecurityUtils.getSubject().login(token);
}
}catch(Exception e){
return "login";
}
return "login";// I want to go redirect to login.ftl
}
//redirect to main.ftl
return "redirect:/admin/common/main.jhtml";
}

HTTP-based metadata provider with SSL - Using MethodInvokingFactoryBean for Java-based configuration

I'm learning example on https://github.com/vdenotaris/spring-boot-security-saml-sample and I don't understand why author using both MethodInvokingFactoryBean and TLSProtocolConfigurer in WebSecurityConfig. What difference between them? Essentially the same results was obtained in each separate case of creating beans and MethodInvokingFactoryBean result has been overridden by TLSProtocolConfigurer.
com.vdenotaris.spring.boot.security.saml.web.config.WebSecurityConfig
#Bean
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader
.getResource("classpath:/saml/samlKeystore.jks");
String storePass = "nalle123";
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("apollo", "nalle123");
String defaultKey = "apollo";
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
}
#Bean
public TLSProtocolConfigurer tlsProtocolConfigurer() {
return new TLSProtocolConfigurer();
}
#Bean
public ProtocolSocketFactory socketFactory() {
return new TLSProtocolSocketFactory(keyManager(), null, "default");
}
#Bean
public Protocol socketFactoryProtocol() {
return new Protocol("https", socketFactory(), 443);
}
#Bean
public MethodInvokingFactoryBean socketFactoryInitialization() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(Protocol.class);
methodInvokingFactoryBean.setTargetMethod("registerProtocol");
Object[] args = {"https", socketFactoryProtocol()};
methodInvokingFactoryBean.setArguments(args);
return methodInvokingFactoryBean;
}
org.springframework.security.saml.trust.httpclient.TLSProtocolConfigurer
private String protocolName = "https";
private int protocolPort = 443;
private KeyManager keyManager;
private String sslHostnameVerification = "default";
private Set<String> trustedKeys;
#Override
public void afterPropertiesSet() throws Exception {
ProtocolSocketFactory socketFactory = new TLSProtocolSocketFactory(keyManager, trustedKeys, sslHostnameVerification);
Protocol p = new Protocol(protocolName, socketFactory, protocolPort);
Protocol.registerProtocol(protocolName, p);
}
#Autowired
public void setKeyManager(KeyManager keyManager) {
this.keyManager = keyManager;
}
Would you please tell me what I missed?

Resources