Remove remoting technologies support

Closes gh-10366
This commit is contained in:
Marcus Da Coregio 2021-10-13 10:04:10 -03:00
parent f672754c58
commit b2e6c60d94
27 changed files with 1 additions and 1723 deletions

View File

@ -208,24 +208,6 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
.isThrownBy(() -> setContext("<global-method-security />" + "<global-method-security />"));
}
// SEC-936
@Test
public void worksWithoutTargetOrClass() {
// @formatter:off
setContext("<global-method-security secured-annotations='enabled'/>"
+ "<b:bean id='businessService' class='org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean'>"
+ " <b:property name='serviceUrl' value='http://localhost:8080/SomeService'/>"
+ " <b:property name='serviceInterface' value='org.springframework.security.access.annotation.BusinessService'/>"
+ "</b:bean>"
+ ConfigTestUtils.AUTH_PROVIDER_XML);
// @formatter:on
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
SecurityContextHolder.getContext().setAuthentication(token);
this.target = (BusinessService) this.appContext.getBean("businessService");
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.target::someUserMethod1);
}
// Expression configuration tests
@SuppressWarnings("unchecked")
@Test

View File

@ -1,47 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.authentication.rcp;
import org.springframework.core.NestedRuntimeException;
import org.springframework.security.core.SpringSecurityCoreVersion;
/**
* Thrown if a <code>RemoteAuthenticationManager</code> cannot validate the presented
* authentication request.
* <p>
* This is thrown rather than the normal <code>AuthenticationException</code> because
* <code>AuthenticationException</code> contains additional properties which may cause
* issues for the remoting protocol.
*
* @author Ben Alex
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public class RemoteAuthenticationException extends NestedRuntimeException {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
/**
* Constructs a <code>RemoteAuthenticationException</code> with the specified message
* and no root cause.
* @param msg the detail message
*/
public RemoteAuthenticationException(String msg) {
super(msg);
}
}

View File

@ -1,51 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.authentication.rcp;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
/**
* Allows remote clients to attempt authentication.
*
* @author Ben Alex
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public interface RemoteAuthenticationManager {
/**
* Attempts to authenticate the remote client using the presented username and
* password. If authentication is successful, a collection of {@code GrantedAuthority}
* objects will be returned.
* <p>
* In order to maximise remoting protocol compatibility, a design decision was taken
* to operate with minimal arguments and return only the minimal amount of information
* required for remote clients to enable/disable relevant user interface commands etc.
* There is nothing preventing users from implementing their own equivalent package
* that works with more complex object types.
* @param username the username the remote client wishes to authenticate with.
* @param password the password the remote client wishes to authenticate with.
* @return all of the granted authorities the specified username and password have
* access to.
* @throws RemoteAuthenticationException if the authentication failed.
*/
Collection<? extends GrantedAuthority> attemptAuthentication(String username, String password)
throws RemoteAuthenticationException;
}

View File

@ -1,67 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.authentication.rcp;
import java.util.Collection;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.Assert;
/**
* Server-side processor of a remote authentication request.
* <p>
* This bean requires no security interceptor to protect it. Instead, the bean uses the
* configured <code>AuthenticationManager</code> to resolve an authentication request.
*
* @author Ben Alex
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public class RemoteAuthenticationManagerImpl implements RemoteAuthenticationManager, InitializingBean {
private AuthenticationManager authenticationManager;
@Override
public void afterPropertiesSet() {
Assert.notNull(this.authenticationManager, "authenticationManager is required");
}
@Override
public Collection<? extends GrantedAuthority> attemptAuthentication(String username, String password)
throws RemoteAuthenticationException {
UsernamePasswordAuthenticationToken request = new UsernamePasswordAuthenticationToken(username, password);
try {
return this.authenticationManager.authenticate(request).getAuthorities();
}
catch (AuthenticationException ex) {
throw new RemoteAuthenticationException(ex.getMessage());
}
}
protected AuthenticationManager getAuthenticationManager() {
return this.authenticationManager;
}
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
}

View File

@ -1,87 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.authentication.rcp;
import java.util.Collection;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.Assert;
/**
* Client-side object which queries a {@link RemoteAuthenticationManager} to validate an
* authentication request.
* <p>
* A new <code>Authentication</code> object is created by this class comprising the
* request <code>Authentication</code> object's <code>principal</code>,
* <code>credentials</code> and the <code>GrantedAuthority</code>[]s returned by the
* <code>RemoteAuthenticationManager</code>.
* <p>
* The <code>RemoteAuthenticationManager</code> should not require any special username or
* password setting on the remoting client proxy factory to execute the call. Instead the
* entire authentication request must be encapsulated solely within the
* <code>Authentication</code> request object. In practical terms this means the
* <code>RemoteAuthenticationManager</code> will <b>not</b> be protected by BASIC or any
* other HTTP-level authentication.
* </p>
* <p>
* If authentication fails, a <code>RemoteAuthenticationException</code> will be thrown.
* This exception should be caught and displayed to the user, enabling them to retry with
* alternative credentials etc.
* </p>
*
* @author Ben Alex
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public class RemoteAuthenticationProvider implements AuthenticationProvider, InitializingBean {
private RemoteAuthenticationManager remoteAuthenticationManager;
@Override
public void afterPropertiesSet() {
Assert.notNull(this.remoteAuthenticationManager, "remoteAuthenticationManager is mandatory");
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getPrincipal().toString();
Object credentials = authentication.getCredentials();
String password = (credentials != null) ? credentials.toString() : null;
Collection<? extends GrantedAuthority> authorities = this.remoteAuthenticationManager
.attemptAuthentication(username, password);
return new UsernamePasswordAuthenticationToken(username, password, authorities);
}
public RemoteAuthenticationManager getRemoteAuthenticationManager() {
return this.remoteAuthenticationManager;
}
public void setRemoteAuthenticationManager(RemoteAuthenticationManager remoteAuthenticationManager) {
this.remoteAuthenticationManager = remoteAuthenticationManager;
}
@Override
public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}

View File

@ -1,22 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Allows remote clients to authenticate and obtain a populated
* <code>Authentication</code> object.
* @deprecated as of 5.6.0 with no replacement
*/
package org.springframework.security.authentication.rcp;

View File

@ -1,66 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.authentication.rcp;
import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests {@link RemoteAuthenticationManagerImpl}.
*
* @author Ben Alex
*/
public class RemoteAuthenticationManagerImplTests {
@Test
public void testFailedAuthenticationReturnsRemoteAuthenticationException() {
RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl();
AuthenticationManager am = mock(AuthenticationManager.class);
given(am.authenticate(any(Authentication.class))).willThrow(new BadCredentialsException(""));
manager.setAuthenticationManager(am);
assertThatExceptionOfType(RemoteAuthenticationException.class)
.isThrownBy(() -> manager.attemptAuthentication("rod", "password"));
}
@Test
public void testStartupChecksAuthenticationManagerSet() throws Exception {
RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl();
assertThatIllegalArgumentException().isThrownBy(manager::afterPropertiesSet);
manager.setAuthenticationManager(mock(AuthenticationManager.class));
manager.afterPropertiesSet();
}
@Test
public void testSuccessfulAuthentication() {
RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl();
AuthenticationManager am = mock(AuthenticationManager.class);
given(am.authenticate(any(Authentication.class))).willReturn(new TestingAuthenticationToken("u", "p", "A"));
manager.setAuthenticationManager(am);
manager.attemptAuthentication("rod", "password");
}
}

View File

@ -1,107 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.authentication.rcp;
import java.util.Collection;
import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests {@link RemoteAuthenticationProvider}.
*
* @author Ben Alex
*/
public class RemoteAuthenticationProviderTests {
@Test
public void testExceptionsGetPassedBackToCaller() {
RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider();
provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(false));
assertThatExceptionOfType(RemoteAuthenticationException.class)
.isThrownBy(() -> provider.authenticate(new UsernamePasswordAuthenticationToken("rod", "password")));
}
@Test
public void testGettersSetters() {
RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider();
provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(true));
assertThat(provider.getRemoteAuthenticationManager()).isNotNull();
}
@Test
public void testStartupChecksAuthenticationManagerSet() throws Exception {
RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider();
assertThatIllegalArgumentException().isThrownBy(provider::afterPropertiesSet);
provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(true));
provider.afterPropertiesSet();
}
@Test
public void testSuccessfulAuthenticationCreatesObject() {
RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider();
provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(true));
Authentication result = provider.authenticate(new UsernamePasswordAuthenticationToken("rod", "password"));
assertThat(result.getPrincipal()).isEqualTo("rod");
assertThat(result.getCredentials()).isEqualTo("password");
assertThat(AuthorityUtils.authorityListToSet(result.getAuthorities())).contains("foo");
}
@Test
public void testNullCredentialsDoesNotCauseNullPointerException() {
RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider();
provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(false));
assertThatExceptionOfType(RemoteAuthenticationException.class)
.isThrownBy(() -> provider.authenticate(new UsernamePasswordAuthenticationToken("rod", null)));
}
@Test
public void testSupports() {
RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider();
assertThat(provider.supports(UsernamePasswordAuthenticationToken.class)).isTrue();
}
private class MockRemoteAuthenticationManager implements RemoteAuthenticationManager {
private boolean grantAccess;
MockRemoteAuthenticationManager(boolean grantAccess) {
this.grantAccess = grantAccess;
}
@Override
public Collection<? extends GrantedAuthority> attemptAuthentication(String username, String password)
throws RemoteAuthenticationException {
if (this.grantAccess) {
return AuthorityUtils.createAuthorityList("foo");
}
else {
throw new RemoteAuthenticationException("as requested");
}
}
}
}

View File

@ -21,7 +21,7 @@ Where a module depends on another Spring Security module, the non-optional depen
[[spring-security-core]]
== Core -- `spring-security-core.jar`
This module contains core authentication and access-contol classes and interfaces, remoting support, and basic provisioning APIs.
This module contains core authentication and access-contol classes and interfaces, and basic provisioning APIs.
It is required by any application that uses Spring Security.
It supports standalone applications, remote clients, method (service layer) security, and JDBC user provisioning.
It contains the following top-level packages:
@ -69,25 +69,6 @@ It contains the following top-level packages:
|===
[[spring-security-remoting]]
== Remoting -- `spring-security-remoting.jar`
This module provides integration with Spring Remoting.
You do not need this unless you are writing a remote client that uses Spring Remoting.
The main package is `org.springframework.security.remoting`.
.Remoting Dependencies
|===
| Dependency | Version | Description
| spring-security-core
|
|
| spring-web
|
| Required for clients which use HTTP remoting support.
|===
[[spring-security-web]]
== Web -- `spring-security-web.jar`
This module contains filters and related web-security infrastructure code.

View File

@ -1,53 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.integration;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Luke Taylor
* @since 2.0
*/
@ContextConfiguration(locations = { "/sec-936-app-context.xml" })
@ExtendWith(SpringExtension.class)
public class SEC936ApplicationContextTests {
/**
* SessionRegistry is used as the test service interface (nothing to do with the test)
*/
@Autowired
private SessionRegistry sessionRegistry;
@Test
public void securityInterceptorHandlesCallWithNoTargetObject() {
SecurityContextHolder.getContext()
.setAuthentication(new UsernamePasswordAuthenticationToken("bob", "bobspassword"));
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.sessionRegistry::getAllPrincipals);
}
}

View File

@ -1,20 +0,0 @@
apply plugin: 'io.spring.convention.spring-module'
dependencies {
management platform(project(":spring-security-dependencies"))
api project(':spring-security-core')
api 'org.springframework:spring-aop'
api 'org.springframework:spring-beans'
api 'org.springframework:spring-context'
api 'org.springframework:spring-core'
api 'org.springframework:spring-web'
testImplementation project(path: ':spring-security-core', configuration: 'tests')
testImplementation "org.assertj:assertj-core"
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.jupiter:junit-jupiter-params"
testImplementation "org.junit.jupiter:junit-jupiter-engine"
testImplementation "org.mockito:mockito-core"
testImplementation "org.mockito:mockito-junit-jupiter"
testImplementation "org.springframework:spring-test"
}

View File

@ -1,39 +0,0 @@
/*
* Copyright 2009-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.dns;
/**
* This will be thrown if no entry matches the specified DNS query.
*
* @author Mike Wiesner
* @since 3.0
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public class DnsEntryNotFoundException extends DnsLookupException {
private static final long serialVersionUID = -947232730426775162L;
public DnsEntryNotFoundException(String msg) {
super(msg);
}
public DnsEntryNotFoundException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright 2009-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.dns;
/**
* This will be thrown for unknown DNS errors.
*
* @author Mike Wiesner
* @since 3.0
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public class DnsLookupException extends RuntimeException {
public DnsLookupException(String msg, Throwable cause) {
super(msg, cause);
}
public DnsLookupException(String msg) {
super(msg);
}
}

View File

@ -1,83 +0,0 @@
/*
* Copyright 2009-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.dns;
/**
* Helper class for DNS operations.
*
* @author Mike Wiesner
* @since 3.0
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public interface DnsResolver {
/**
* Resolves the IP Address (A record) to the specified host name. Throws
* DnsEntryNotFoundException if there is no record.
* @param hostname The hostname for which you need the IP Address
* @return IP Address as a String
* @throws DnsEntryNotFoundException No record found
* @throws DnsLookupException Unknown DNS error
*/
String resolveIpAddress(String hostname) throws DnsEntryNotFoundException, DnsLookupException;
/**
* <p>
* Resolves the host name for the specified service in the specified domain
*
* <p>
* For example, if you need the host name for an LDAP server running in the domain
* springsource.com, you would call <b>resolveServiceEntry("ldap",
* "springsource.com")</b>.
*
* <p>
* The DNS server needs to provide the service records for this, in the example above,
* it would look like this:
*
* <pre>
* _ldap._tcp.springsource.com IN SRV 10 0 88 ldap.springsource.com.
* </pre>
*
* The method will return the record with highest priority (which means the lowest
* number in the DNS record) and if there are more than one records with the same
* priority, it will return the one with the highest weight. You will find more
* informatione about DNS service records at
* <a href="https://en.wikipedia.org/wiki/SRV_record">Wikipedia</a>.
* @param serviceType The service type you are searching for, e.g. ldap, kerberos, ...
* @param domain The domain, in which you are searching for the service
* @return The hostname of the service
* @throws DnsEntryNotFoundException No record found
* @throws DnsLookupException Unknown DNS error
*/
String resolveServiceEntry(String serviceType, String domain) throws DnsEntryNotFoundException, DnsLookupException;
/**
* Resolves the host name for the specified service and then the IP Address for this
* host in one call.
* @param serviceType The service type you are searching for, e.g. ldap, kerberos, ...
* @param domain The domain, in which you are searching for the service
* @return IP Address of the service
* @throws DnsEntryNotFoundException No record found
* @throws DnsLookupException Unknown DNS error
* @see #resolveServiceEntry(String, String)
* @see #resolveIpAddress(String)
*/
String resolveServiceIpAddress(String serviceType, String domain)
throws DnsEntryNotFoundException, DnsLookupException;
}

View File

@ -1,41 +0,0 @@
/*
* Copyright 2009-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.dns;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
/**
* This is used in JndiDnsResolver to get an InitialDirContext for DNS queries.
*
* @author Mike Wiesner
* @since 3.0
* @see InitialDirContext
* @see DirContext
* @see JndiDnsResolver
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public interface InitialContextFactory {
/**
* Must return a DirContext which can be used for DNS queries
* @return JNDI DirContext
*/
DirContext getCtx();
}

View File

@ -1,215 +0,0 @@
/*
* Copyright 2009-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.dns;
import java.util.Arrays;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
/**
* Implementation of DnsResolver which uses JNDI for the DNS queries.
*
* Uses an <b>InitialContextFactory</b> to get the JNDI DirContext. The default
* implementation will just create a new Context with the context factory
* <b>com.sun.jndi.dns.DnsContextFactory</b>
*
* @author Mike Wiesner
* @author Kathryn Newbould
* @since 3.0
* @see DnsResolver
* @see InitialContextFactory
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public class JndiDnsResolver implements DnsResolver {
private InitialContextFactory ctxFactory = new DefaultInitialContextFactory();
private static final int SERVICE_RECORD_PRIORITY_INDEX = 0;
private static final int SERVICE_RECORD_WEIGHT_INDEX = 1;
private static final int SERVICE_RECORD_PORT_INDEX = 2;
private static final int SERVICE_RECORD_TARGET_INDEX = 3;
/**
* Allows to inject an own JNDI context factory.
* @param ctxFactory factory to use, when a DirContext is needed
* @see InitialDirContext
* @see DirContext
*/
public void setCtxFactory(InitialContextFactory ctxFactory) {
this.ctxFactory = ctxFactory;
}
@Override
public String resolveIpAddress(String hostname) {
return resolveIpAddress(hostname, this.ctxFactory.getCtx());
}
@Override
public String resolveServiceEntry(String serviceType, String domain) {
return resolveServiceEntry(serviceType, domain, this.ctxFactory.getCtx()).getHostName();
}
@Override
public String resolveServiceIpAddress(String serviceType, String domain) {
DirContext ctx = this.ctxFactory.getCtx();
String hostname = resolveServiceEntry(serviceType, domain, ctx).getHostName();
return resolveIpAddress(hostname, ctx);
}
/**
* Resolves the host name for the specified service and then the IP Address and port
* for this host in one call.
* @param serviceType The service type you are searching for, e.g. ldap, kerberos, ...
* @param domain The domain, in which you are searching for the service
* @return IP address and port of the service, formatted [ip_address]:[port]
* @throws DnsEntryNotFoundException No record found
* @throws DnsLookupException Unknown DNS error
* @since 5.6
* @see #resolveServiceEntry(String, String)
* @see #resolveServiceIpAddress(String, String)
*/
public String resolveServiceIpAddressAndPort(String serviceType, String domain) {
DirContext ctx = this.ctxFactory.getCtx();
ConnectionInfo hostInfo = resolveServiceEntry(serviceType, domain, ctx);
return resolveIpAddress(hostInfo.getHostName(), ctx) + ":" + hostInfo.getPort();
}
// This method is needed, so that we can use only one DirContext for
// resolveServiceIpAddress().
private String resolveIpAddress(String hostname, DirContext ctx) {
try {
Attribute dnsRecord = lookup(hostname, ctx, "A");
// There should be only one A record, therefore it is save to return
// only the first.
return dnsRecord.get().toString();
}
catch (NamingException ex) {
throw new DnsLookupException("DNS lookup failed for: " + hostname, ex);
}
}
// This method is needed, so that we can use only one DirContext for
// resolveServiceIpAddress().
private ConnectionInfo resolveServiceEntry(String serviceType, String domain, DirContext ctx) {
String target = null;
String port = null;
try {
String query = new StringBuilder("_").append(serviceType).append("._tcp.").append(domain).toString();
Attribute dnsRecord = lookup(query, ctx, "SRV");
// There are maybe more records defined, we will return the one
// with the highest priority (lowest number) and the highest weight
// (highest number)
int highestPriority = -1;
int highestWeight = -1;
for (NamingEnumeration<?> recordEnum = dnsRecord.getAll(); recordEnum.hasMoreElements();) {
String[] record = recordEnum.next().toString().split(" ");
if (record.length != 4) {
throw new DnsLookupException(
"Wrong service record for query " + query + ": [" + Arrays.toString(record) + "]");
}
int priority = Integer.parseInt(record[SERVICE_RECORD_PRIORITY_INDEX]);
int weight = Integer.parseInt(record[SERVICE_RECORD_WEIGHT_INDEX]);
// we have a new highest Priority, so forget also the highest weight
if (priority < highestPriority || highestPriority == -1) {
highestPriority = priority;
highestWeight = weight;
target = record[SERVICE_RECORD_TARGET_INDEX].trim();
port = record[SERVICE_RECORD_PORT_INDEX].trim();
}
// same priority, but higher weight
if (priority == highestPriority && weight > highestWeight) {
highestWeight = weight;
target = record[SERVICE_RECORD_TARGET_INDEX].trim();
port = record[SERVICE_RECORD_PORT_INDEX].trim();
}
}
}
catch (NamingException ex) {
throw new DnsLookupException("DNS lookup failed for service " + serviceType + " at " + domain, ex);
}
// remove the "." at the end
if (target.endsWith(".")) {
target = target.substring(0, target.length() - 1);
}
return new ConnectionInfo(target, port);
}
private Attribute lookup(String query, DirContext ictx, String recordType) {
try {
Attributes dnsResult = ictx.getAttributes(query, new String[] { recordType });
return dnsResult.get(recordType);
}
catch (NamingException ex) {
if (ex instanceof NameNotFoundException) {
throw new DnsEntryNotFoundException("DNS entry not found for:" + query, ex);
}
throw new DnsLookupException("DNS lookup failed for: " + query, ex);
}
}
private static class DefaultInitialContextFactory implements InitialContextFactory {
@Override
public DirContext getCtx() {
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
env.put(Context.PROVIDER_URL, "dns:"); // This is needed for IBM JDK/JRE
try {
return new InitialDirContext(env);
}
catch (NamingException ex) {
throw new DnsLookupException("Cannot create InitialDirContext for DNS lookup", ex);
}
}
}
private static class ConnectionInfo {
private final String hostName;
private final String port;
ConnectionInfo(String hostName, String port) {
this.hostName = hostName;
this.port = port;
}
String getHostName() {
return this.hostName;
}
String getPort() {
return this.port;
}
}
}

View File

@ -1,20 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* DNS resolution.
*/
package org.springframework.security.remoting.dns;

View File

@ -1,98 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.httpinvoker;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Adds BASIC authentication support to <code>SimpleHttpInvokerRequestExecutor</code>.
*
* @author Ben Alex
* @author Rob Winch
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public class AuthenticationSimpleHttpInvokerRequestExecutor extends SimpleHttpInvokerRequestExecutor {
private static final Log logger = LogFactory.getLog(AuthenticationSimpleHttpInvokerRequestExecutor.class);
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
/**
* Provided so subclasses can perform additional configuration if required (eg set
* additional request headers for non-security related information etc).
* @param con the HTTP connection to prepare
* @param contentLength the length of the content to send
*
*/
protected void doPrepareConnection(HttpURLConnection con, int contentLength) throws IOException {
}
/**
* Called every time a HTTP invocation is made.
* <p>
* Simply allows the parent to setup the connection, and then adds an
* <code>Authorization</code> HTTP header property that will be used for BASIC
* authentication.
* </p>
* <p>
* The <code>SecurityContextHolder</code> is used to obtain the relevant principal and
* credentials.
* </p>
* @param con the HTTP connection to prepare
* @param contentLength the length of the content to send
* @throws IOException if thrown by HttpURLConnection methods
*/
@Override
protected void prepareConnection(HttpURLConnection con, int contentLength) throws IOException {
super.prepareConnection(con, contentLength);
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if ((auth != null) && (auth.getName() != null) && (auth.getCredentials() != null)
&& !this.trustResolver.isAnonymous(auth)) {
String base64 = auth.getName() + ":" + auth.getCredentials().toString();
con.setRequestProperty("Authorization",
"Basic " + new String(Base64.getEncoder().encode(base64.getBytes())));
if (logger.isDebugEnabled()) {
logger.debug("HttpInvocation now presenting via BASIC authentication SecurityContextHolder-derived: "
+ auth.toString());
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Unable to set BASIC authentication header as SecurityContext did not provide "
+ "valid Authentication: " + auth);
}
}
doPrepareConnection(con, contentLength);
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Enables use of Spring's <code>HttpInvoker</code> extension points to present the
* <code>principal</code> and <code>credentials</code> located in the
* <code>ContextHolder</code> via BASIC authentication.
* <p>
* The beans are wired as follows:
*
* <pre>
* &lt;bean id="test" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"&gt;
* &lt;property name="serviceUrl"&gt;&lt;value&gt;http://localhost/Test&lt;/value&gt;&lt;/property&gt;
* &lt;property name="serviceInterface"&gt;&lt;value&gt;test.TargetInterface&lt;/value&gt;&lt;/property&gt;
* &lt;property name="httpInvokerRequestExecutor"&gt;&lt;ref bean="httpInvokerRequestExecutor"/&gt;&lt;/property&gt;
* &lt;/bean&gt;
*
* &lt;bean id="httpInvokerRequestExecutor"
* class="org.springframework.security.core.context.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor"/&gt;
* </pre>
*/
package org.springframework.security.remoting.httpinvoker;

View File

@ -1,20 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Remote client related functionality.
*/
package org.springframework.security.remoting;

View File

@ -1,124 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.rmi;
import java.lang.reflect.InvocationTargetException;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.log.LogMessage;
import org.springframework.remoting.support.RemoteInvocation;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* The actual {@code RemoteInvocation} that is passed from the client to the server.
* <p>
* The principal and credentials information will be extracted from the current security
* context and passed to the server as part of the invocation object.
* <p>
* To avoid potential serialization-based attacks, this implementation interprets the
* values as {@code String}s and creates a {@code UsernamePasswordAuthenticationToken} on
* the server side to hold them. If a different token type is required you can override
* the {@code createAuthenticationRequest} method.
*
* @author James Monaghan
* @author Ben Alex
* @author Luke Taylor
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public class ContextPropagatingRemoteInvocation extends RemoteInvocation {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private static final Log logger = LogFactory.getLog(ContextPropagatingRemoteInvocation.class);
private final String principal;
private final String credentials;
/**
* Constructs the object, storing the principal and credentials extracted from the
* client-side security context.
* @param methodInvocation the method to invoke
*/
public ContextPropagatingRemoteInvocation(MethodInvocation methodInvocation) {
super(methodInvocation);
Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
if (currentUser != null) {
this.principal = currentUser.getName();
Object userCredentials = currentUser.getCredentials();
this.credentials = (userCredentials != null) ? userCredentials.toString() : null;
}
else {
this.credentials = null;
this.principal = null;
}
if (logger.isDebugEnabled()) {
logger.debug("RemoteInvocation now has principal: " + this.principal);
if (this.credentials == null) {
logger.debug("RemoteInvocation now has null credentials.");
}
}
}
/**
* Invoked on the server-side.
* <p>
* The transmitted principal and credentials will be used to create an unauthenticated
* {@code Authentication} instance for processing by the
* {@code AuthenticationManager}.
* @param targetObject the target object to apply the invocation to
* @return the invocation result
* @throws NoSuchMethodException if the method name could not be resolved
* @throws IllegalAccessException if the method could not be accessed
* @throws InvocationTargetException if the method invocation resulted in an exception
*/
@Override
public Object invoke(Object targetObject)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
if (this.principal != null) {
Authentication request = createAuthenticationRequest(this.principal, this.credentials);
request.setAuthenticated(false);
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(request);
SecurityContextHolder.setContext(context);
logger.debug(LogMessage.format("Set SecurityContextHolder to contain: %s", request));
}
try {
return super.invoke(targetObject);
}
finally {
SecurityContextHolder.clearContext();
logger.debug("Cleared SecurityContextHolder.");
}
}
/**
* Creates the server-side authentication request object.
*/
protected Authentication createAuthenticationRequest(String principal, String credentials) {
return new UsernamePasswordAuthenticationToken(principal, credentials);
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.rmi;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.remoting.support.RemoteInvocation;
import org.springframework.remoting.support.RemoteInvocationFactory;
/**
* Called by a client-side instance of
* <code>org.springframework.remoting.rmi.RmiProxyFactoryBean</code> when it wishes to
* create a remote invocation.
* <P>
* Set an instance of this bean against the above class'
* <code>remoteInvocationFactory</code> property.
* </p>
*
* @author James Monaghan
* @author Ben Alex
* @deprecated as of 5.6.0 with no replacement
*/
@Deprecated
public class ContextPropagatingRemoteInvocationFactory implements RemoteInvocationFactory {
@Override
public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) {
return new ContextPropagatingRemoteInvocation(methodInvocation);
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Enables use of Spring's RMI remoting extension points to propagate the
* <code>SecurityContextHolder</code> (which should contain an <code>Authentication</code>
* request token) from one JVM to the remote JVM.
* <p>
* The beans are wired as follows: <pre>
* &lt;bean id="test" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"&gt;
* &lt;property name="serviceUrl"&gt;&lt;value&gt;rmi://localhost/Test&lt;/value&gt;&lt;/property&gt;
* &lt;property name="serviceInterface"&gt;&lt;value&gt;test.TargetInterface&lt;/value&gt;&lt;/property&gt;
* &lt;property name="refreshStubOnConnectFailure"&gt;&lt;value&gt;true&lt;/value&gt;&lt;/property&gt;
* &lt;property name="remoteInvocationFactory"&gt;&lt;ref bean="remoteInvocationFactory"/&gt;&lt;/property&gt;
* &lt;/bean&gt;
*
* &lt;bean id="remoteInvocationFactory"
* class="org.springframework.security.remoting.rmi.ContextPropagatingRemoteInvocationFactory"/&gt;
* </pre>
*/
package org.springframework.security.remoting.rmi;

View File

@ -1,129 +0,0 @@
/*
* Copyright 2009-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.dns;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* @author Mike Wiesner
* @since 3.0
*/
public class JndiDnsResolverTests {
private JndiDnsResolver dnsResolver;
private InitialContextFactory contextFactory;
private DirContext context;
@BeforeEach
public void setup() {
this.contextFactory = mock(InitialContextFactory.class);
this.context = mock(DirContext.class);
this.dnsResolver = new JndiDnsResolver();
this.dnsResolver.setCtxFactory(this.contextFactory);
given(this.contextFactory.getCtx()).willReturn(this.context);
}
@Test
public void testResolveIpAddress() throws Exception {
Attributes records = new BasicAttributes("A", "63.246.7.80");
given(this.context.getAttributes("www.springsource.com", new String[] { "A" })).willReturn(records);
String ipAddress = this.dnsResolver.resolveIpAddress("www.springsource.com");
assertThat(ipAddress).isEqualTo("63.246.7.80");
}
@Test
public void testResolveIpAddressNotExisting() throws Exception {
given(this.context.getAttributes(any(String.class), any(String[].class)))
.willThrow(new NameNotFoundException("not found"));
assertThatExceptionOfType(DnsEntryNotFoundException.class)
.isThrownBy(() -> this.dnsResolver.resolveIpAddress("notexisting.ansdansdugiuzgguzgioansdiandwq.foo"));
}
@Test
public void testResolveServiceEntry() throws Exception {
BasicAttributes records = createSrvRecords();
given(this.context.getAttributes("_ldap._tcp.springsource.com", new String[] { "SRV" })).willReturn(records);
String hostname = this.dnsResolver.resolveServiceEntry("ldap", "springsource.com");
assertThat(hostname).isEqualTo("kdc.springsource.com");
}
@Test
public void testResolveServiceEntryNotExisting() throws Exception {
given(this.context.getAttributes(any(String.class), any(String[].class)))
.willThrow(new NameNotFoundException("not found"));
assertThatExceptionOfType(DnsEntryNotFoundException.class)
.isThrownBy(() -> this.dnsResolver.resolveServiceEntry("wrong", "secpod.de"));
}
@Test
public void testResolveServiceIpAddress() throws Exception {
BasicAttributes srvRecords = createSrvRecords();
BasicAttributes aRecords = new BasicAttributes("A", "63.246.7.80");
given(this.context.getAttributes("_ldap._tcp.springsource.com", new String[] { "SRV" })).willReturn(srvRecords);
given(this.context.getAttributes("kdc.springsource.com", new String[] { "A" })).willReturn(aRecords);
String ipAddress = this.dnsResolver.resolveServiceIpAddress("ldap", "springsource.com");
assertThat(ipAddress).isEqualTo("63.246.7.80");
}
@Test
public void resolveServiceIpAddressAndPortWhenExistsThenReturnsIpAddressAndPort() throws Exception {
BasicAttributes srvRecords = createSrvRecords();
BasicAttributes aRecords = new BasicAttributes("A", "63.246.7.80");
given(this.context.getAttributes("_ldap._tcp.springsource.com", new String[] { "SRV" })).willReturn(srvRecords);
given(this.context.getAttributes("kdc.springsource.com", new String[] { "A" })).willReturn(aRecords);
String ipAddressAndPort = this.dnsResolver.resolveServiceIpAddressAndPort("ldap", "springsource.com");
assertThat(ipAddressAndPort).isEqualTo("63.246.7.80:389");
}
@Test
public void testUnknowError() throws Exception {
given(this.context.getAttributes(any(String.class), any(String[].class)))
.willThrow(new NamingException("error"));
assertThatExceptionOfType(DnsLookupException.class).isThrownBy(() -> this.dnsResolver.resolveIpAddress(""));
}
private BasicAttributes createSrvRecords() {
BasicAttributes records = new BasicAttributes();
BasicAttribute record = new BasicAttribute("SRV");
// the structure of the service records is:
// priority weight port hostname
// for more information: https://en.wikipedia.org/wiki/SRV_record
record.add("20 80 389 kdc3.springsource.com.");
record.add("10 70 389 kdc.springsource.com.");
record.add("20 20 389 kdc4.springsource.com.");
record.add("10 30 389 kdc2.springsource.com");
records.put(record);
return records;
}
}

View File

@ -1,126 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.httpinvoker;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests {@link AuthenticationSimpleHttpInvokerRequestExecutor}.
*
* @author Ben Alex
* @author Rob Winch
*/
public class AuthenticationSimpleHttpInvokerRequestExecutorTests {
@AfterEach
public void tearDown() {
SecurityContextHolder.clearContext();
}
@Test
public void testNormalOperation() throws Exception {
// Setup client-side context
Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("Aladdin", "open sesame");
SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication);
// Create a connection and ensure our executor sets its
// properties correctly
AuthenticationSimpleHttpInvokerRequestExecutor executor = new AuthenticationSimpleHttpInvokerRequestExecutor();
HttpURLConnection conn = new MockHttpURLConnection(new URL("https://localhost/"));
executor.prepareConnection(conn, 10);
// Check connection properties
// See https://tools.ietf.org/html/rfc1945 section 11.1 for example
// we are comparing against
assertThat(conn.getRequestProperty("Authorization")).isEqualTo("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
}
@Test
public void testNullContextHolderIsNull() throws Exception {
SecurityContextHolder.getContext().setAuthentication(null);
// Create a connection and ensure our executor sets its
// properties correctly
AuthenticationSimpleHttpInvokerRequestExecutor executor = new AuthenticationSimpleHttpInvokerRequestExecutor();
HttpURLConnection conn = new MockHttpURLConnection(new URL("https://localhost/"));
executor.prepareConnection(conn, 10);
// Check connection properties (shouldn't be an Authorization header)
assertThat(conn.getRequestProperty("Authorization")).isNull();
}
// SEC-1975
@Test
public void testNullContextHolderWhenAnonymous() throws Exception {
AnonymousAuthenticationToken anonymous = new AnonymousAuthenticationToken("key", "principal",
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
SecurityContextHolder.getContext().setAuthentication(anonymous);
// Create a connection and ensure our executor sets its
// properties correctly
AuthenticationSimpleHttpInvokerRequestExecutor executor = new AuthenticationSimpleHttpInvokerRequestExecutor();
HttpURLConnection conn = new MockHttpURLConnection(new URL("https://localhost/"));
executor.prepareConnection(conn, 10);
// Check connection properties (shouldn't be an Authorization header)
assertThat(conn.getRequestProperty("Authorization")).isNull();
}
private class MockHttpURLConnection extends HttpURLConnection {
private Map<String, String> requestProperties = new HashMap<>();
MockHttpURLConnection(URL u) {
super(u);
}
@Override
public void connect() {
throw new UnsupportedOperationException("mock not implemented");
}
@Override
public void disconnect() {
throw new UnsupportedOperationException("mock not implemented");
}
@Override
public String getRequestProperty(String key) {
return this.requestProperties.get(key);
}
@Override
public void setRequestProperty(String key, String value) {
this.requestProperties.put(key, value);
}
@Override
public boolean usingProxy() {
throw new UnsupportedOperationException("mock not implemented");
}
}
}

View File

@ -1,104 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.remoting.rmi;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.security.TargetObject;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.util.SimpleMethodInvocation;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests {@link ContextPropagatingRemoteInvocation} and
* {@link ContextPropagatingRemoteInvocationFactory}.
*
* @author Ben Alex
*/
public class ContextPropagatingRemoteInvocationTests {
@AfterEach
public void tearDown() {
SecurityContextHolder.clearContext();
}
private ContextPropagatingRemoteInvocation getRemoteInvocation() throws Exception {
Class<TargetObject> clazz = TargetObject.class;
Method method = clazz.getMethod("makeLowerCase", new Class[] { String.class });
MethodInvocation mi = new SimpleMethodInvocation(new TargetObject(), method, "SOME_STRING");
ContextPropagatingRemoteInvocationFactory factory = new ContextPropagatingRemoteInvocationFactory();
return (ContextPropagatingRemoteInvocation) factory.createRemoteInvocation(mi);
}
@Test
public void testContextIsResetEvenIfExceptionOccurs() throws Exception {
// Setup client-side context
Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("rod", "koala");
SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication);
ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation();
// Set up the wrong arguments.
remoteInvocation.setArguments(new Object[] {});
assertThatIllegalArgumentException()
.isThrownBy(() -> remoteInvocation.invoke(TargetObject.class.newInstance()));
assertThat(SecurityContextHolder.getContext().getAuthentication())
.withFailMessage("Authentication must be null").isNull();
}
@Test
public void testNormalOperation() throws Exception {
// Setup client-side context
Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("rod", "koala");
SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication);
ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation();
// Set to null, as ContextPropagatingRemoteInvocation already obtained
// a copy and nulling is necessary to ensure the Context delivered by
// ContextPropagatingRemoteInvocation is used on server-side
SecurityContextHolder.clearContext();
// The result from invoking the TargetObject should contain the
// Authentication class delivered via the SecurityContextHolder
assertThat(remoteInvocation.invoke(new TargetObject())).isEqualTo(
"some_string org.springframework.security.authentication.UsernamePasswordAuthenticationToken false");
}
@Test
public void testNullContextHolderDoesNotCauseInvocationProblems() throws Exception {
SecurityContextHolder.clearContext(); // just to be explicit
ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation();
SecurityContextHolder.clearContext(); // unnecessary, but for
// explicitness
assertThat(remoteInvocation.invoke(new TargetObject())).isEqualTo("some_string Authentication empty");
}
// SEC-1867
@Test
public void testNullCredentials() throws Exception {
Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("rod", null);
SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication);
ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation();
assertThat(ReflectionTestUtils.getField(remoteInvocation, "credentials")).isNull();
}
}

View File

@ -1,15 +0,0 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.security" level="${sec.log.level:-WARN}"/>
<root level="${root.level:-WARN}">
<appender-ref ref="STDOUT" />
</root>
</configuration>