Treat URLs as String before equals/hashcode
java.net.URL performs DNS lookups whenever its equals/hashCode is used. Thus attribute values of type java.net.URL need to be converted to something else before they are used for equals/hashCode. Closes gh-10673
This commit is contained in:
parent
e28fcbfbbe
commit
ca0a6d9777
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
|
@ -16,9 +16,11 @@
|
|||
|
||||
package org.springframework.security.oauth2.core.user;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
|
@ -85,13 +87,37 @@ public class OAuth2UserAuthority implements GrantedAuthority {
|
|||
if (!this.getAuthority().equals(that.getAuthority())) {
|
||||
return false;
|
||||
}
|
||||
return this.getAttributes().equals(that.getAttributes());
|
||||
Map<String, Object> thatAttributes = that.getAttributes();
|
||||
if (getAttributes().size() != thatAttributes.size()) {
|
||||
return false;
|
||||
}
|
||||
for (Map.Entry<String, Object> e : getAttributes().entrySet()) {
|
||||
String key = e.getKey();
|
||||
Object value = convertURLIfNecessary(e.getValue());
|
||||
if (value == null) {
|
||||
if (!(thatAttributes.get(key) == null && thatAttributes.containsKey(key))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Object thatValue = convertURLIfNecessary(thatAttributes.get(key));
|
||||
if (!value.equals(thatValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.getAuthority().hashCode();
|
||||
result = 31 * result + this.getAttributes().hashCode();
|
||||
result = 31 * result;
|
||||
for (Map.Entry<String, Object> e : getAttributes().entrySet()) {
|
||||
Object key = e.getKey();
|
||||
Object value = convertURLIfNecessary(e.getValue());
|
||||
result += Objects.hashCode(key) ^ Objects.hashCode(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -100,4 +126,12 @@ public class OAuth2UserAuthority implements GrantedAuthority {
|
|||
return this.getAuthority();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code URL} converted to a string since {@code URL} shouldn't be used for
|
||||
* equality/hashCode. For other instances the value is returned as is.
|
||||
*/
|
||||
private static Object convertURLIfNecessary(Object value) {
|
||||
return (value instanceof URL) ? ((URL) value).toExternalForm() : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.security.oauth2.core.user;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -35,6 +37,22 @@ public class OAuth2UserAuthorityTests {
|
|||
|
||||
private static final Map<String, Object> ATTRIBUTES = Collections.singletonMap("username", "test");
|
||||
|
||||
private static final OAuth2UserAuthority AUTHORITY_WITH_OBJECTURL;
|
||||
|
||||
private static final OAuth2UserAuthority AUTHORITY_WITH_STRINGURL;
|
||||
|
||||
static {
|
||||
try {
|
||||
AUTHORITY_WITH_OBJECTURL = new OAuth2UserAuthority(
|
||||
Collections.singletonMap("someurl", new URL("https://localhost")));
|
||||
AUTHORITY_WITH_STRINGURL = new OAuth2UserAuthority(
|
||||
Collections.singletonMap("someurl", "https://localhost"));
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenAuthorityIsNullThenThrowIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new OAuth2UserAuthority(null, ATTRIBUTES));
|
||||
|
@ -58,4 +76,22 @@ public class OAuth2UserAuthorityTests {
|
|||
assertThat(userAuthority.getAttributes()).isEqualTo(ATTRIBUTES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsRegardlessOfUrlType() {
|
||||
assertThat(AUTHORITY_WITH_OBJECTURL).isEqualTo(AUTHORITY_WITH_OBJECTURL);
|
||||
assertThat(AUTHORITY_WITH_STRINGURL).isEqualTo(AUTHORITY_WITH_STRINGURL);
|
||||
|
||||
assertThat(AUTHORITY_WITH_OBJECTURL).isEqualTo(AUTHORITY_WITH_STRINGURL);
|
||||
assertThat(AUTHORITY_WITH_STRINGURL).isEqualTo(AUTHORITY_WITH_OBJECTURL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hashCodeIsSameRegardlessOfUrlType() {
|
||||
assertThat(AUTHORITY_WITH_OBJECTURL.hashCode()).isEqualTo(AUTHORITY_WITH_OBJECTURL.hashCode());
|
||||
assertThat(AUTHORITY_WITH_STRINGURL.hashCode()).isEqualTo(AUTHORITY_WITH_STRINGURL.hashCode());
|
||||
|
||||
assertThat(AUTHORITY_WITH_OBJECTURL.hashCode()).isEqualTo(AUTHORITY_WITH_STRINGURL.hashCode());
|
||||
assertThat(AUTHORITY_WITH_STRINGURL.hashCode()).isEqualTo(AUTHORITY_WITH_OBJECTURL.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue